UNPKG

i18n-pro

Version:

An out-of-the-box, lightweight JavaScript i18n auto-translation solution

319 lines (318 loc) 11.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.translateTextsToLangsImpl = exports.getTranslateConfig = exports.setTranslateConfig = void 0; const gpt_3_encoder_1 = require("gpt-3-encoder"); const constants_1 = require("../constants"); const utils_1 = require("../utils"); const chalk_1 = __importDefault(require("../chalk")); const baidu_1 = require("./baidu"); const youdao_1 = require("./youdao"); const tencent_1 = require("./tencent"); const aliyun_1 = require("./aliyun"); const microsoft_1 = require("./microsoft"); const google_1 = require("./google"); const openai_1 = require("./openai"); const googlex_1 = require("./googlex"); let config = { from: '', to: [], codeLocaleMap: undefined, }; let lastRequestTimestamp = 0; let innerConfig = { maxLengthConfig: { maxLengthType: 'allStrLength', maxLength: 100000, }, }; const translatorImplMap = { baidu: baidu_1.translateByBaidu, youdao: youdao_1.translateByYoudao, tencent: tencent_1.translateByTencent, aliyun: aliyun_1.translateByAliyun, microsoft: microsoft_1.translateByMicrosoft, google: google_1.translateByGoogle, googlex: googlex_1.translateByGooglex, openai: openai_1.translateByOpenAI, }; const translatorSetConfigMap = { baidu: baidu_1.setBaiduConfig, youdao: youdao_1.setYoudaoConfig, tencent: tencent_1.setTencentConfig, aliyun: aliyun_1.setAliyunConfig, microsoft: microsoft_1.setMicrosoftConfig, google: google_1.setGoogleConfig, googlex: googlex_1.setGooglexConfig, openai: openai_1.setOpenAIConfig, }; const maxLengthMap = { baidu: { maxLengthType: 'allStrLength', maxLength: 3000, separator: constants_1.SEPARATOR_STR, }, youdao: { maxLengthType: 'allStrLength', maxLength: 5000, }, tencent: { maxLengthType: 'allStrLength', maxLength: 5000, }, aliyun: { maxLengthType: 'strLengthAndArrLength', maxLength: 1000, maxArrayLength: 50, }, microsoft: { maxLengthType: 'allStrLengthAndArrLength', maxLength: 5000, maxArrayLength: 1000, }, google: { maxLengthType: 'allStrLength', maxLength: 5000, }, googlex: { maxLengthType: 'allStrLength', maxLength: 5000, }, openai: { maxLengthType: 'allTokenLength', maxLength: 1000, separator: constants_1.SEPARATOR_STR, }, }; let currentTranslatorImpl; let currentTranslatorSetConfig; function setTranslateConfig(configProp, innerConfigProp) { const { translator = 'googlex' } = configProp; if (!Object.keys(translatorImplMap).includes(translator)) { (0, utils_1.logError)(t('不存在{0}的配置项', chalk_1.default.yellowBright(` translator = ${translator} `))); process.exit(1); } config = configProp[`${translator}Config`]; if (typeof config === 'undefined' || Object.keys(config).length == 0) { (0, utils_1.logError)(t('当前{0}没有配置对应配置内容{1}', chalk_1.default.yellowBright(` translator = ${translator} `), chalk_1.default.redBright(` ${translator}Config `))); process.exit(1); } currentTranslatorImpl = translatorImplMap[translator]; currentTranslatorSetConfig = translatorSetConfigMap[translator]; currentTranslatorSetConfig(configProp[`${translator}Config`]); innerConfig = { ...innerConfig, ...(() => { const maxLengthConfig = maxLengthMap[translator]; if (maxLengthConfig) return { maxLengthConfig }; return {}; })(), ...(innerConfigProp || {}), }; } exports.setTranslateConfig = setTranslateConfig; function getTranslateConfig() { return config; } exports.getTranslateConfig = getTranslateConfig; async function translateTextsToLangImpl(props) { const res = await currentTranslatorImpl(props); return res; } async function translateTextsToLang(props) { const { texts, from, to } = props; const { delay } = config; const { maxLengthConfig: { maxLengthType, maxLength, maxArrayLength, separator = '', }, } = innerConfig; let success = {}; let error = {}; let count = 0; let fromTexts = []; let textErrorMsg = {}; let tokens = 0; try { for (let i = 0; i < texts.length; i++) { const text = texts[i]; if (maxLengthType === 'strLengthAndArrLength' && text.length > maxLength) { error[text] = t('当前文案超出最大字符数限制:{0}', maxLength); continue; } fromTexts.push(text); count += (count === 0 ? 0 : separator.length) + text.length; if (i === texts.length - 1 || (['allStrLength', 'allStrLengthAndArrLength'].includes(maxLengthType) && texts.length - 1 > i && count + separator.length + texts[i + 1].length > maxLength) || (['strLengthAndArrLength', 'allStrLengthAndArrLength'].includes(maxLengthType) && fromTexts.length == maxArrayLength) || (['allTokenLength'].includes(maxLengthType) && texts.length - 1 > i && (tokens = (0, gpt_3_encoder_1.encode)(fromTexts + texts[i + 1]).length) > maxLength)) { if (typeof delay === 'number' && delay > 0 && delay * 1000 > Date.now() - lastRequestTimestamp) { const now = Date.now(); let last = 0; const prefix = '\u001b[100D'; while ((last = Date.now() - now) < delay * 1000) { process.stdout.write(t('{0}秒后将进行下一波翻译', chalk_1.default.redBright(Math.ceil((delay * 1000 - last) / 1000))) + prefix); } process.stdout.write(prefix); } const res = await translateTextsToLangImpl({ texts: fromTexts, from, to, tokens, }); lastRequestTimestamp = Date.now(); const { success: _success, error: _error, textErrorMsg: _textErrorMsg, } = res; success = { ...success, ..._success, }; error = { ...error, ..._error, }; textErrorMsg = { ..._textErrorMsg, }; fromTexts = []; count = 0; } } } catch (error) { (0, utils_1.logError)(error); } return { success, error, textErrorMsg, }; } function mergeTranslateLog(langCode, textResMap, logTarget) { Object.entries(textResMap).forEach(([text, target]) => { logTarget[text] = { ...(logTarget[text] || {}), [langCode]: target, }; }); } async function translateTextsToLangsImpl(props) { const { texts, customKeys, keyTextMap, langsProp, incrementalMode } = props; const { from, to: tos, codeLocaleMap = {} } = config; const success = {}; const error = {}; const textErrorMsg = {}; const langs = {}; const textIsExist = texts.reduce((res, text) => { res[text] = true; return res; }, {}); const keyIsExist = customKeys.reduce((res, text) => { res[text] = true; return res; }, {}); try { for (const to of tos) { const locale = codeLocaleMap[to] || to; const lang = langsProp[locale] || {}; const keyToTranslateText = []; const textKeysMap = {}; const translatedLang = {}; const keyTranslatedLang = {}; const keyTranslatedLangCopy = {}; const translateSuccess = {}; const keyTranslateSuccess = {}; Object.entries(lang).forEach(([key, translatedText]) => { if (incrementalMode) { if (textIsExist[key]) { translatedLang[key] = translatedText; } } if (keyIsExist[key]) { keyTranslatedLang[key] = translatedText; } }); const toTranslateText = incrementalMode ? texts.reduce((res, key) => { const translatedText = lang[key]; if (!translatedText) { res.push(key); } return res; }, []) : [...texts]; customKeys.forEach((key) => { const translatedText = lang[key]; if (incrementalMode) { if (!translatedText) { const text = keyTextMap[key]; const translatedText = lang[text]; if (!translatedText) { keyToTranslateText.push(text); const keys = textKeysMap[text] || []; keys.push(key); textKeysMap[text] = keys; } else { keyTranslatedLangCopy[key] = translatedText; } } } else { if (!translatedText) { const text = keyTextMap[key]; keyToTranslateText.push(text); const keys = textKeysMap[text] || []; keys.push(key); textKeysMap[text] = keys; } } }); const allToTranslateText = Array.from(new Set([...keyToTranslateText, ...toTranslateText])); const res = await translateTextsToLang({ texts: allToTranslateText, from, to, }); const { success: _success, error: _error, textErrorMsg: _textErrorMsg, } = res; Object.entries(_success).forEach(([text, target]) => { if (toTranslateText.includes(text)) { translateSuccess[text] = target; } if (keyToTranslateText.includes(text)) { const keys = textKeysMap[text]; keys?.forEach((key) => { keyTranslateSuccess[key] = target; }); } }); mergeTranslateLog(locale, _success, success); mergeTranslateLog(locale, _error, error); mergeTranslateLog(locale, _textErrorMsg, textErrorMsg); langs[locale] = { ...keyTranslatedLang, ...keyTranslatedLangCopy, ...keyTranslateSuccess, ...translatedLang, ...translateSuccess, }; } } catch (error) { (0, utils_1.logError)(error); } return { success, error, langs, textErrorMsg, }; } exports.translateTextsToLangsImpl = translateTextsToLangsImpl;