UNPKG

@scoutello/i18n-magic

Version:

Intelligent CLI toolkit that automates internationalization workflows for JavaScript/TypeScript projects and auto-translates new string keys to other languages

109 lines 4.99 kB
import { getKeysWithNamespaces, getPureKey, getTextInput, loadLocalesFile, translateKey, writeLocalesFile, } from "../lib/utils.js"; const getKeyToReplace = async (allAvailableKeys) => { const keyToReplace = await getTextInput("Enter the key to replace the translation for: "); if (!allAvailableKeys[keyToReplace]) { console.log(`The key "${keyToReplace}" does not exist.`); return await getKeyToReplace(allAvailableKeys); } const namespaces = allAvailableKeys[keyToReplace].map((k) => k.namespace); console.log(`The key "${keyToReplace}" exists in namespaces: ${namespaces.join(", ")}.`); return { key: keyToReplace, namespaces }; }; export const replaceTranslation = async (config, key) => { const { loadPath, savePath, defaultLocale, defaultNamespace, namespaces, locales, globPatterns, context, openai, } = config; // Find all keys with their namespaces from the codebase const keysWithNamespaces = await getKeysWithNamespaces({ globPatterns, defaultNamespace, }); // Build a map of all available keys across all namespaces const allAvailableKeys = {}; const namespaceKeysResults = await Promise.all(namespaces.map(async (namespace) => ({ namespace, keys: await loadLocalesFile(loadPath, defaultLocale, namespace), }))); for (const { namespace, keys } of namespaceKeysResults) { for (const [keyName, value] of Object.entries(keys)) { if (!allAvailableKeys[keyName]) { allAvailableKeys[keyName] = []; } allAvailableKeys[keyName].push({ namespace, value }); } } let keyToReplace; let targetNamespaces = []; if (key) { if (allAvailableKeys[key]) { keyToReplace = key; // Determine which namespaces this key should be updated in based on usage const keyUsage = keysWithNamespaces.filter((k) => { const pureKey = getPureKey(k.key, defaultNamespace, true); return pureKey === key || k.key === key; }); if (keyUsage.length > 0) { // Use namespaces from actual usage const allNamespaces = []; for (const k of keyUsage) { allNamespaces.push(...k.namespaces); } targetNamespaces = [...new Set(allNamespaces)]; } else { // Fallback to all namespaces where the key exists targetNamespaces = allAvailableKeys[key].map((k) => k.namespace); } console.log(`The key "${keyToReplace}" exists in namespaces: ${targetNamespaces.join(", ")}.`); } else { console.log(`The key "${key}" does not exist.`); const result = await getKeyToReplace(allAvailableKeys); keyToReplace = result.key; targetNamespaces = result.namespaces; } } else { const result = await getKeyToReplace(allAvailableKeys); keyToReplace = result.key; targetNamespaces = result.namespaces; } // Show current translations across namespaces const currentTranslations = await Promise.all(targetNamespaces.map(async (namespace) => { const keys = await loadLocalesFile(loadPath, defaultLocale, namespace); return { namespace, value: keys[keyToReplace] }; })); for (const { namespace, value } of currentTranslations) { if (value) { console.log(`Current translation in ${defaultLocale} (${namespace}): "${value}"`); } } const newTranslation = await getTextInput("Enter the new translation: "); // Batch translate for all non-default locales first const translationCache = { [defaultLocale]: newTranslation, }; const nonDefaultLocales = locales.filter((l) => l !== defaultLocale); if (nonDefaultLocales.length > 0) { await Promise.all(nonDefaultLocales.map(async (locale) => { const translation = await translateKey({ context, inputLanguage: defaultLocale, outputLanguage: locale, object: { [keyToReplace]: newTranslation, }, openai, model: config.model, }); translationCache[locale] = translation[keyToReplace]; })); } // Update the key in all relevant namespaces and locales in parallel await Promise.all(targetNamespaces.flatMap((namespace) => locales.map(async (locale) => { const newValue = translationCache[locale]; const existingKeys = await loadLocalesFile(loadPath, locale, namespace); existingKeys[keyToReplace] = newValue; await writeLocalesFile(savePath, locale, namespace, existingKeys); console.log(`Updated "${keyToReplace}" in ${locale} (${namespace}): "${newValue}"`); }))); }; //# sourceMappingURL=replace.js.map