UNPKG

i18n-llm-translate

Version:

Automatically translates namespace-based JSON translation files across multiple languages from any source language

140 lines (139 loc) 7.36 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.readTranslationsCache = readTranslationsCache; const util_1 = require("./util"); const logger_1 = require("./logger"); const fs_1 = require("fs"); const path_1 = __importDefault(require("path")); function readTranslationsCache(options) { return __awaiter(this, void 0, void 0, function* () { const logger = options.logger || logger_1.defaultLogger; const baseLanguageCodeKey = (0, util_1.formatLanguageContainerDirectoryName)(options.baseLanguageCode, options); const cachePath = path_1.default.resolve(process.env.PWD, options.languagesDirectoryPath, options.namesMapping.jsonCache); let cache = '{}'; try { cache = yield fs_1.promises.readFile(cachePath, 'utf-8'); } catch (_a) { logger.warn(`"${cachePath}" not found. Initializing empty JSON.`); } try { cache = JSON.parse(cache); } catch (_b) { logger.error(`Error reading "${cachePath}". File is not a proper JSON!`); } return { cache, cleanCache(namespaces) { let dirty = false; const namespaceFiles = namespaces.map(n => n.jsonFileName); for (let cachedFile in cache) { if (!namespaceFiles.includes(cachedFile)) { logger.warn(`Namespace file "${cachedFile}" not found. Clearing it from cache`); delete cache[cachedFile]; dirty = true; } } return dirty; }, syncCacheWithNamespaces(namespaces, writeNamespaceValues) { function deepCopy(obj) { return JSON.parse(JSON.stringify(obj)); } function walk(cache, baseTranslations, targetLanguagesTranslations) { // Remove keys which are no longer at base translations if (typeof baseTranslations === 'object') for (let cacheKey in cache) { if (cacheKey in baseTranslations) { continue; } delete cache[cacheKey]; logger.verbose(`Cache: Removed unknown base path key: "${cacheKey}"`); } for (let baseKey in baseTranslations) { const baseValue = baseTranslations[baseKey]; const isTranslation = typeof baseValue === 'string'; let cacheValue = cache[baseKey] || {}; if (isTranslation) { // Remove unknown languages for (let languageCode of Object.keys(cacheValue)) { if (languageCode !== baseLanguageCodeKey && !options.targetLanguageCodes.includes(languageCode)) { delete cacheValue[languageCode]; logger.verbose(`Cache: Removed unknown language code: "${languageCode}" in "${baseKey}"`); } } cacheValue[baseLanguageCodeKey] = writeNamespaceValues ? baseValue : cacheValue[baseLanguageCodeKey] || ''; for (let targetLanguage of targetLanguagesTranslations) { cacheValue[targetLanguage.languageCode] = writeNamespaceValues ? targetLanguage.translations[baseKey] || '' : cacheValue[targetLanguage.languageCode] || ''; } } else { const deeperTargetLanguages = deepCopy(targetLanguagesTranslations); for (let deeperTargetLanguage of deeperTargetLanguages) { deeperTargetLanguage.translations = deeperTargetLanguage.translations[baseKey] || {}; } cacheValue = walk(cacheValue, baseValue, deeperTargetLanguages); } cache[baseKey] = cacheValue; } return cache; } for (let namespace of namespaces) { const cacheNamespace = cache[namespace.jsonFileName] || {}; cache[namespace.jsonFileName] = walk(cacheNamespace, deepCopy(namespace.baseLanguageTranslations), deepCopy(namespace.targetLanguages)); } }, getBaseLanguageTranslationDifferences(namespace) { const fileCache = cache[namespace.jsonFileName]; if (!fileCache) return namespace.baseLanguageTranslations; function walk(cache, baseTranslations) { var _a; if (typeof baseTranslations !== 'object') { return cache; } const diff = {}; for (const key of Object.keys(baseTranslations)) { if (typeof baseTranslations[key] === "object") { const result = walk(cache[key], baseTranslations[key]); if (result) diff[key] = result; continue; } if (baseTranslations[key] === ((_a = cache[key]) === null || _a === void 0 ? void 0 : _a[baseLanguageCodeKey])) { continue; } diff[key] = baseTranslations[key]; } if (Object.keys(diff).length === 0) return undefined; return diff; } return walk(fileCache, namespace.baseLanguageTranslations); }, write() { return __awaiter(this, void 0, void 0, function* () { yield fs_1.promises.writeFile(cachePath, JSON.stringify(cache, null, 4), 'utf-8'); logger.verbose(`Successfully wrote translations cache`); }); }, }; }); }