From eb9827a3aec8a9a4904eb106b92ca8f669ed1ba4 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 14 Dec 2017 16:48:03 -0600 Subject: [PATCH] more fixes for i18n --- config.js | 4 +++ middleware/i18n.js | 6 +++++ routes/index.js | 13 ++++----- services/i18n.js | 66 +++++++++++++++++++++------------------------- 4 files changed, 47 insertions(+), 42 deletions(-) create mode 100644 middleware/i18n.js diff --git a/config.js b/config.js index e14997be9..d3a6344cc 100644 --- a/config.js +++ b/config.js @@ -23,6 +23,10 @@ const CONFIG = { // EMAIL_SUBJECT_PREFIX is the string before emails in the subject. EMAIL_SUBJECT_PREFIX: process.env.TALK_EMAIL_SUBJECT_PREFIX || '[Talk]', + // DEFAULT_LANG is the default language used for server sent emails and + // rendered text. + DEFAULT_LANG: process.env.TALK_DEFAULT_LANG || 'en', + // When TRUE, it ensures that database indexes created in core will not add // indexes. CREATE_MONGO_INDEXES: process.env.DISABLE_CREATE_MONGO_INDEXES !== 'TRUE', diff --git a/middleware/i18n.js b/middleware/i18n.js new file mode 100644 index 000000000..c2ca2436a --- /dev/null +++ b/middleware/i18n.js @@ -0,0 +1,6 @@ +const i18n = require('../services/i18n'); + +module.exports = (req, res, next) => { + res.locals.t = i18n.request(req); + next(); +}; diff --git a/routes/index.js b/routes/index.js index 0ee012a79..a769d6b6f 100644 --- a/routes/index.js +++ b/routes/index.js @@ -7,7 +7,7 @@ const debug = require('debug')('talk:routes'); const enabled = require('debug').enabled; const errors = require('../errors'); const express = require('express'); -const i18n = require('../services/i18n'); +const i18n = require('../middleware/i18n'); const path = require('path'); const plugins = require('../services/plugins'); const pubsub = require('../middleware/pubsub'); @@ -64,6 +64,9 @@ if (!DISABLE_STATIC_SERVER) { router.get('/embed.js.map', serveFile('../dist/embed.js.map')); } +// Add the i18n middleware to all routes. +router.use(i18n); + //============================================================================== // STATIC ROUTES //============================================================================== @@ -116,19 +119,19 @@ if (process.env.NODE_ENV !== 'production') { }); }); - // GraphQL documention. + // GraphQL documentation. router.get('/admin/docs', (req, res) => { res.render('admin/docs'); }); } +router.use('/api/v1', require('./api')); + //============================================================================== // ROUTES //============================================================================== -router.use('/api/v1', require('./api')); - // Development routes. if (process.env.NODE_ENV !== 'production') { router.use('/assets', staticTemplate, require('./assets')); @@ -184,8 +187,6 @@ router.use('/', (err, req, res, next) => { console.error(err); } - i18n.init(req); - if (err instanceof errors.APIError) { res.status(err.status); res.render('error', { diff --git a/services/i18n.js b/services/i18n.js index 338f6680a..cd1bacd93 100644 --- a/services/i18n.js +++ b/services/i18n.js @@ -5,6 +5,7 @@ const accepts = require('accepts'); const _ = require('lodash'); const yaml = require('yamljs'); const plugins = require('./plugins'); +const {DEFAULT_LANG} = require('../config'); const resolve = (...paths) => path.resolve(path.join(__dirname, '..', 'locales', ...paths)); @@ -31,9 +32,6 @@ let translations = fs.readdirSync(resolve()) // Create a list of all supported translations. const languages = Object.keys(translations); -let defaultLanguage = process.env.TALK_DEFAULT_LANG || 'en'; -let language = defaultLanguage; - let loadedPluginTranslations = false; const loadPluginTranslations = () => { if (loadedPluginTranslations) { @@ -52,46 +50,42 @@ const loadPluginTranslations = () => { loadedPluginTranslations = true; }; +const t = (language) => (key, ...replacements) => { + + // Loads the translations into the translations array from plugins. This is + // done lazily to ensure that we don't have an import cycle. + loadPluginTranslations(); + + // Check if the translation exists on the object. + if (_.has(translations[language], key)) { + + // Get the translation value. + let translation = _.get(translations[language], key); + + // Replace any {n} with the arguments passed to this method. + replacements.forEach((str, n) => { + translation = translation.replace(new RegExp(`\\{${n}\\}`, 'g'), str); + }); + + return translation; + } else { + console.warn(`${key} language key not set`); + return key; + } +}; + /** * Exposes a service object to allow translations. * @type {Object} */ const i18n = { - - /** - * Create the new Task kue. - */ - init(req) { + request(req) { const lang = accepts(req).language(languages); - language = lang ? lang : defaultLanguage; - }, - - /** - * Translates a key. - */ - t(key, ...replacements) { - - // Loads the translations into the translations array from plugins. This is - // done lazily to ensure that we don't have an import cycle. - loadPluginTranslations(); - - // Check if the translation exists on the object. - if (_.has(translations[language], key)) { - - // Get the translation value. - let translation = _.get(translations[language], key); - - // Replace any {n} with the arguments passed to this method. - replacements.forEach((str, n) => { - translation = translation.replace(new RegExp(`\\{${n}\\}`, 'g'), str); - }); - - return translation; - } else { - console.warn(`${key} language key not set`); - return key; - } + const language = lang ? lang : DEFAULT_LANG; + + return t(language); }, + t: t(DEFAULT_LANG), }; module.exports = i18n;