176 lines
15 KiB
JavaScript
176 lines
15 KiB
JavaScript
import * as path from 'path';
|
|
import { isString, isArray, isObject, isNumber } from '@polymech/core/primitives';
|
|
import { sync as read } from "@polymech/fs/read";
|
|
import { sync as write } from "@polymech/fs/write";
|
|
import { minify as minify_html } from 'html-minifier-terser';
|
|
import { store, get } from './store.js';
|
|
import * as deepl from './deepl.js';
|
|
const minify = false;
|
|
import { defaultFilters, defaultOptions, transformObject, testFilters } from './async-iterator.js';
|
|
import { update } from './glossary.js';
|
|
import { createLogger } from '@polymech/log';
|
|
export let logger = createLogger('i18n');
|
|
export const clean = (text = "") => text.trim();
|
|
export const extension = (file) => path.parse(file).ext;
|
|
export const getTranslation = (translations, all = false) => {
|
|
if (!all) {
|
|
if (translations && translations[0] && translations[0].text) {
|
|
return translations[0].text;
|
|
}
|
|
}
|
|
else {
|
|
return translations;
|
|
}
|
|
return false;
|
|
};
|
|
export const storeSet = (storePath, text, translation, file = '') => {
|
|
const store = read(storePath, 'json') || {};
|
|
store[text] = clean(translation);
|
|
write(storePath, store);
|
|
};
|
|
export const storeGet = (storePath, text, file = '') => {
|
|
const db = read(storePath, 'json') || {};
|
|
if (db[text]) {
|
|
return db[text];
|
|
}
|
|
};
|
|
export const translateObjectAIT = async (obj, src, options) => {
|
|
const opts = defaultOptions({
|
|
throttleDelay: 100,
|
|
concurrentTasks: 1,
|
|
path: options.query,
|
|
filterCallback: testFilters(defaultFilters([
|
|
async (input) => !options.keys.includes(input)
|
|
])),
|
|
transform: async (input, path) => {
|
|
if ((isNumber(input) || parseInt(input))) {
|
|
return input;
|
|
}
|
|
const stored = get(options.store, input, options);
|
|
if (stored) {
|
|
return stored;
|
|
}
|
|
const translated = await _translate(input, src, options);
|
|
if (translated) {
|
|
if (options.store) {
|
|
store(options.store, input, translated, options);
|
|
}
|
|
return translated;
|
|
}
|
|
return input;
|
|
},
|
|
errorCallback: (path, value, error) => {
|
|
logger.error(`Error at path: ${path}, value: ${value}, error: ${error}`);
|
|
return value;
|
|
}
|
|
});
|
|
try {
|
|
await transformObject(obj, opts.transform, opts.path, opts.throttleDelay, opts.concurrentTasks, opts.errorCallback, opts.filterCallback);
|
|
return obj;
|
|
}
|
|
catch (error) {
|
|
logger.error('Translation failed:', error);
|
|
}
|
|
};
|
|
export const translateDeepL = async (text, srcLang = 'EN', dstLang = 'DE', dOptions, options = {}, file = '') => {
|
|
if (minify) {
|
|
text = await minify_html(text, {
|
|
collapseWhitespace: true
|
|
});
|
|
}
|
|
const glossary = await update(srcLang.toLowerCase(), dstLang.toLowerCase(), options);
|
|
const deeplOptions = {
|
|
preserve_formatting: '1',
|
|
tag_handling: ["xml"],
|
|
...dOptions,
|
|
text: text,
|
|
target_lang: dstLang,
|
|
source_lang: srcLang,
|
|
glossary_id: glossary?.glossaryId,
|
|
formality: options.formality || 'default',
|
|
};
|
|
let ret = await deepl.translate_deepl(deeplOptions);
|
|
if (!ret) {
|
|
logger.error('Translate failed : ' + text, file);
|
|
return false;
|
|
}
|
|
ret = ret?.data;
|
|
if (options.filters) {
|
|
(ret.translations).forEach((t, i) => {
|
|
options.filters.forEach((f) => {
|
|
ret.translations[i].text = f(text, t.text, file);
|
|
});
|
|
});
|
|
}
|
|
return ret.translations;
|
|
};
|
|
const _translate = async (value, src, options) => {
|
|
const translations = await translateDeepL(value, options.srcLang, options.dstLang, {
|
|
auth_key: options.api_key,
|
|
formality: options.formality || 'default',
|
|
free_api: false
|
|
}, options, src);
|
|
return getTranslation(translations);
|
|
};
|
|
export const translateObject = async (obj, src, options) => {
|
|
if (isNumber(obj)) {
|
|
return obj;
|
|
}
|
|
if (isString(obj) && !obj.trim().length) {
|
|
return obj;
|
|
}
|
|
if (isString(obj) && options.store) {
|
|
const stored = get(options.store, obj, options);
|
|
if (stored && options.cache) {
|
|
return stored;
|
|
}
|
|
const ret = await _translate(obj, src, options);
|
|
if (ret && options.store) {
|
|
store(options.store, obj, ret, options);
|
|
return ret;
|
|
}
|
|
else {
|
|
console.error('Error translating : ', obj);
|
|
}
|
|
return obj;
|
|
}
|
|
if (isObject(obj) || isArray(obj)) {
|
|
for await (const [key, value] of Object.entries(obj)) {
|
|
if (!obj[key]) {
|
|
continue;
|
|
}
|
|
if (!isString(key)) {
|
|
continue;
|
|
}
|
|
if (isString(value) && options.keys && !options.keys.includes(key)) {
|
|
continue;
|
|
}
|
|
if (isString(value)) {
|
|
const stored = get(options.store, value, options);
|
|
if (stored && options.cache) {
|
|
obj[key] = stored;
|
|
}
|
|
else {
|
|
obj[key] = await _translate(value, src, options);
|
|
if (options.store) {
|
|
store(options.store, value, obj[key], options);
|
|
}
|
|
}
|
|
}
|
|
else if (isObject(value)) {
|
|
obj[key] = await translateObject(value, src, options);
|
|
}
|
|
else if (isArray(value)) {
|
|
let i = 0;
|
|
for await (const v of value) {
|
|
if (!v)
|
|
continue;
|
|
value[i] = await translateObject(v, src, options);
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return obj;
|
|
};
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsYXRlX2NvbW1vbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL3RyYW5zbGF0ZV9jb21tb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBQzVCLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQTtBQUNqRixPQUFPLEVBQUUsSUFBSSxJQUFJLElBQUksRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ2hELE9BQU8sRUFBRSxJQUFJLElBQUksS0FBSyxFQUFFLE1BQU0sb0JBQW9CLENBQUE7QUFDbEQsT0FBTyxFQUFFLE1BQU0sSUFBSSxXQUFXLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQTtBQUc1RCxPQUFPLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUN2QyxPQUFPLEtBQUssS0FBSyxNQUFNLFlBQVksQ0FBQTtBQUVuQyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUE7QUFFcEIsT0FBTyxFQUNILGNBQWMsRUFDZCxjQUFjLEVBQ2QsZUFBZSxFQUVmLFdBQVcsRUFDZCxNQUFNLHFCQUFxQixDQUFBO0FBRTVCLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFFdEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUM1QyxNQUFNLENBQUMsSUFBSSxNQUFNLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0FBRXhDLE1BQU0sQ0FBQyxNQUFNLEtBQUssR0FBRyxDQUFDLE9BQWUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUE7QUFDdkQsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFHLENBQUMsSUFBWSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxD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
|