diff --git a/services/i18n.js b/services/i18n.js index 4c65ed1d4..9d74ec0e4 100644 --- a/services/i18n.js +++ b/services/i18n.js @@ -1,22 +1,56 @@ -const has = require('lodash/has'); -const get = require('lodash/get'); - -const yaml = require('yamljs'); - -const da = yaml.load('./locales/da.yml'); -const es = yaml.load('./locales/es.yml'); -const en = yaml.load('./locales/en.yml'); -const fr = yaml.load('./locales/fr.yml'); -const pt_BR = yaml.load('./locales/pt_BR.yml'); - +const fs = require('fs'); +const path = require('path'); +const debug = require('debug')('talk:services:i18n'); const accepts = require('accepts'); +const _ = require('lodash'); +const yaml = require('yamljs'); +const plugins = require('./plugins'); -// default language -let defaultLanguage = 'en'; +const resolve = (...paths) => path.resolve(path.join(__dirname, '..', 'locales', ...paths)); + +// Load all the translations. +let translations = fs.readdirSync(resolve()) + + // Resolve all the filenames relative the the locales directory. + .map((filename) => resolve(filename)) + + // Translations are only yml/yaml files. + .filter((filename) => /\.(yaml|yml)$/.test(filename)) + + // Load the translation files from disk. + .map((filename) => fs.readFileSync(filename, 'utf8')) + + // Load the translation files. + .reduce((packs, contents) => { + + const pack = yaml.parse(contents); + + return _.merge(packs, pack); + }, {}); + +// Create a list of all supported translations. +const languages = Object.keys(translations); + +let defaultLanguage = process.env.TALK_DEFAULT_LANG || 'en'; let language = defaultLanguage; -const languages = ['en', 'da', 'es', 'fr', 'pt_BR']; -const translations = Object.assign(en, es, fr, pt_BR, da); +let loadedPluginTranslations = false; +const loadPluginTranslations = () => { + if (loadedPluginTranslations) { + return; + } + + // Load the plugin translations. + plugins.forEach('server', 'translations').forEach(({plugin, translations: filename}) => { + debug(`added plugin '${plugin.name}'`); + + const pack = yaml.parse(fs.readFileSync(filename, 'utf8')); + + translations = _.merge(translations, pack); + }); + + loadedPluginTranslations = true; +}; /** * Exposes a service object to allow translations. @@ -28,6 +62,11 @@ const i18n = { * Create the new Task kue. */ init(req) { + + // Loads the translations into the translations array from plugins. This is + // done lazily to ensure that we don't have an import cycle. + loadPluginTranslations(); + const lang = accepts(req).language(languages); language = lang ? lang : defaultLanguage; }, @@ -37,13 +76,15 @@ const i18n = { */ t(key, ...replacements) { - if (has(translations[language], key)) { + // Check if the translation exists on the object. + if (_.has(translations[language], key)) { - let translation = get(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, i) => { - translation = translation.replace(new RegExp(`\\{${i}\\}`, 'g'), str); + // Replace any {n} with the arguments passed to this method. + replacements.forEach((str, n) => { + translation = translation.replace(new RegExp(`\\{${n}\\}`, 'g'), str); }); return translation;