Files
talk/services/i18n.js
T
2017-12-21 23:26:34 -07:00

103 lines
2.8 KiB
JavaScript

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');
const {DEFAULT_LANG} = require('../config');
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);
// Move the default language to the front.
if (languages.includes(DEFAULT_LANG)) {
const from = languages.indexOf(DEFAULT_LANG);
languages.splice(from, 1);
languages.splice(0, 0, DEFAULT_LANG);
}
debug(`loaded language sets for ${languages}`);
let loadedPluginTranslations = false;
const loadPluginTranslations = () => {
if (loadedPluginTranslations) {
return;
}
// Load the plugin translations.
plugins.get('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;
};
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 = {
request(req) {
debug(`possible languages given request '${accepts(req).languages()}'`);
const lang = accepts(req).language(languages);
debug(`parsed request language as '${lang}'`);
const language = lang ? lang : DEFAULT_LANG;
debug(`decided language as '${language}'`);
return t(language);
},
t: t(DEFAULT_LANG),
};
module.exports = i18n;