UNPKG

i18n-llm-translate

Version:

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

104 lines (103 loc) 5.69 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createDeepLTranslateEngine = createDeepLTranslateEngine; const util_1 = require("../../util"); const logger_1 = require("../../logger"); function createDeepLTranslateEngine(config) { if (!config.apiKey) { throw new Error('DeepL > Missing apiKey'); } const API_BASE = 'https://api.deepl.com/v2/'; function fetchTranslations(targetLanguageCode, translations, options) { return __awaiter(this, void 0, void 0, function* () { const bodyParams = new URLSearchParams(); bodyParams.append('source_lang', options.baseLanguageCode.toUpperCase()); bodyParams.append('target_lang', targetLanguageCode.toUpperCase()); translations.forEach((text) => bodyParams.append('text', text)); const result = yield fetch(`${API_BASE}translate`, { body: bodyParams, headers: { 'Authorization': `DeepL-Auth-Key ${config.apiKey}`, 'Content-Type': 'application/x-www-form-urlencoded', }, method: 'POST', }); if (!result.ok) { const errorText = yield result.text(); throw new Error(`DeepL API error: ${result.status}\n${errorText}`); } return JSON.parse(yield result.text()); }); } return { name: 'DeepL', type: 'ml', canBeTrustedWithVariablesTranslation: false, translate(translations, options) { return __awaiter(this, void 0, void 0, function* () { // TODO: Change for 'walk' method in future const flatTranslations = (0, util_1.flattenObject)(translations); const languagesTranslations = {}; const logger = options.logger || logger_1.defaultLogger; for (let targetLanguageCode of options.targetLanguageCodes) { logger.engineDebug('DeepL', `Translating '${options.baseLanguageCode}' > '${targetLanguageCode}'`); const baseTranslationsValues = Object.values(flatTranslations); const result = yield fetchTranslations(targetLanguageCode, baseTranslationsValues, options); const languageTranslations = {}; const keys = Object.keys(flatTranslations); for (let i = 0; i < result.translations.length; i++) { languageTranslations[keys[i]] = result.translations[i].text; } languagesTranslations[targetLanguageCode] = (0, util_1.unflattenObject)(languageTranslations); } return languagesTranslations; }); }, translateMissed(missingTranslations, options) { return __awaiter(this, void 0, void 0, function* () { // TODO: Change for 'walk' method in future const flatBaseTranslations = (0, util_1.flattenObject)(missingTranslations.baseLanguageTranslations); const languagesTranslations = {}; const logger = options.logger || logger_1.defaultLogger; for (let targetLanguageCode in missingTranslations.targetLanguageTranslationsKeys) { logger.engineDebug('DeepL', `Translating '${options.baseLanguageCode}' > '${targetLanguageCode}'`); const missingKeys = Object.keys((0, util_1.flattenObject)(missingTranslations.targetLanguageTranslationsKeys[targetLanguageCode])); const missingValues = []; for (let missingKey of missingKeys) { missingValues.push(flatBaseTranslations[missingKey]); } const result = yield fetchTranslations(targetLanguageCode, missingValues, options); const languageTranslations = {}; for (let i = 0; i < result.translations.length; i++) { languageTranslations[missingKeys[i]] = result.translations[i].text; } languagesTranslations[targetLanguageCode] = (0, util_1.unflattenObject)(languageTranslations); } return languagesTranslations; }); }, estimatePrice(usage) { if (!('charactersCount' in usage)) return undefined; const { charactersCount } = usage; if (charactersCount === 0) { return undefined; } // DeepL API Pro pricing (as of 2025): €25 per 1M characters const PRICE_PER_MILLION_CHARS = 20; // € const CHARS_PER_MILLION = 1000000; const millionsOfChars = charactersCount / CHARS_PER_MILLION; const estimatedCost = millionsOfChars * PRICE_PER_MILLION_CHARS; return `~${estimatedCost.toFixed(4)}€`; } }; }