mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-22 18:31:57 +03:00
114 lines
3.7 KiB
JavaScript
114 lines
3.7 KiB
JavaScript
|
const {i18n, events, logging, errors} = require('../../../server/lib/common');
|
||
|
const settingsCache = require('../../../server/services/settings/cache');
|
||
|
const config = require('../../../server/config');
|
||
|
|
||
|
const jp = require('jsonpath');
|
||
|
|
||
|
const isNil = require('lodash/isNil');
|
||
|
|
||
|
class ThemeI18n extends i18n.I18n {
|
||
|
constructor(locale) {
|
||
|
super(locale);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Setup i18n support for themes:
|
||
|
* - Load correct language file into memory
|
||
|
*/
|
||
|
init() {
|
||
|
// This function is called during theme initialization, and when switching language or theme.
|
||
|
const currentLocale = this._loadLocale();
|
||
|
const activeTheme = settingsCache.get('active_theme');
|
||
|
|
||
|
// 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, currentLocale);
|
||
|
|
||
|
if (!this._strings && currentLocale !== 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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Load the current locale out of the settings cache
|
||
|
*/
|
||
|
_loadLocale() {
|
||
|
this._locale = settingsCache.get('default_locale');
|
||
|
return this._locale;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Do the lookup with JSON path
|
||
|
*
|
||
|
* @param {String} msgPath
|
||
|
*/
|
||
|
_getCandidateString(msgPath) {
|
||
|
// Both jsonpath's dot-notation and bracket-notation start with '$'
|
||
|
// E.g.: $.store.book.title or $['store']['book']['title']
|
||
|
// The {{t}} translation helper passes the default English text
|
||
|
// The full Unicode jsonpath with '$' is built here
|
||
|
// jp.stringify and jp.value are jsonpath methods
|
||
|
// Info: https://www.npmjs.com/package/jsonpath
|
||
|
let path = jp.stringify(['$', msgPath]);
|
||
|
return jp.value(this._strings, path) || msgPath;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let themeI18n = new ThemeI18n();
|
||
|
|
||
|
// /**
|
||
|
// * When active theme changes, we reload theme translations
|
||
|
// * We listen on the service event, because of the following known case:
|
||
|
// * 1. you override a theme, which is already active
|
||
|
// * 2. The data has not changed, no event is triggered.
|
||
|
// */
|
||
|
events.on('services.themes.activated', function () {
|
||
|
themeI18n.init();
|
||
|
});
|
||
|
|
||
|
/**
|
||
|
* When locale changes, we reload theme translations
|
||
|
*/
|
||
|
events.on('settings.default_locale.edited', function () {
|
||
|
themeI18n.init();
|
||
|
});
|
||
|
|
||
|
module.exports = themeI18n;
|