Skip to content

Commit

Permalink
Made i18n more tolerant of missing files (#21561)
Browse files Browse the repository at this point in the history
no ref

This fix adds an extra fallback to 'en' when a locale folder is missing one or more translation files, and a test for the fallback. Previously, Ghost would fail to boot if an expected file translation was missing.
  • Loading branch information
cathysarisky authored Nov 21, 2024
1 parent 3abff38 commit a31afd4
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 10 deletions.
34 changes: 24 additions & 10 deletions ghost/i18n/lib/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,26 @@ const SUPPORTED_LOCALES = [
'ta' // Tamil
];

function generateResources(locales, ns) {
return locales.reduce((acc, locale) => {
let res;
// add an extra fallback - this handles the case where we have a partial set of translations for some reason
// by falling back to the english translations
try {
res = require(`../locales/${locale}/${ns}.json`);
} catch (err) {
res = require(`../locales/en/${ns}.json`);
}

// Note: due some random thing in TypeScript, 'requiring' a JSON file with a space in a key name, only adds it to the default export
// If changing this behaviour, please also check the comments and signup-form apps in another language (mainly sentences with a space in them)
acc[locale] = {
[ns]: {...res, ...(res.default && typeof res.default === 'object' ? res.default : {})}
};
return acc;
}, {});
}

/**
* @param {string} [lng]
* @param {'ghost'|'portal'|'test'|'signup-form'|'comments'|'search'|'newsletter'} ns
Expand All @@ -75,6 +95,8 @@ module.exports = (lng = 'en', ns = 'portal') => {
suffix: '}'
};
}

let resources = generateResources(SUPPORTED_LOCALES, ns);
i18nextInstance.init({
lng,

Expand All @@ -94,19 +116,11 @@ module.exports = (lng = 'en', ns = 'portal') => {
// separators
interpolation,

resources: SUPPORTED_LOCALES.reduce((acc, locale) => {
const res = require(`../locales/${locale}/${ns}.json`);

// Note: due some random thing in TypeScript, 'requiring' a JSON file with a space in a key name, only adds it to the default export
// If changing this behaviour, please also check the comments and signup-form apps in another language (mainly sentences with a space in them)
acc[locale] = {
[ns]: {...res, ...(res.default && typeof res.default === 'object' ? res.default : {})}
};
return acc;
}, {})
resources
});

return i18nextInstance;
};

module.exports.SUPPORTED_LOCALES = SUPPORTED_LOCALES;
module.exports.generateResources = generateResources;
7 changes: 7 additions & 0 deletions ghost/i18n/test/i18n.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,11 @@ describe('i18n', function () {
assert.equal(t('Your subscription will renew on {date}.', {date: '8 Oct 2024'}), 'Votre abonnement sera renouvelé le 8 Oct 2024.');
});
});
describe('it gracefully falls back to en if a file is missing', function () {
it('should be able to translate a key that is missing in the locale', async function () {
const resources = i18n.generateResources(['xx'], 'portal');
const englishResources = i18n.generateResources(['en'], 'portal');
assert.deepEqual(resources.xx, englishResources.en);
});
});
});

0 comments on commit a31afd4

Please sign in to comment.