Ghost/core/frontend/services/theme-engine/i18n/i18n.js
Hannah Wolfe 9ce407966f Improved theme locale handling
- when activating a theme, we need to load the current locale
- this request used to be buried deep in the themeI18n init call
- now we surface it in the bridge and pass it down, which is closer to what we want to do with eventually initialising the frontend
with everything it needs up front (or not initialising it, if it isn't needed)

- in the related helpers we depend on the site.locale value instead of proxy -> themeI18n -> settingsCache drastically simplifying the code and removing deep requires
- site.locale is updated via middleware and can be relied upon
2021-05-05 16:13:26 +01:00

73 lines
2.5 KiB
JavaScript

const errors = require('@tryghost/errors');
const i18n = require('../../../../shared/i18n');
const logging = require('../../../../shared/logging');
const config = require('../../../../shared/config');
const isNil = require('lodash/isNil');
class ThemeI18n extends i18n.I18n {
constructor(options = {}) {
super(options);
// We don't care what gets passed in, themes use fulltext mode
this._stringMode = 'fulltext';
}
/**
* Setup i18n support for themes:
* - Load correct language file into memory
*
* @param {String} activeTheme - name of the currently loaded theme
*/
init({activeTheme, locale}) {
// This function is called during theme initialization, and when switching language or theme.
this._locale = locale || this._locale;
// Reading file for current locale and active theme and keeping its content in memory
if (activeTheme) {
// Reading translation file for theme .hbs templates.
// Compatibility with both old themes and i18n-capable themes.
// Preventing missing files.
this._strings = this._tryGetLocale(activeTheme, this._locale);
if (!this._strings && this._locale !== this.defaultLocale()) {
logging.warn(`Falling back to locales/${this.defaultLocale()}.json.`);
this._strings = this._tryGetLocale(activeTheme, this.defaultLocale());
}
}
if (isNil(this._strings)) {
// even if empty, themeStrings must be an object for jp.value
this._strings = {};
}
this._initializeIntl();
}
/**
* Attempt to load a local file and parse the contents
*
* @param {String} activeTheme
* @param {String} locale
*/
_tryGetLocale(activeTheme, locale) {
try {
return this._readStringsFile(config.getContentPath('themes'), activeTheme, 'locales', `${locale}.json`);
} catch (err) {
if (err.code === 'ENOENT') {
if (locale !== this.defaultLocale()) {
logging.warn(`Theme's file locales/${locale}.json not found.`);
}
} else if (err instanceof SyntaxError) {
logging.error(new errors.IncorrectUsageError({
err,
message: `Unable to parse locales/${locale}.json. Please check that it is valid JSON.`
}));
} else {
throw err;
}
}
}
}
module.exports = ThemeI18n;