diff --git a/server/core/localization.js b/server/core/localization.js index 36ef8104..dd735b68 100644 --- a/server/core/localization.js +++ b/server/core/localization.js @@ -17,10 +17,22 @@ module.exports = { ns: this.namespaces, defaultNS: 'common', saveMissing: false, - preload: [WIKI.config.site.lang], lng: WIKI.config.site.lang, fallbackLng: 'en' }) + + // Load fallback defaults + const enFallback = require('../locales/default.json') + if (_.isPlainObject(enFallback)) { + _.forOwn(enFallback, (data, ns) => { + this.namespaces.push(ns) + this.engine.addResourceBundle('en', ns, data) + }) + } + + // Load current language + this.loadLocale(WIKI.config.site.lang, { silent: true }) + return this }, attachMiddleware (app) { @@ -39,10 +51,22 @@ module.exports = { throw new Error('Invalid locale or namespace') } }, - async loadLocale(locale) { - return Promise.fromCallback(cb => { - return this.engine.loadLanguages(locale, cb) + async loadLocale(locale, opts = { silent: false }) { + const res = await WIKI.db.Locale.findOne({ + where: { + code: locale + } }) + if (res) { + if (_.isPlainObject(res.strings)) { + _.forOwn(res.strings, (data, ns) => { + this.namespaces.push(ns) + this.engine.addResourceBundle(locale, ns, data, true, true) + }) + } + } else if (!opts.silent) { + throw new Error('No such locale in local store.') + } }, async setCurrentLocale(locale) { return Promise.fromCallback(cb => { diff --git a/server/graph/resolvers/localization.js b/server/graph/resolvers/localization.js index 5505f2b5..2a849dc3 100644 --- a/server/graph/resolvers/localization.js +++ b/server/graph/resolvers/localization.js @@ -28,6 +28,12 @@ module.exports = { installDate: isInstalled ? _.find(localLocales, ['code', rl.code]).updatedAt : null } }) + }, + async config(obj, args, context, info) { + return { + locale: WIKI.config.site.lang, + autoUpdate: WIKI.config.site.langAutoUpdate + } } }, LocalizationMutation: { diff --git a/server/graph/schemas/localization.graphql b/server/graph/schemas/localization.graphql index eabd7b8d..967e08c1 100644 --- a/server/graph/schemas/localization.graphql +++ b/server/graph/schemas/localization.graphql @@ -16,6 +16,7 @@ extend type Mutation { type LocalizationQuery { locales: [LocalizationLocale] + config: LocalizationConfig } # ----------------------------------------------- @@ -43,3 +44,8 @@ type LocalizationLocale { nativeName: String! updatedAt: Date! } + +type LocalizationConfig { + locale: String! + autoUpdate: Boolean! +} diff --git a/server/jobs/sync-graph-locales.js b/server/jobs/sync-graph-locales.js index 45eb5367..c14759f3 100644 --- a/server/jobs/sync-graph-locales.js +++ b/server/jobs/sync-graph-locales.js @@ -5,6 +5,8 @@ const { createApolloFetch } = require('apollo-fetch') /* global WIKI */ WIKI.redis = require('../core/redis').init() +WIKI.db = require('../core/db').init() + const apollo = createApolloFetch({ uri: 'https://graph.requarks.io' }) @@ -13,7 +15,11 @@ module.exports = async (job) => { WIKI.logger.info('Syncing locales with Graph endpoint...') try { - const resp = await apollo({ + await WIKI.configSvc.loadFromDb(['site']) + + // -> Fetch locales list + + const respList = await apollo({ query: `{ localization { locales { @@ -27,8 +33,38 @@ module.exports = async (job) => { } }` }) - const locales = _.sortBy(_.get(resp, 'data.localization.locales', []), 'name').map(lc => ({...lc, isInstalled: (lc.code === 'en')})) + const locales = _.sortBy(_.get(respList, 'data.localization.locales', []), 'name').map(lc => ({...lc, isInstalled: (lc.code === 'en')})) WIKI.redis.set('locales', JSON.stringify(locales)) + const currentLocale = _.find(locales, ['code', WIKI.config.site.lang]) + + // -> Download locale strings + + if (WIKI.config.site.langAutoUpdate) { + const respStrings = await apollo({ + query: `{ + localization { + strings(code: "${WIKI.config.site.lang}") { + key + value + } + } + }` + }) + const strings = _.get(respStrings, 'data.localization.strings', []) + let lcObj = {} + _.forEach(strings, row => { + if (_.includes(row.key, '::')) { return } + _.set(lcObj, row.key.replace(':', '.'), row.value) + }) + + WIKI.db.Locale.upsert({ + code: WIKI.config.site.lang, + strings: lcObj, + isRTL: currentLocale.isRTL, + name: currentLocale.name, + nativeName: currentLocale.nativeName + }) + } WIKI.logger.info('Syncing locales with Graph endpoint: [ COMPLETED ]') } catch (err) { diff --git a/server/setup.js b/server/setup.js index 0aff3380..c06df4e8 100644 --- a/server/setup.js +++ b/server/setup.js @@ -284,7 +284,8 @@ module.exports = () => { // Site namespace _.set(WIKI.config.site, 'title', req.body.title) _.set(WIKI.config.site, 'lang', 'en') - _.set(WIKI.config.site, 'rtl', _.includes(WIKI.data.rtlLangs, req.body.lang)) + _.set(WIKI.config.site, 'langAutoUpdate', true) + _.set(WIKI.config.site, 'rtl', false) _.set(WIKI.config.site, 'sessionSecret', (await crypto.randomBytesAsync(32)).toString('hex')) // Auth namespace