langie 1.10.0 → 1.11.0
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/components/index.cjs +231 -23
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.css +1 -0
- package/dist/components/index.css.map +1 -1
- package/dist/components/index.mjs +232 -24
- package/dist/components/index.mjs.map +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/core.mjs.map +1 -1
- package/dist/index.cjs +276 -205
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -0
- package/dist/index.css.map +1 -1
- package/dist/index.mjs +277 -206
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/utils/localizeLanguageNames.d.ts +9 -0
- package/package.json +3 -2
- package/src/index.d.ts +2 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* langie v1.
|
|
2
|
+
* langie v1.11.0
|
|
3
3
|
* (c) 2026 nlit
|
|
4
4
|
* @license Apache-2.0
|
|
5
5
|
*
|
|
@@ -78,6 +78,7 @@ styleInject(".multiselect-single-label,\n.multiselect-option {\n display: flex;
|
|
|
78
78
|
var import_vue3 = require("vue");
|
|
79
79
|
var import_multiselect = __toESM(require("@vueform/multiselect"));
|
|
80
80
|
var import_fuse = __toESM(require("fuse.js"));
|
|
81
|
+
var import_transliteration = require("transliteration");
|
|
81
82
|
|
|
82
83
|
// src/language-aliases/european.ts
|
|
83
84
|
var EUROPEAN_LANGUAGES = [
|
|
@@ -195,7 +196,19 @@ var EUROPEAN_LANGUAGES = [
|
|
|
195
196
|
},
|
|
196
197
|
{
|
|
197
198
|
lang: "serbian",
|
|
198
|
-
match: [
|
|
199
|
+
match: [
|
|
200
|
+
"srp",
|
|
201
|
+
"sr",
|
|
202
|
+
"ser",
|
|
203
|
+
"serbia",
|
|
204
|
+
"serbian",
|
|
205
|
+
"srpski",
|
|
206
|
+
"\u0441\u0440\u0431\u0438\u0458\u0430",
|
|
207
|
+
"\u0441\u0440\u043F\u0441\u043A\u0438",
|
|
208
|
+
"\u0441\u0435\u0440\u0431",
|
|
209
|
+
"\u0441\u0435\u0440\u0431\u0441\u043A\u0438\u0439",
|
|
210
|
+
"\u0441\u0435\u0440\u0431\u0441"
|
|
211
|
+
],
|
|
199
212
|
suggest: ["croatian", "bosnian", "montenegrin"]
|
|
200
213
|
},
|
|
201
214
|
{
|
|
@@ -361,7 +374,7 @@ var ASIAN_LANGUAGES = [
|
|
|
361
374
|
// Central Asian & Turkic Languages
|
|
362
375
|
{
|
|
363
376
|
lang: "kazakh",
|
|
364
|
-
match: ["kaz", "kk", "kazakh", "kazakhstan"],
|
|
377
|
+
match: ["kaz", "kk", "kazlat", "kazakh", "kazakhstan", "\u043A\u0430\u0437\u0430\u0445", "\u043A\u0430\u0437\u0430\u0445\u0441\u043A\u0438\u0439", "\u043A\u0430\u0437\u0430\u0445\u0441"],
|
|
365
378
|
suggest: ["russian", "kyrgyz", "uzbek"]
|
|
366
379
|
},
|
|
367
380
|
{
|
|
@@ -627,11 +640,17 @@ var _hoisted_1 = {
|
|
|
627
640
|
};
|
|
628
641
|
var _hoisted_2 = ["src", "alt"];
|
|
629
642
|
var _hoisted_3 = { class: "language-text" };
|
|
630
|
-
var _hoisted_4 = {
|
|
643
|
+
var _hoisted_4 = {
|
|
644
|
+
key: 0,
|
|
645
|
+
class: "native-name"
|
|
646
|
+
};
|
|
631
647
|
var _hoisted_5 = ["data-lang-code"];
|
|
632
648
|
var _hoisted_6 = ["src", "alt"];
|
|
633
649
|
var _hoisted_7 = { class: "language-text" };
|
|
634
|
-
var _hoisted_8 = {
|
|
650
|
+
var _hoisted_8 = {
|
|
651
|
+
key: 0,
|
|
652
|
+
class: "native-name"
|
|
653
|
+
};
|
|
635
654
|
var _hoisted_9 = { class: "multiselect-no-options" };
|
|
636
655
|
var LanguageSelect_default = /* @__PURE__ */ (0, import_vue.defineComponent)({
|
|
637
656
|
__name: "LanguageSelect",
|
|
@@ -678,13 +697,13 @@ var LanguageSelect_default = /* @__PURE__ */ (0, import_vue.defineComponent)({
|
|
|
678
697
|
"5b09cc17-THEME_COLORS.dark.border": (0, import_vue2.unref)(THEME_COLORS).dark.border,
|
|
679
698
|
"5b09cc17-THEME_COLORS.dark.placeholder": (0, import_vue2.unref)(THEME_COLORS).dark.placeholder,
|
|
680
699
|
"5b09cc17-THEME_COLORS.dark.ring": (0, import_vue2.unref)(THEME_COLORS).dark.ring,
|
|
700
|
+
"5b09cc17-THEME_COLORS.dark.dropdownText": (0, import_vue2.unref)(THEME_COLORS).dark.dropdownText,
|
|
681
701
|
"5b09cc17-THEME_COLORS.dark.optionPointed": (0, import_vue2.unref)(THEME_COLORS).dark.optionPointed,
|
|
682
702
|
"5b09cc17-THEME_COLORS.dark.optionPointedText": (0, import_vue2.unref)(THEME_COLORS).dark.optionPointedText,
|
|
683
703
|
"5b09cc17-THEME_COLORS.dark.optionSelected": (0, import_vue2.unref)(THEME_COLORS).dark.optionSelected,
|
|
684
704
|
"5b09cc17-THEME_COLORS.dark.optionSelectedText": (0, import_vue2.unref)(THEME_COLORS).dark.optionSelectedText,
|
|
685
705
|
"5b09cc17-THEME_COLORS.dark.dropdownBackground": (0, import_vue2.unref)(THEME_COLORS).dark.dropdownBackground,
|
|
686
706
|
"5b09cc17-THEME_COLORS.dark.dropdownBorder": (0, import_vue2.unref)(THEME_COLORS).dark.dropdownBorder,
|
|
687
|
-
"5b09cc17-THEME_COLORS.dark.dropdownText": (0, import_vue2.unref)(THEME_COLORS).dark.dropdownText,
|
|
688
707
|
"5b09cc17-COLORS.border.flag": (0, import_vue2.unref)(COLORS).border.flag,
|
|
689
708
|
"5b09cc17-COLORS.border.dark": (0, import_vue2.unref)(COLORS).border.dark,
|
|
690
709
|
"5b09cc17-COLORS.text.secondary": (0, import_vue2.unref)(COLORS).text.secondary,
|
|
@@ -710,7 +729,7 @@ var LanguageSelect_default = /* @__PURE__ */ (0, import_vue.defineComponent)({
|
|
|
710
729
|
const fuse = (0, import_vue3.computed)(() => {
|
|
711
730
|
if (!validLanguages.value.length) return null;
|
|
712
731
|
return new import_fuse.default(validLanguages.value, {
|
|
713
|
-
keys: ["name", "native_name", "code"],
|
|
732
|
+
keys: ["name", "native_name", "search_alias", "code"],
|
|
714
733
|
includeScore: true,
|
|
715
734
|
threshold: 0.6,
|
|
716
735
|
// Use highest threshold to catch all cases
|
|
@@ -745,15 +764,18 @@ var LanguageSelect_default = /* @__PURE__ */ (0, import_vue.defineComponent)({
|
|
|
745
764
|
if (!fuse.value) return [];
|
|
746
765
|
const aliasResult = applyLanguageAlias(query);
|
|
747
766
|
const searchTerm = Array.isArray(aliasResult.primary) ? aliasResult.primary[0] : aliasResult.primary;
|
|
748
|
-
const
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
const originalResults = fuse.value.search(query);
|
|
752
|
-
originalResults.forEach((result) => {
|
|
753
|
-
if (!results.some((r) => r.code === result.item.code)) {
|
|
754
|
-
results.push(result.item);
|
|
755
|
-
}
|
|
767
|
+
const mergeByCode = (hits) => {
|
|
768
|
+
hits.forEach((hit) => {
|
|
769
|
+
if (!results.some((r) => r.code === hit.item.code)) results.push(hit.item);
|
|
756
770
|
});
|
|
771
|
+
};
|
|
772
|
+
results = fuse.value.search(searchTerm).map((result) => result.item);
|
|
773
|
+
if (searchTerm !== query) {
|
|
774
|
+
mergeByCode(fuse.value.search(query));
|
|
775
|
+
}
|
|
776
|
+
const latinQuery = (0, import_transliteration.transliterate)(query);
|
|
777
|
+
if (latinQuery && latinQuery.toLowerCase() !== query.toLowerCase()) {
|
|
778
|
+
mergeByCode(fuse.value.search(latinQuery));
|
|
757
779
|
}
|
|
758
780
|
if (aliasResult.suggestions.length > 0) {
|
|
759
781
|
aliasResult.suggestions.forEach((suggestion) => {
|
|
@@ -878,13 +900,13 @@ var LanguageSelect_default = /* @__PURE__ */ (0, import_vue.defineComponent)({
|
|
|
878
900
|
1
|
|
879
901
|
/* TEXT */
|
|
880
902
|
),
|
|
881
|
-
(0, import_vue2.
|
|
903
|
+
value.native_name && value.native_name !== value.name ? ((0, import_vue2.openBlock)(), (0, import_vue2.createElementBlock)(
|
|
882
904
|
"span",
|
|
883
905
|
_hoisted_4,
|
|
884
|
-
"(" + (0, import_vue2.toDisplayString)(value.native_name
|
|
906
|
+
"(" + (0, import_vue2.toDisplayString)(value.native_name) + ")",
|
|
885
907
|
1
|
|
886
908
|
/* TEXT */
|
|
887
|
-
)
|
|
909
|
+
)) : (0, import_vue2.createCommentVNode)("v-if", true)
|
|
888
910
|
])
|
|
889
911
|
])) : (0, import_vue2.createCommentVNode)("v-if", true)
|
|
890
912
|
]),
|
|
@@ -906,13 +928,13 @@ var LanguageSelect_default = /* @__PURE__ */ (0, import_vue.defineComponent)({
|
|
|
906
928
|
1
|
|
907
929
|
/* TEXT */
|
|
908
930
|
),
|
|
909
|
-
(0, import_vue2.
|
|
931
|
+
option.native_name && option.native_name !== option.name ? ((0, import_vue2.openBlock)(), (0, import_vue2.createElementBlock)(
|
|
910
932
|
"span",
|
|
911
933
|
_hoisted_8,
|
|
912
|
-
"(" + (0, import_vue2.toDisplayString)(option.native_name
|
|
934
|
+
"(" + (0, import_vue2.toDisplayString)(option.native_name) + ")",
|
|
913
935
|
1
|
|
914
936
|
/* TEXT */
|
|
915
|
-
)
|
|
937
|
+
)) : (0, import_vue2.createCommentVNode)("v-if", true)
|
|
916
938
|
])
|
|
917
939
|
], 8, _hoisted_5)
|
|
918
940
|
]),
|
|
@@ -1229,6 +1251,181 @@ var clearCache = (pattern) => {
|
|
|
1229
1251
|
return cacheManager.clear(pattern);
|
|
1230
1252
|
};
|
|
1231
1253
|
|
|
1254
|
+
// src/core.ts
|
|
1255
|
+
var DEFAULT_TRANSLATOR_HOST = "http://localhost:8081";
|
|
1256
|
+
var translationCache = /* @__PURE__ */ new Map();
|
|
1257
|
+
function getTranslationCacheKey(serviceTranslations, options) {
|
|
1258
|
+
return JSON.stringify({
|
|
1259
|
+
translations: serviceTranslations.map((t) => ({
|
|
1260
|
+
[API_FIELD_TEXT]: t[API_FIELD_TEXT],
|
|
1261
|
+
[API_FIELD_FROM]: t[API_FIELD_FROM],
|
|
1262
|
+
[API_FIELD_TO]: t[API_FIELD_TO],
|
|
1263
|
+
[API_FIELD_CTX]: t[API_FIELD_CTX] || options[API_FIELD_CTX] || "ui"
|
|
1264
|
+
})),
|
|
1265
|
+
host: options.translatorHost || DEFAULT_TRANSLATOR_HOST,
|
|
1266
|
+
context: options[API_FIELD_CTX] || "ui"
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
async function translateBatch(translations2 = [], options = {}) {
|
|
1270
|
+
if (!Array.isArray(translations2) || translations2.length === 0) {
|
|
1271
|
+
throw new Error("translations must be a non-empty array");
|
|
1272
|
+
}
|
|
1273
|
+
const translatorHost = options.translatorHost || DEFAULT_TRANSLATOR_HOST;
|
|
1274
|
+
const apiKey = options.apiKey || process.env.TRANSLATOR_API_KEY;
|
|
1275
|
+
const serviceTranslations = [];
|
|
1276
|
+
const indexMap = [];
|
|
1277
|
+
translations2.forEach((tr, idx) => {
|
|
1278
|
+
const from = (tr[API_FIELD_FROM] || "").toLowerCase();
|
|
1279
|
+
const to = (tr[API_FIELD_TO] || "").toLowerCase();
|
|
1280
|
+
if (from === to) {
|
|
1281
|
+
return;
|
|
1282
|
+
}
|
|
1283
|
+
serviceTranslations.push(tr);
|
|
1284
|
+
indexMap.push(idx);
|
|
1285
|
+
});
|
|
1286
|
+
let serviceResults = [];
|
|
1287
|
+
if (serviceTranslations.length > 0) {
|
|
1288
|
+
const cacheKey = getTranslationCacheKey(serviceTranslations, options);
|
|
1289
|
+
if (translationCache.has(cacheKey)) {
|
|
1290
|
+
serviceResults = await translationCache.get(cacheKey);
|
|
1291
|
+
} else {
|
|
1292
|
+
const translationPromise = (async () => {
|
|
1293
|
+
try {
|
|
1294
|
+
const turnstileToken = options.getTurnstileToken ? await options.getTurnstileToken() : void 0;
|
|
1295
|
+
const controller = new AbortController();
|
|
1296
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
1297
|
+
const resp = await fetch(`${translatorHost}/translate`, {
|
|
1298
|
+
method: "POST",
|
|
1299
|
+
headers: {
|
|
1300
|
+
"Content-Type": "application/json",
|
|
1301
|
+
...apiKey ? { Authorization: `Bearer ${apiKey}`, "X-Api-Key": apiKey } : {}
|
|
1302
|
+
},
|
|
1303
|
+
body: JSON.stringify({
|
|
1304
|
+
[API_FIELD_TRANSLATIONS]: serviceTranslations.map((t) => ({
|
|
1305
|
+
[API_FIELD_TEXT]: t[API_FIELD_TEXT],
|
|
1306
|
+
[API_FIELD_FROM]: t[API_FIELD_FROM],
|
|
1307
|
+
[API_FIELD_TO]: t[API_FIELD_TO],
|
|
1308
|
+
[API_FIELD_CTX]: t[API_FIELD_CTX] || options[API_FIELD_CTX] || "ui"
|
|
1309
|
+
})),
|
|
1310
|
+
[API_FIELD_CTX]: options[API_FIELD_CTX] || "ui",
|
|
1311
|
+
...turnstileToken ? { [API_FIELD_TURNSTILE]: turnstileToken } : {}
|
|
1312
|
+
}),
|
|
1313
|
+
signal: controller.signal
|
|
1314
|
+
});
|
|
1315
|
+
clearTimeout(timeoutId);
|
|
1316
|
+
if (!resp.ok) {
|
|
1317
|
+
console.error(
|
|
1318
|
+
"[translator-sdk] Translator error response:",
|
|
1319
|
+
resp.status,
|
|
1320
|
+
resp.statusText
|
|
1321
|
+
);
|
|
1322
|
+
throw new Error(`Translator service error: ${resp.status} ${resp.statusText}`);
|
|
1323
|
+
}
|
|
1324
|
+
let parsed;
|
|
1325
|
+
try {
|
|
1326
|
+
parsed = await resp.clone().json();
|
|
1327
|
+
} catch (jsonErr) {
|
|
1328
|
+
console.error("[translator-sdk] Failed to parse JSON response:", jsonErr);
|
|
1329
|
+
throw new Error(`Failed to parse JSON response: ${jsonErr}`);
|
|
1330
|
+
}
|
|
1331
|
+
const data = parsed || {};
|
|
1332
|
+
if (data[API_FIELD_ERROR]) {
|
|
1333
|
+
console.warn(`[translator-sdk] Top-level API error:`, data[API_FIELD_ERROR]);
|
|
1334
|
+
return serviceTranslations.map((translation) => ({
|
|
1335
|
+
[API_FIELD_TEXT]: translation[API_FIELD_TEXT],
|
|
1336
|
+
[API_FIELD_ERROR]: data[API_FIELD_ERROR]
|
|
1337
|
+
}));
|
|
1338
|
+
}
|
|
1339
|
+
const results = Array.isArray(data[API_FIELD_TRANSLATIONS]) ? data[API_FIELD_TRANSLATIONS].map((translation, index) => {
|
|
1340
|
+
const originalText = serviceTranslations[index]?.[API_FIELD_TEXT] || "";
|
|
1341
|
+
if (translation[API_FIELD_ERROR]) {
|
|
1342
|
+
console.warn(
|
|
1343
|
+
`[translator-sdk] Translation error for "${originalText}":`,
|
|
1344
|
+
translation[API_FIELD_ERROR]
|
|
1345
|
+
);
|
|
1346
|
+
return {
|
|
1347
|
+
[API_FIELD_TEXT]: originalText,
|
|
1348
|
+
// Return original text on error
|
|
1349
|
+
[API_FIELD_ERROR]: translation[API_FIELD_ERROR]
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
if (translation[API_FIELD_FROM] && !translation[API_FIELD_TEXT]) {
|
|
1353
|
+
return {
|
|
1354
|
+
[API_FIELD_TEXT]: originalText,
|
|
1355
|
+
// For detection, return original text
|
|
1356
|
+
[API_FIELD_FROM]: translation[API_FIELD_FROM]
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
return {
|
|
1360
|
+
[API_FIELD_TEXT]: translation[API_FIELD_TEXT] || originalText
|
|
1361
|
+
};
|
|
1362
|
+
}) : data[API_FIELD_TEXT] ? [{ [API_FIELD_TEXT]: data[API_FIELD_TEXT] }] : [];
|
|
1363
|
+
return results;
|
|
1364
|
+
} catch (error) {
|
|
1365
|
+
translationCache.delete(cacheKey);
|
|
1366
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
1367
|
+
const message2 = `Translator request to ${translatorHost} timed out after 5 seconds.`;
|
|
1368
|
+
console.error(message2);
|
|
1369
|
+
throw new Error(message2);
|
|
1370
|
+
}
|
|
1371
|
+
const message = `Failed to connect to translator at ${translatorHost}. Is the service running?`;
|
|
1372
|
+
console.error(message);
|
|
1373
|
+
throw new Error(message);
|
|
1374
|
+
}
|
|
1375
|
+
})();
|
|
1376
|
+
translationCache.set(cacheKey, translationPromise);
|
|
1377
|
+
serviceResults = await translationPromise;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
const final = translations2.map((tr, idx) => {
|
|
1381
|
+
const from = (tr[API_FIELD_FROM] || "").toLowerCase();
|
|
1382
|
+
const to = (tr[API_FIELD_TO] || "").toLowerCase();
|
|
1383
|
+
if (from === to) return { [API_FIELD_TEXT]: tr[API_FIELD_TEXT] };
|
|
1384
|
+
const svcIdx = indexMap.indexOf(idx);
|
|
1385
|
+
if (svcIdx !== -1) return serviceResults[svcIdx] || { [API_FIELD_TEXT]: tr[API_FIELD_TEXT] };
|
|
1386
|
+
return { [API_FIELD_TEXT]: tr[API_FIELD_TEXT] };
|
|
1387
|
+
});
|
|
1388
|
+
return final;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
// src/utils/localizeLanguageNames.ts
|
|
1392
|
+
var CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
1393
|
+
var NAME_CTX = "language name";
|
|
1394
|
+
async function translateNames(names, targetLang, options) {
|
|
1395
|
+
const requests = names.map((name) => ({
|
|
1396
|
+
[API_FIELD_TEXT]: name,
|
|
1397
|
+
[API_FIELD_FROM]: "en",
|
|
1398
|
+
[API_FIELD_TO]: targetLang,
|
|
1399
|
+
[API_FIELD_CTX]: NAME_CTX
|
|
1400
|
+
}));
|
|
1401
|
+
try {
|
|
1402
|
+
const results = await translateBatch(requests, options);
|
|
1403
|
+
const map = {};
|
|
1404
|
+
names.forEach((name, i) => {
|
|
1405
|
+
const translated = results[i]?.[API_FIELD_TEXT];
|
|
1406
|
+
if (translated) map[name] = translated;
|
|
1407
|
+
});
|
|
1408
|
+
return map;
|
|
1409
|
+
} catch (error) {
|
|
1410
|
+
devDebug("[localizeLanguageNames] translate failed:", error);
|
|
1411
|
+
return null;
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
async function localizeLanguageNames(languages, targetLang, options = {}) {
|
|
1415
|
+
const to = (targetLang || "").toLowerCase();
|
|
1416
|
+
if (!to || to === "en" || languages.length === 0) return languages;
|
|
1417
|
+
const cacheKey = `langie_langnames_${to}`;
|
|
1418
|
+
let map = getCache(cacheKey);
|
|
1419
|
+
if (!map) {
|
|
1420
|
+
const names = [...new Set(languages.map((l) => l.name).filter(Boolean))];
|
|
1421
|
+
map = await translateNames(names, to, options);
|
|
1422
|
+
if (map && Object.keys(map).length) setCache(cacheKey, map, CACHE_TTL_MS);
|
|
1423
|
+
}
|
|
1424
|
+
if (!map) return languages;
|
|
1425
|
+
const resolved = map;
|
|
1426
|
+
return languages.map((l) => ({ ...l, search_alias: resolved[l.name] || l.search_alias }));
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1232
1429
|
// src/composables/useLangie-core.ts
|
|
1233
1430
|
var availableLanguages = (0, import_vue4.ref)([]);
|
|
1234
1431
|
var translations = (0, import_vue4.reactive)({});
|
|
@@ -1258,8 +1455,7 @@ function useLangieCore(options = {}) {
|
|
|
1258
1455
|
const cachedLanguages = getCache("langie_languages_cache");
|
|
1259
1456
|
if (cachedLanguages && availableLanguages.value.length === 0) {
|
|
1260
1457
|
availableLanguages.value = cachedLanguages;
|
|
1261
|
-
|
|
1262
|
-
devDebug("[useLangie] Loaded languages from cache:", cachedLanguages.length);
|
|
1458
|
+
devDebug("[useLangie] Seeded languages from cache (will revalidate):", cachedLanguages.length);
|
|
1263
1459
|
} else if (cachedLanguages) {
|
|
1264
1460
|
devDebug(
|
|
1265
1461
|
"[useLangie] Cache exists but languages already loaded:",
|
|
@@ -1269,6 +1465,16 @@ function useLangieCore(options = {}) {
|
|
|
1269
1465
|
devDebug("[useLangie] No cached languages found");
|
|
1270
1466
|
}
|
|
1271
1467
|
}
|
|
1468
|
+
const applyLocalizedNames = (lang) => {
|
|
1469
|
+
const base = availableLanguages.value;
|
|
1470
|
+
if (!base.length) return;
|
|
1471
|
+
localizeLanguageNames(base, lang, { translatorHost }).then((localized) => {
|
|
1472
|
+
if (localized !== base && availableLanguages.value === base) {
|
|
1473
|
+
availableLanguages.value = localized;
|
|
1474
|
+
}
|
|
1475
|
+
}).catch(() => {
|
|
1476
|
+
});
|
|
1477
|
+
};
|
|
1272
1478
|
const setLanguage = (lang) => {
|
|
1273
1479
|
if (lang && lang !== currentLanguage.value) {
|
|
1274
1480
|
}
|
|
@@ -1276,6 +1482,7 @@ function useLangieCore(options = {}) {
|
|
|
1276
1482
|
if (typeof window !== "undefined") {
|
|
1277
1483
|
localStorage.setItem("interface_language", lang);
|
|
1278
1484
|
}
|
|
1485
|
+
applyLocalizedNames(lang);
|
|
1279
1486
|
};
|
|
1280
1487
|
const fetchLanguages = async (opts = {}) => {
|
|
1281
1488
|
const { force = false, country: explicitCountry } = opts;
|
|
@@ -1376,6 +1583,7 @@ function useLangieCore(options = {}) {
|
|
|
1376
1583
|
}
|
|
1377
1584
|
_languagesCache = filtered;
|
|
1378
1585
|
_languagesPromise = null;
|
|
1586
|
+
applyLocalizedNames(currentLanguage.value);
|
|
1379
1587
|
return filtered;
|
|
1380
1588
|
} catch (error) {
|
|
1381
1589
|
devDebug("[useLangie] Language fetch error:", { error });
|