"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAllTranslations = getAllTranslations; exports.getAllTranslationsFromPaths = getAllTranslationsFromPaths; exports.getRegisteredLocales = getRegisteredLocales; exports.getTranslationsByLocale = getTranslationsByLocale; exports.registerTranslationFile = registerTranslationFile; exports.registerTranslationFiles = registerTranslationFiles; var fs = _interopRequireWildcard(require("fs")); var path = _interopRequireWildcard(require("path")); var _util = require("util"); var _helper = require("./core/helper"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ const TRANSLATION_FILE_EXTENSION = '.json'; /** * Internal property for storing registered translations paths. * Key is locale, value is array of registered paths */ const translationsRegistry = {}; /** * Internal property for caching loaded translations files. * Key is path to translation file, value is object with translation messages */ const loadedFiles = {}; /** * Returns locale by the given translation file name * @param fullFileName * @returns locale * @example * getLocaleFromFileName('./path/to/translation/ru.json') // => 'ru' */ function getLocaleFromFileName(fullFileName) { if (!fullFileName) { throw new Error('Filename is empty'); } const fileExt = path.extname(fullFileName); if (fileExt !== TRANSLATION_FILE_EXTENSION) { throw new Error(`Translations must have 'json' extension. File being registered is ${fullFileName}`); } return path.basename(fullFileName, TRANSLATION_FILE_EXTENSION); } /** * Loads file and parses it as JSON * @param pathToFile * @returns */ async function loadFile(pathToFile) { // doing this at the moment because fs is mocked in a lot of places where this would otherwise fail return JSON.parse(await (0, _util.promisify)(fs.readFile)(pathToFile, 'utf8')); } /** * Loads translations files and adds them into "loadedFiles" cache * @param files * @returns */ async function loadAndCacheFiles(files) { const translations = await Promise.all(files.map(loadFile)); files.forEach((file, index) => { loadedFiles[file] = translations[index]; }); } /** * Registers translation file with i18n loader * @param translationFilePath - Absolute path to the translation file to register. */ function registerTranslationFile(translationFilePath) { if (!path.isAbsolute(translationFilePath)) { throw new TypeError('Paths to translation files must be absolute. ' + `Got relative path: "${translationFilePath}"`); } const locale = getLocaleFromFileName(translationFilePath); translationsRegistry[locale] = (0, _helper.unique)([...(translationsRegistry[locale] || []), translationFilePath]); } /** * Registers array of translation files with i18n loader * @param arrayOfPaths - Array of absolute paths to the translation files to register. */ function registerTranslationFiles(arrayOfPaths = []) { arrayOfPaths.forEach(registerTranslationFile); } /** * Returns an array of locales that have been registered with i18n loader * @returns registeredTranslations */ function getRegisteredLocales() { return Object.keys(translationsRegistry); } /** * Returns translation messages by specified locale * @param locale * @returns translation messages */ async function getTranslationsByLocale(locale) { const files = translationsRegistry[locale] || []; const notLoadedFiles = files.filter(file => !loadedFiles[file]); if (notLoadedFiles.length) { await loadAndCacheFiles(notLoadedFiles); } if (!files.length) { return { messages: {} }; } return files.reduce((translation, file) => ({ locale: loadedFiles[file].locale || translation.locale, formats: loadedFiles[file].formats || translation.formats, messages: { ...loadedFiles[file].messages, ...translation.messages } }), { locale, messages: {} }); } /** * Returns all translations for registered locales * @returns A Promise object * where keys are the locale and values are objects of translation messages */ async function getAllTranslations() { const locales = getRegisteredLocales(); const translations = await Promise.all(locales.map(getTranslationsByLocale)); return locales.reduce((acc, locale, index) => ({ ...acc, [locale]: translations[index] }), {}); } /** * Registers passed translations files, loads them and returns promise with * all translation messages * @param paths - Array of absolute paths to the translation files * @returns A Promise object where * keys are the locale and values are objects of translation messages */ async function getAllTranslationsFromPaths(paths) { registerTranslationFiles(paths); return await getAllTranslations(); }