@lynxflow/seo-engine 1.6.6 → 1.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/i18n-detector.d.ts +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +4 -45
- package/dist/index.mjs +4 -45
- package/package.json +1 -1
- package/src/engine.test.ts +0 -9
- package/src/i18n-detector.ts +0 -1
- package/src/i18n-dictionary.ts +4 -4
- package/src/index.ts +0 -1
- package/src/google-translate-bridge.ts +0 -71
package/dist/i18n-detector.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Automatically detects and synchronizes website locales without requiring hardcoded lists.
|
|
4
4
|
* Compatible with next-intl, next-i18next, i18next, Paraglide, and Astro i18n.
|
|
5
5
|
*/
|
|
6
|
-
export declare const SUPPORTED_CANONICAL_LOCALES: readonly ["en", "fr", "es", "de", "it", "pt", "nl", "ru", "tr", "zh", "ja", "ko", "hi", "id", "ar", "pl", "sv", "no", "da", "fi", "cs", "el", "ro", "hu", "uk", "vi", "th", "ms", "
|
|
6
|
+
export declare const SUPPORTED_CANONICAL_LOCALES: readonly ["en", "fr", "es", "de", "it", "pt", "nl", "ru", "tr", "zh", "ja", "ko", "hi", "id", "ar", "pl", "sv", "no", "da", "fi", "cs", "el", "ro", "hu", "uk", "vi", "th", "ms", "bg", "hr", "sk", "sl", "et", "lv", "lt", "fa", "bn", "ta", "sw", "af", "tl"];
|
|
7
7
|
export type SupportedLocale = (typeof SUPPORTED_CANONICAL_LOCALES)[number];
|
|
8
8
|
export declare class I18nDetector {
|
|
9
9
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -19,7 +19,6 @@ export * from "./brand-icons";
|
|
|
19
19
|
export * from "./ui-icons";
|
|
20
20
|
export * from "./og-image-generator";
|
|
21
21
|
export * from "./free-public-tools";
|
|
22
|
-
export * from "./google-translate-bridge";
|
|
23
22
|
export * from "./urlytics-engine";
|
|
24
23
|
export * from "./keyword-permutator";
|
|
25
24
|
export * from "./llm-prompt";
|
package/dist/index.js
CHANGED
|
@@ -91,7 +91,6 @@ __export(exports_src, {
|
|
|
91
91
|
IndexNowClient: () => IndexNowClient,
|
|
92
92
|
I18nDetector: () => I18nDetector,
|
|
93
93
|
HyperswitchGateway: () => HyperswitchGateway,
|
|
94
|
-
GoogleTranslateBridge: () => GoogleTranslateBridge,
|
|
95
94
|
GeoMeshLinkingEngine: () => GeoMeshLinkingEngine,
|
|
96
95
|
FreePublicToolsEngine: () => FreePublicToolsEngine,
|
|
97
96
|
ExtendedSchemaGraphBuilder: () => ExtendedSchemaGraphBuilder,
|
|
@@ -337,8 +336,8 @@ class ApiKeyGuardian {
|
|
|
337
336
|
var DICTIONARIES = {
|
|
338
337
|
fr: {
|
|
339
338
|
geoTitle: (s, city, country, b) => `${s} à ${city} (${country}) — ${b}`,
|
|
340
|
-
geoDesc: (s, city) => `Découvrez la solution de ${s} à ${city}. Automatisez vos opérations et boostez votre croissance
|
|
341
|
-
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} est la solution de référence pour ${s} à ${city} (${country}). Déploiement en 10 minutes dès ${price} ${cur}/mois avec
|
|
339
|
+
geoDesc: (s, city) => `Découvrez la solution de ${s} à ${city}. Automatisez vos opérations et boostez votre croissance.`,
|
|
340
|
+
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} est la solution de référence pour ${s} à ${city} (${country}). Déploiement en 10 minutes dès ${price} ${cur}/mois avec avis clients synchronisés et support dédié.`,
|
|
342
341
|
vsTitle: (b, comp, y) => `${b} vs ${comp} : Comparatif Complet & Tarifs ${y}`,
|
|
343
342
|
vsDesc: (b, comp) => `Pourquoi choisir ${b} plutôt que ${comp} ? Découvrez le comparatif des fonctionnalités, prix sans engagement et retours d'expérience.`,
|
|
344
343
|
vsDirectAnswer: (b, comp) => `${b} se distingue de ${comp} par une tarification transparente sans engagement, une automatisation IA native 24/7 et un support client réactif.`,
|
|
@@ -355,8 +354,8 @@ var DICTIONARIES = {
|
|
|
355
354
|
},
|
|
356
355
|
en: {
|
|
357
356
|
geoTitle: (s, city, country, b) => `${s} in ${city} (${country}) — ${b}`,
|
|
358
|
-
geoDesc: (s, city) => `Discover the leading ${s} solution in ${city}. Automate your operations, scale revenue, and save
|
|
359
|
-
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} is the
|
|
357
|
+
geoDesc: (s, city) => `Discover the leading ${s} solution in ${city}. Automate your operations, scale revenue, and save time every week.`,
|
|
358
|
+
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} is the leading ${s} platform in ${city} (${country}). 10-minute setup starting at ${cur}${price}/mo with verified customer review integration.`,
|
|
360
359
|
vsTitle: (b, comp, y) => `${b} vs ${comp}: Full Feature Comparison & Pricing ${y}`,
|
|
361
360
|
vsDesc: (b, comp) => `Why switch from ${comp} to ${b}? Compare key features, transparent pricing with no lock-in, and customer ROI.`,
|
|
362
361
|
vsDirectAnswer: (b, comp) => `${b} beats ${comp} with native 24/7 AI automation, flexible no-contract pricing, and instant omnichannel setup.`,
|
|
@@ -4128,7 +4127,6 @@ var SUPPORTED_CANONICAL_LOCALES = [
|
|
|
4128
4127
|
"vi",
|
|
4129
4128
|
"th",
|
|
4130
4129
|
"ms",
|
|
4131
|
-
"he",
|
|
4132
4130
|
"bg",
|
|
4133
4131
|
"hr",
|
|
4134
4132
|
"sk",
|
|
@@ -4539,45 +4537,6 @@ class FreePublicToolsEngine {
|
|
|
4539
4537
|
});
|
|
4540
4538
|
}
|
|
4541
4539
|
}
|
|
4542
|
-
// src/google-translate-bridge.ts
|
|
4543
|
-
class GoogleTranslateBridge {
|
|
4544
|
-
static async translateText(text, targetLang, sourceLang = "auto") {
|
|
4545
|
-
if (!text || !text.trim())
|
|
4546
|
-
return "";
|
|
4547
|
-
const cleanTarget = targetLang.toLowerCase().split(/[-_]/)[0];
|
|
4548
|
-
const cleanSource = sourceLang.toLowerCase().split(/[-_]/)[0];
|
|
4549
|
-
if (cleanTarget === cleanSource)
|
|
4550
|
-
return text;
|
|
4551
|
-
try {
|
|
4552
|
-
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${cleanSource}&tl=${cleanTarget}&dt=t&q=${encodeURIComponent(text)}`;
|
|
4553
|
-
const res = await fetch(url);
|
|
4554
|
-
if (!res.ok)
|
|
4555
|
-
return text;
|
|
4556
|
-
const data = await res.json();
|
|
4557
|
-
if (Array.isArray(data) && Array.isArray(data[0])) {
|
|
4558
|
-
return data[0].map((item) => item[0]).join("");
|
|
4559
|
-
}
|
|
4560
|
-
return text;
|
|
4561
|
-
} catch {
|
|
4562
|
-
return text;
|
|
4563
|
-
}
|
|
4564
|
-
}
|
|
4565
|
-
static async translateBatch(texts, targetLang, sourceLang = "auto") {
|
|
4566
|
-
if (!texts || texts.length === 0)
|
|
4567
|
-
return [];
|
|
4568
|
-
return Promise.all(texts.map((t) => this.translateText(t, targetLang, sourceLang)));
|
|
4569
|
-
}
|
|
4570
|
-
static async translateObject(obj, targetLang, sourceLang = "auto") {
|
|
4571
|
-
const keys = Object.keys(obj);
|
|
4572
|
-
const values = keys.map((k) => obj[k]);
|
|
4573
|
-
const translatedValues = await this.translateBatch(values, targetLang, sourceLang);
|
|
4574
|
-
const result = {};
|
|
4575
|
-
keys.forEach((k, idx) => {
|
|
4576
|
-
result[k] = translatedValues[idx];
|
|
4577
|
-
});
|
|
4578
|
-
return result;
|
|
4579
|
-
}
|
|
4580
|
-
}
|
|
4581
4540
|
// src/urlytics-engine.ts
|
|
4582
4541
|
class UrlyticsEngine {
|
|
4583
4542
|
static parseUrl(rawUrl) {
|
package/dist/index.mjs
CHANGED
|
@@ -224,8 +224,8 @@ class ApiKeyGuardian {
|
|
|
224
224
|
var DICTIONARIES = {
|
|
225
225
|
fr: {
|
|
226
226
|
geoTitle: (s, city, country, b) => `${s} à ${city} (${country}) — ${b}`,
|
|
227
|
-
geoDesc: (s, city) => `Découvrez la solution de ${s} à ${city}. Automatisez vos opérations et boostez votre croissance
|
|
228
|
-
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} est la solution de référence pour ${s} à ${city} (${country}). Déploiement en 10 minutes dès ${price} ${cur}/mois avec
|
|
227
|
+
geoDesc: (s, city) => `Découvrez la solution de ${s} à ${city}. Automatisez vos opérations et boostez votre croissance.`,
|
|
228
|
+
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} est la solution de référence pour ${s} à ${city} (${country}). Déploiement en 10 minutes dès ${price} ${cur}/mois avec avis clients synchronisés et support dédié.`,
|
|
229
229
|
vsTitle: (b, comp, y) => `${b} vs ${comp} : Comparatif Complet & Tarifs ${y}`,
|
|
230
230
|
vsDesc: (b, comp) => `Pourquoi choisir ${b} plutôt que ${comp} ? Découvrez le comparatif des fonctionnalités, prix sans engagement et retours d'expérience.`,
|
|
231
231
|
vsDirectAnswer: (b, comp) => `${b} se distingue de ${comp} par une tarification transparente sans engagement, une automatisation IA native 24/7 et un support client réactif.`,
|
|
@@ -242,8 +242,8 @@ var DICTIONARIES = {
|
|
|
242
242
|
},
|
|
243
243
|
en: {
|
|
244
244
|
geoTitle: (s, city, country, b) => `${s} in ${city} (${country}) — ${b}`,
|
|
245
|
-
geoDesc: (s, city) => `Discover the leading ${s} solution in ${city}. Automate your operations, scale revenue, and save
|
|
246
|
-
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} is the
|
|
245
|
+
geoDesc: (s, city) => `Discover the leading ${s} solution in ${city}. Automate your operations, scale revenue, and save time every week.`,
|
|
246
|
+
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} is the leading ${s} platform in ${city} (${country}). 10-minute setup starting at ${cur}${price}/mo with verified customer review integration.`,
|
|
247
247
|
vsTitle: (b, comp, y) => `${b} vs ${comp}: Full Feature Comparison & Pricing ${y}`,
|
|
248
248
|
vsDesc: (b, comp) => `Why switch from ${comp} to ${b}? Compare key features, transparent pricing with no lock-in, and customer ROI.`,
|
|
249
249
|
vsDirectAnswer: (b, comp) => `${b} beats ${comp} with native 24/7 AI automation, flexible no-contract pricing, and instant omnichannel setup.`,
|
|
@@ -4015,7 +4015,6 @@ var SUPPORTED_CANONICAL_LOCALES = [
|
|
|
4015
4015
|
"vi",
|
|
4016
4016
|
"th",
|
|
4017
4017
|
"ms",
|
|
4018
|
-
"he",
|
|
4019
4018
|
"bg",
|
|
4020
4019
|
"hr",
|
|
4021
4020
|
"sk",
|
|
@@ -4426,45 +4425,6 @@ class FreePublicToolsEngine {
|
|
|
4426
4425
|
});
|
|
4427
4426
|
}
|
|
4428
4427
|
}
|
|
4429
|
-
// src/google-translate-bridge.ts
|
|
4430
|
-
class GoogleTranslateBridge {
|
|
4431
|
-
static async translateText(text, targetLang, sourceLang = "auto") {
|
|
4432
|
-
if (!text || !text.trim())
|
|
4433
|
-
return "";
|
|
4434
|
-
const cleanTarget = targetLang.toLowerCase().split(/[-_]/)[0];
|
|
4435
|
-
const cleanSource = sourceLang.toLowerCase().split(/[-_]/)[0];
|
|
4436
|
-
if (cleanTarget === cleanSource)
|
|
4437
|
-
return text;
|
|
4438
|
-
try {
|
|
4439
|
-
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${cleanSource}&tl=${cleanTarget}&dt=t&q=${encodeURIComponent(text)}`;
|
|
4440
|
-
const res = await fetch(url);
|
|
4441
|
-
if (!res.ok)
|
|
4442
|
-
return text;
|
|
4443
|
-
const data = await res.json();
|
|
4444
|
-
if (Array.isArray(data) && Array.isArray(data[0])) {
|
|
4445
|
-
return data[0].map((item) => item[0]).join("");
|
|
4446
|
-
}
|
|
4447
|
-
return text;
|
|
4448
|
-
} catch {
|
|
4449
|
-
return text;
|
|
4450
|
-
}
|
|
4451
|
-
}
|
|
4452
|
-
static async translateBatch(texts, targetLang, sourceLang = "auto") {
|
|
4453
|
-
if (!texts || texts.length === 0)
|
|
4454
|
-
return [];
|
|
4455
|
-
return Promise.all(texts.map((t) => this.translateText(t, targetLang, sourceLang)));
|
|
4456
|
-
}
|
|
4457
|
-
static async translateObject(obj, targetLang, sourceLang = "auto") {
|
|
4458
|
-
const keys = Object.keys(obj);
|
|
4459
|
-
const values = keys.map((k) => obj[k]);
|
|
4460
|
-
const translatedValues = await this.translateBatch(values, targetLang, sourceLang);
|
|
4461
|
-
const result = {};
|
|
4462
|
-
keys.forEach((k, idx) => {
|
|
4463
|
-
result[k] = translatedValues[idx];
|
|
4464
|
-
});
|
|
4465
|
-
return result;
|
|
4466
|
-
}
|
|
4467
|
-
}
|
|
4468
4428
|
// src/urlytics-engine.ts
|
|
4469
4429
|
class UrlyticsEngine {
|
|
4470
4430
|
static parseUrl(rawUrl) {
|
|
@@ -7102,7 +7062,6 @@ export {
|
|
|
7102
7062
|
IndexNowClient,
|
|
7103
7063
|
I18nDetector,
|
|
7104
7064
|
HyperswitchGateway,
|
|
7105
|
-
GoogleTranslateBridge,
|
|
7106
7065
|
GeoMeshLinkingEngine,
|
|
7107
7066
|
FreePublicToolsEngine,
|
|
7108
7067
|
ExtendedSchemaGraphBuilder,
|
package/package.json
CHANGED
package/src/engine.test.ts
CHANGED
|
@@ -11,7 +11,6 @@ import { I18nDetector } from "./i18n-detector";
|
|
|
11
11
|
import { renderUiIconSvg, resolveFeatureIcon } from "./ui-icons";
|
|
12
12
|
import { OgImageGenerator } from "./og-image-generator";
|
|
13
13
|
import { FreePublicToolsEngine } from "./free-public-tools";
|
|
14
|
-
import { GoogleTranslateBridge } from "./google-translate-bridge";
|
|
15
14
|
|
|
16
15
|
describe("Multilingual SEO Slug Engine (10+ Languages)", () => {
|
|
17
16
|
it("English: Strips stop words and years", () => {
|
|
@@ -338,12 +337,4 @@ describe("Audited Reference Engines (Advertools, Santifer, Seonaut)", () => {
|
|
|
338
337
|
const schema = FreePublicToolsEngine.generateSampleSchema("softwareApp", "Acme", "https://acme.com");
|
|
339
338
|
expect(schema["@type"]).toBe("SoftwareApplication");
|
|
340
339
|
});
|
|
341
|
-
|
|
342
|
-
it("GoogleTranslateBridge: Translates texts and handles batch translation", async () => {
|
|
343
|
-
const identical = await GoogleTranslateBridge.translateText("Bonjour", "fr", "fr");
|
|
344
|
-
expect(identical).toBe("Bonjour");
|
|
345
|
-
|
|
346
|
-
const batch = await GoogleTranslateBridge.translateBatch(["Hello", "World"], "en", "en");
|
|
347
|
-
expect(batch).toEqual(["Hello", "World"]);
|
|
348
|
-
});
|
|
349
340
|
});
|
package/src/i18n-detector.ts
CHANGED
package/src/i18n-dictionary.ts
CHANGED
|
@@ -31,8 +31,8 @@ export const DICTIONARIES: Record<string, LocaleCopy> = {
|
|
|
31
31
|
// 🇫🇷 French (Europe / Africa / Canada)
|
|
32
32
|
fr: {
|
|
33
33
|
geoTitle: (s, city, country, b) => `${s} à ${city} (${country}) — ${b}`,
|
|
34
|
-
geoDesc: (s, city) => `Découvrez la solution de ${s} à ${city}. Automatisez vos opérations et boostez votre croissance
|
|
35
|
-
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} est la solution de référence pour ${s} à ${city} (${country}). Déploiement en 10 minutes dès ${price} ${cur}/mois avec
|
|
34
|
+
geoDesc: (s, city) => `Découvrez la solution de ${s} à ${city}. Automatisez vos opérations et boostez votre croissance.`,
|
|
35
|
+
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} est la solution de référence pour ${s} à ${city} (${country}). Déploiement en 10 minutes dès ${price} ${cur}/mois avec avis clients synchronisés et support dédié.`,
|
|
36
36
|
vsTitle: (b, comp, y) => `${b} vs ${comp} : Comparatif Complet & Tarifs ${y}`,
|
|
37
37
|
vsDesc: (b, comp) => `Pourquoi choisir ${b} plutôt que ${comp} ? Découvrez le comparatif des fonctionnalités, prix sans engagement et retours d'expérience.`,
|
|
38
38
|
vsDirectAnswer: (b, comp) => `${b} se distingue de ${comp} par une tarification transparente sans engagement, une automatisation IA native 24/7 et un support client réactif.`,
|
|
@@ -51,8 +51,8 @@ export const DICTIONARIES: Record<string, LocaleCopy> = {
|
|
|
51
51
|
// 🇬🇧 English (Global)
|
|
52
52
|
en: {
|
|
53
53
|
geoTitle: (s, city, country, b) => `${s} in ${city} (${country}) — ${b}`,
|
|
54
|
-
geoDesc: (s, city) => `Discover the leading ${s} solution in ${city}. Automate your operations, scale revenue, and save
|
|
55
|
-
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} is the
|
|
54
|
+
geoDesc: (s, city) => `Discover the leading ${s} solution in ${city}. Automate your operations, scale revenue, and save time every week.`,
|
|
55
|
+
geoDirectAnswer: (b, s, city, country, price, cur) => `${b} is the leading ${s} platform in ${city} (${country}). 10-minute setup starting at ${cur}${price}/mo with verified customer review integration.`,
|
|
56
56
|
vsTitle: (b, comp, y) => `${b} vs ${comp}: Full Feature Comparison & Pricing ${y}`,
|
|
57
57
|
vsDesc: (b, comp) => `Why switch from ${comp} to ${b}? Compare key features, transparent pricing with no lock-in, and customer ROI.`,
|
|
58
58
|
vsDirectAnswer: (b, comp) => `${b} beats ${comp} with native 24/7 AI automation, flexible no-contract pricing, and instant omnichannel setup.`,
|
package/src/index.ts
CHANGED
|
@@ -20,7 +20,6 @@ export * from "./brand-icons";
|
|
|
20
20
|
export * from "./ui-icons";
|
|
21
21
|
export * from "./og-image-generator";
|
|
22
22
|
export * from "./free-public-tools";
|
|
23
|
-
export * from "./google-translate-bridge";
|
|
24
23
|
export * from "./urlytics-engine";
|
|
25
24
|
export * from "./keyword-permutator";
|
|
26
25
|
export * from "./llm-prompt";
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 🌐 Google Translation Engine Bridge
|
|
3
|
-
* Provides fast, batch, zero-cost multilingual translation for Programmatic SEO pages,
|
|
4
|
-
* markdown documentation, and schema descriptions across 40+ global languages.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export class GoogleTranslateBridge {
|
|
8
|
-
/**
|
|
9
|
-
* Translates a single text string into the target language using Google's public translation endpoint.
|
|
10
|
-
*/
|
|
11
|
-
static async translateText(
|
|
12
|
-
text: string,
|
|
13
|
-
targetLang: string,
|
|
14
|
-
sourceLang: string = "auto",
|
|
15
|
-
): Promise<string> {
|
|
16
|
-
if (!text || !text.trim()) return "";
|
|
17
|
-
const cleanTarget = targetLang.toLowerCase().split(/[-_]/)[0];
|
|
18
|
-
const cleanSource = sourceLang.toLowerCase().split(/[-_]/)[0];
|
|
19
|
-
|
|
20
|
-
if (cleanTarget === cleanSource) return text;
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${cleanSource}&tl=${cleanTarget}&dt=t&q=${encodeURIComponent(
|
|
24
|
-
text,
|
|
25
|
-
)}`;
|
|
26
|
-
|
|
27
|
-
const res = await fetch(url);
|
|
28
|
-
if (!res.ok) return text;
|
|
29
|
-
|
|
30
|
-
const data = (await res.json()) as any;
|
|
31
|
-
if (Array.isArray(data) && Array.isArray(data[0])) {
|
|
32
|
-
return data[0].map((item: any) => item[0]).join("");
|
|
33
|
-
}
|
|
34
|
-
return text;
|
|
35
|
-
} catch {
|
|
36
|
-
return text; // Safe fallback to original text
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Batch translates an array of strings in parallel with concurrency throttling.
|
|
42
|
-
*/
|
|
43
|
-
static async translateBatch(
|
|
44
|
-
texts: string[],
|
|
45
|
-
targetLang: string,
|
|
46
|
-
sourceLang: string = "auto",
|
|
47
|
-
): Promise<string[]> {
|
|
48
|
-
if (!texts || texts.length === 0) return [];
|
|
49
|
-
return Promise.all(texts.map((t) => this.translateText(t, targetLang, sourceLang)));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Translates a structured key-value object (e.g. SEO page meta or FAQ list).
|
|
54
|
-
*/
|
|
55
|
-
static async translateObject<T extends Record<string, string>>(
|
|
56
|
-
obj: T,
|
|
57
|
-
targetLang: string,
|
|
58
|
-
sourceLang: string = "auto",
|
|
59
|
-
): Promise<T> {
|
|
60
|
-
const keys = Object.keys(obj) as (keyof T)[];
|
|
61
|
-
const values = keys.map((k) => obj[k]);
|
|
62
|
-
const translatedValues = await this.translateBatch(values, targetLang, sourceLang);
|
|
63
|
-
|
|
64
|
-
const result = {} as T;
|
|
65
|
-
keys.forEach((k, idx) => {
|
|
66
|
-
result[k] = translatedValues[idx] as any;
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
return result;
|
|
70
|
-
}
|
|
71
|
-
}
|