langie 1.9.25

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.
@@ -0,0 +1,2327 @@
1
+ /**
2
+ * langie v1.9.25
3
+ * (c) 2026 nlit
4
+ * @license Apache-2.0
5
+ *
6
+ * Licensed under the Apache License, Version 2.0
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ */
9
+ "use strict";
10
+ var __create = Object.create;
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __export = (target, all) => {
17
+ for (var name in all)
18
+ __defProp(target, name, { get: all[name], enumerable: true });
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") {
22
+ for (let key of __getOwnPropNames(from))
23
+ if (!__hasOwnProp.call(to, key) && key !== except)
24
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
+ // If the importer is in node compatibility mode or this is not an ESM
30
+ // file that has been converted to a CommonJS file using a Babel-
31
+ // compatible transform (i.e. "__esModule" has not been set), then set
32
+ // "default" to the CommonJS "module.exports" for node compatibility.
33
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
+ mod
35
+ ));
36
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
+
38
+ // src/components/index.ts
39
+ var components_exports = {};
40
+ __export(components_exports, {
41
+ InterfaceLanguageSelect: () => InterfaceLanguageSelect_default2,
42
+ LanguageSelect: () => LanguageSelect_default2,
43
+ lt: () => lt_default2
44
+ });
45
+ module.exports = __toCommonJS(components_exports);
46
+
47
+ // vue-script:/Users/nlit/projects/langie-sdk/src/components/LanguageSelect.vue?type=script
48
+ var import_vue = require("vue");
49
+ var import_vue2 = require("vue");
50
+ var import_default = require("@vueform/multiselect/themes/default.css");
51
+ var import_vue3 = require("vue");
52
+ var import_multiselect = __toESM(require("@vueform/multiselect"));
53
+ var import_fuse = __toESM(require("fuse.js"));
54
+
55
+ // src/language-aliases/european.ts
56
+ var EUROPEAN_LANGUAGES = [
57
+ // Major European Languages
58
+ {
59
+ lang: "english",
60
+ match: [
61
+ "eng",
62
+ "en",
63
+ "united states",
64
+ "united states of america",
65
+ "usa",
66
+ "us",
67
+ "great britain",
68
+ "britain",
69
+ "british",
70
+ "england",
71
+ "united kingdom",
72
+ "uk"
73
+ ],
74
+ suggest: ["irish", "scottish", "welsh"]
75
+ },
76
+ {
77
+ lang: "spanish",
78
+ match: [
79
+ "spa",
80
+ "es",
81
+ "esp",
82
+ "spain",
83
+ "espa\xF1ol",
84
+ "mexico",
85
+ "mexican",
86
+ "argentina",
87
+ "colombia",
88
+ "venezuela"
89
+ ],
90
+ suggest: ["catalan", "galician", "basque"]
91
+ },
92
+ {
93
+ lang: "french",
94
+ match: [
95
+ "fra",
96
+ "fr",
97
+ "fre",
98
+ "france",
99
+ "fran\xE7ais",
100
+ "canada",
101
+ "canadian",
102
+ "quebec",
103
+ "belgium",
104
+ "swiss"
105
+ ],
106
+ suggest: ["occitan", "breton", "corsican"]
107
+ },
108
+ {
109
+ lang: "german",
110
+ match: [
111
+ "ger",
112
+ "de",
113
+ "deu",
114
+ "germany",
115
+ "deutsch",
116
+ "austria",
117
+ "austrian",
118
+ "switzerland",
119
+ "swiss"
120
+ ],
121
+ suggest: ["bavarian", "saxon", "luxembourgish"]
122
+ },
123
+ {
124
+ lang: "italian",
125
+ match: ["ita", "it", "italy", "italiano", "swiss italian"],
126
+ suggest: ["sardinian", "neapolitan", "venetian"]
127
+ },
128
+ {
129
+ lang: "portuguese",
130
+ match: ["por", "pt", "portugal", "brazil", "brazilian", "braz", "mozambique", "angola"],
131
+ suggest: ["galician", "mirandese"]
132
+ },
133
+ {
134
+ lang: "dutch",
135
+ match: ["dut", "nl", "nld", "netherlands", "holland", "flemish", "belgium"],
136
+ suggest: ["frisian", "afrikaans"]
137
+ },
138
+ // Slavic Languages
139
+ {
140
+ lang: "russian",
141
+ match: ["rus", "ru", "russia", "belarus"],
142
+ suggest: ["kazakh", "tatar", "belarusian", "tajik", "uzbek", "moldovan"]
143
+ },
144
+ {
145
+ lang: "ukrainian",
146
+ match: ["ukr", "uk", "ukraine"],
147
+ suggest: ["russian", "belarusian"]
148
+ },
149
+ {
150
+ lang: "polish",
151
+ match: ["pol", "pl", "poland"],
152
+ suggest: ["silesian", "kashubian"]
153
+ },
154
+ {
155
+ lang: "czech",
156
+ match: ["ces", "cs", "cze", "czech republic", "czechia"],
157
+ suggest: ["slovak", "moravian"]
158
+ },
159
+ {
160
+ lang: "slovak",
161
+ match: ["slk", "sk", "slovakia"],
162
+ suggest: ["czech", "rusyn"]
163
+ },
164
+ {
165
+ lang: "croatian",
166
+ match: ["hrv", "hr", "croatia"],
167
+ suggest: ["serbian", "bosnian", "montenegrin"]
168
+ },
169
+ {
170
+ lang: "serbian",
171
+ match: ["srp", "sr", "ser", "serbia", "serbian", "srpski", "\u0441\u0440\u0431\u0438\u0458\u0430", "\u0441\u0440\u043F\u0441\u043A\u0438"],
172
+ suggest: ["croatian", "bosnian", "montenegrin"]
173
+ },
174
+ {
175
+ lang: "bulgarian",
176
+ match: ["bul", "bg", "bulgaria"],
177
+ suggest: ["macedonian"]
178
+ },
179
+ {
180
+ lang: "slovenian",
181
+ match: ["slv", "sl", "slovenia"],
182
+ suggest: ["croatian"]
183
+ },
184
+ // Nordic Languages
185
+ {
186
+ lang: "swedish",
187
+ match: ["swe", "sv", "sweden"],
188
+ suggest: ["norwegian", "danish", "finnish"]
189
+ },
190
+ {
191
+ lang: "norwegian",
192
+ match: ["nor", "no", "norway"],
193
+ suggest: ["swedish", "danish"]
194
+ },
195
+ {
196
+ lang: "danish",
197
+ match: ["dan", "da", "denmark"],
198
+ suggest: ["norwegian", "swedish"]
199
+ },
200
+ {
201
+ lang: "finnish",
202
+ match: ["fin", "fi", "finland"],
203
+ suggest: ["estonian", "swedish"]
204
+ },
205
+ {
206
+ lang: "icelandic",
207
+ match: ["isl", "is", "iceland"],
208
+ suggest: ["faroese", "norwegian"]
209
+ },
210
+ // Other European Languages
211
+ {
212
+ lang: "greek",
213
+ match: ["ell", "el", "gre", "greece", "hellenic"],
214
+ suggest: ["macedonian", "albanian"]
215
+ },
216
+ {
217
+ lang: "romanian",
218
+ match: ["ron", "ro", "rum", "romania"],
219
+ suggest: ["moldovan", "hungarian"]
220
+ },
221
+ {
222
+ lang: "hungarian",
223
+ match: ["hun", "hu", "hungary", "magyar"],
224
+ suggest: ["romanian", "slovak"]
225
+ },
226
+ {
227
+ lang: "albanian",
228
+ match: ["sqi", "sq", "alb", "albania", "kosovo"],
229
+ suggest: ["greek", "macedonian"]
230
+ },
231
+ {
232
+ lang: "lithuanian",
233
+ match: ["lit", "lt", "lithuania"],
234
+ suggest: ["latvian", "polish"]
235
+ },
236
+ {
237
+ lang: "latvian",
238
+ match: ["lav", "lv", "latvia"],
239
+ suggest: ["lithuanian", "estonian"]
240
+ },
241
+ {
242
+ lang: "estonian",
243
+ match: ["est", "et", "estonia"],
244
+ suggest: ["finnish", "latvian"]
245
+ },
246
+ // Celtic Languages
247
+ {
248
+ lang: "irish",
249
+ match: ["gle", "ga", "ireland", "gaelic"],
250
+ suggest: ["scottish", "welsh"]
251
+ },
252
+ {
253
+ lang: "welsh",
254
+ match: ["cym", "cy", "wales", "cymru"],
255
+ suggest: ["irish", "cornish"]
256
+ },
257
+ {
258
+ lang: "scottish",
259
+ match: ["gla", "gd", "scotland", "scots gaelic"],
260
+ suggest: ["irish", "english"]
261
+ },
262
+ // Additional Languages
263
+ {
264
+ lang: "esperanto",
265
+ match: ["epo", "eo", "esperanto"],
266
+ suggest: []
267
+ },
268
+ {
269
+ lang: "latin",
270
+ match: ["lat", "la", "latin"],
271
+ suggest: ["italian", "spanish", "french"]
272
+ }
273
+ ];
274
+
275
+ // src/language-aliases/asian.ts
276
+ var ASIAN_LANGUAGES = [
277
+ // Asian Languages
278
+ {
279
+ lang: "chinese",
280
+ match: [
281
+ "chi",
282
+ "zh",
283
+ "zho",
284
+ "zh-cn",
285
+ "cn",
286
+ "china",
287
+ "mandarin",
288
+ "zhongwen",
289
+ "simplified",
290
+ "traditional"
291
+ ],
292
+ suggest: ["cantonese", "taiwanese", "hakka"]
293
+ },
294
+ {
295
+ lang: "japanese",
296
+ match: ["jpn", "ja", "jp", "japan", "nihongo"],
297
+ suggest: ["okinawan"]
298
+ },
299
+ {
300
+ lang: "korean",
301
+ match: ["kor", "ko", "kr", "korea", "hangul", "south korea", "north korea"],
302
+ suggest: ["jeju"]
303
+ },
304
+ {
305
+ lang: "hindi",
306
+ match: ["hin", "hi", "india", "indian", "devanagari"],
307
+ suggest: ["urdu", "punjabi", "gujarati", "marathi", "bengali"]
308
+ },
309
+ {
310
+ lang: "arabic",
311
+ match: ["ara", "ar", "arab", "saudi", "egypt", "egyptian", "gulf", "levantine", "maghreb"],
312
+ suggest: ["persian", "hebrew", "urdu"]
313
+ },
314
+ {
315
+ lang: "thai",
316
+ match: ["tha", "th", "thailand", "siam"],
317
+ suggest: ["lao", "khmer"]
318
+ },
319
+ {
320
+ lang: "vietnamese",
321
+ match: ["vie", "vi", "vietnam"],
322
+ suggest: ["khmer", "lao"]
323
+ },
324
+ {
325
+ lang: "indonesian",
326
+ match: ["ind", "id", "indonesia", "bahasa"],
327
+ suggest: ["malay", "javanese", "sundanese"]
328
+ },
329
+ {
330
+ lang: "malay",
331
+ match: ["msa", "ms", "malaysia", "brunei"],
332
+ suggest: ["indonesian"]
333
+ },
334
+ // Central Asian & Turkic Languages
335
+ {
336
+ lang: "kazakh",
337
+ match: ["kaz", "kk", "kazakh", "kazakhstan"],
338
+ suggest: ["russian", "kyrgyz", "uzbek"]
339
+ },
340
+ {
341
+ lang: "turkish",
342
+ match: ["tur", "tr", "turkey"],
343
+ suggest: ["kurdish", "azerbaijani"]
344
+ },
345
+ {
346
+ lang: "uzbek",
347
+ match: ["uzb", "uz", "uzbekistan"],
348
+ suggest: ["tajik", "kazakh", "kyrgyz"]
349
+ },
350
+ {
351
+ lang: "kyrgyz",
352
+ match: ["kir", "ky", "kyrgyzstan"],
353
+ suggest: ["kazakh", "uzbek"]
354
+ },
355
+ {
356
+ lang: "tajik",
357
+ match: ["tgk", "tg", "tajikistan"],
358
+ suggest: ["persian", "uzbek"]
359
+ },
360
+ {
361
+ lang: "azerbaijani",
362
+ match: ["aze", "az", "azerbaijan"],
363
+ suggest: ["turkish", "persian"]
364
+ },
365
+ // Middle Eastern Languages
366
+ {
367
+ lang: "persian",
368
+ match: ["fas", "fa", "per", "iran", "farsi", "dari", "afghanistan"],
369
+ suggest: ["tajik", "kurdish", "pashto"]
370
+ },
371
+ {
372
+ lang: "hebrew",
373
+ match: ["heb", "he", "israel", "israeli"],
374
+ suggest: ["arabic", "yiddish"]
375
+ },
376
+ {
377
+ lang: "kurdish",
378
+ match: ["kur", "ku", "kurdistan", "kurmanji", "sorani"],
379
+ suggest: ["turkish", "persian", "arabic"]
380
+ },
381
+ // South Asian Languages
382
+ {
383
+ lang: "urdu",
384
+ match: ["urd", "ur", "pakistan", "pakistani"],
385
+ suggest: ["hindi", "punjabi"]
386
+ },
387
+ {
388
+ lang: "bengali",
389
+ match: ["ben", "bn", "bangladesh", "bengal"],
390
+ suggest: ["hindi", "assamese"]
391
+ },
392
+ {
393
+ lang: "punjabi",
394
+ match: ["pan", "pa", "punjab"],
395
+ suggest: ["hindi", "urdu"]
396
+ },
397
+ {
398
+ lang: "gujarati",
399
+ match: ["guj", "gu", "gujarat"],
400
+ suggest: ["hindi", "marathi"]
401
+ },
402
+ {
403
+ lang: "marathi",
404
+ match: ["mar", "mr", "maharashtra"],
405
+ suggest: ["hindi", "gujarati"]
406
+ },
407
+ {
408
+ lang: "tamil",
409
+ match: ["tam", "ta", "tamil nadu", "sri lanka"],
410
+ suggest: ["malayalam", "telugu", "kannada"]
411
+ },
412
+ {
413
+ lang: "telugu",
414
+ match: ["tel", "te", "andhra pradesh"],
415
+ suggest: ["tamil", "kannada"]
416
+ },
417
+ {
418
+ lang: "kannada",
419
+ match: ["kan", "kn", "karnataka"],
420
+ suggest: ["tamil", "telugu", "malayalam"]
421
+ },
422
+ {
423
+ lang: "malayalam",
424
+ match: ["mal", "ml", "kerala"],
425
+ suggest: ["tamil", "kannada"]
426
+ },
427
+ {
428
+ lang: "nepali",
429
+ match: ["nep", "ne", "nepal"],
430
+ suggest: ["hindi"]
431
+ },
432
+ {
433
+ lang: "sinhala",
434
+ match: ["sin", "si", "sri lanka", "ceylon"],
435
+ suggest: ["tamil"]
436
+ },
437
+ // Southeast Asian Languages
438
+ {
439
+ lang: "burmese",
440
+ match: ["mya", "my", "myanmar", "burma"],
441
+ suggest: ["thai"]
442
+ },
443
+ {
444
+ lang: "khmer",
445
+ match: ["khm", "km", "cambodia", "cambodian"],
446
+ suggest: ["vietnamese", "thai"]
447
+ },
448
+ {
449
+ lang: "lao",
450
+ match: ["lao", "lo", "laos"],
451
+ suggest: ["thai", "vietnamese"]
452
+ },
453
+ {
454
+ lang: "tagalog",
455
+ match: ["tgl", "tl", "philippines", "filipino"],
456
+ suggest: ["cebuano", "ilocano"]
457
+ }
458
+ ];
459
+
460
+ // src/language-aliases/african.ts
461
+ var AFRICAN_LANGUAGES = [
462
+ // African Languages
463
+ {
464
+ lang: "swahili",
465
+ match: ["swa", "sw", "kiswahili", "tanzania", "kenya"],
466
+ suggest: ["arabic"]
467
+ },
468
+ {
469
+ lang: "amharic",
470
+ match: ["amh", "am", "ethiopia", "ethiopian"],
471
+ suggest: ["tigrinya", "oromo"]
472
+ },
473
+ {
474
+ lang: "yoruba",
475
+ match: ["yor", "yo", "nigeria", "benin"],
476
+ suggest: ["igbo", "hausa"]
477
+ },
478
+ {
479
+ lang: "zulu",
480
+ match: ["zul", "zu", "south africa"],
481
+ suggest: ["xhosa", "afrikaans"]
482
+ }
483
+ ];
484
+
485
+ // src/language-aliases/index.ts
486
+ var LANGUAGE_ALIAS_TABLE = [
487
+ ...EUROPEAN_LANGUAGES,
488
+ ...ASIAN_LANGUAGES,
489
+ ...AFRICAN_LANGUAGES
490
+ ];
491
+
492
+ // src/search-utils.ts
493
+ function applyLanguageAlias(term = "") {
494
+ const s = term.toLowerCase().trim();
495
+ if (!s) return { primary: term, suggestions: [] };
496
+ const isMatch = (alias, input) => {
497
+ if (input === alias) return true;
498
+ if (alias.length >= 3 && input.length >= alias.length && input.startsWith(alias)) return true;
499
+ if (input.length >= 2 && alias.startsWith(input)) return true;
500
+ return false;
501
+ };
502
+ const hits = /* @__PURE__ */ new Set();
503
+ const suggestions = /* @__PURE__ */ new Set();
504
+ for (const { lang, match, suggest } of LANGUAGE_ALIAS_TABLE) {
505
+ for (const m of match) {
506
+ if (isMatch(m, s)) {
507
+ hits.add(lang);
508
+ if (suggest) {
509
+ suggest.forEach((sug) => suggestions.add(sug));
510
+ }
511
+ }
512
+ }
513
+ }
514
+ let primary;
515
+ if (hits.size === 0) {
516
+ primary = term;
517
+ } else if (hits.size === 1) {
518
+ primary = Array.from(hits)[0];
519
+ } else {
520
+ primary = Array.from(hits);
521
+ }
522
+ return { primary, suggestions: Array.from(suggestions) };
523
+ }
524
+
525
+ // src/constants/colors.ts
526
+ var COLORS = {
527
+ // Primary colors
528
+ primary: {
529
+ blue: "#3b82f6",
530
+ blueLight: "#60a5fa",
531
+ blueDark: "#2563eb",
532
+ blueAlpha30: "#3b82f630",
533
+ blueAlpha50: "#3b82f650"
534
+ },
535
+ // Neutral colors
536
+ neutral: {
537
+ white: "#fff",
538
+ gray50: "#f9fafb",
539
+ gray100: "#f3f4f6",
540
+ gray200: "#e5e7eb",
541
+ gray300: "#d1d5db",
542
+ gray400: "#9ca3af",
543
+ gray500: "#6b7280",
544
+ gray600: "#4b5563",
545
+ gray700: "#374151",
546
+ gray800: "#1f2937",
547
+ gray900: "#111827"
548
+ },
549
+ // Border colors
550
+ border: {
551
+ light: "#d1d5db",
552
+ dark: "#4b5563",
553
+ flag: "#eee"
554
+ },
555
+ // Text colors
556
+ text: {
557
+ primary: "#1f2937",
558
+ secondary: "#6b7280",
559
+ placeholder: "#9ca3af",
560
+ inverse: "#f9fafb"
561
+ }
562
+ };
563
+ var THEME_COLORS = {
564
+ light: {
565
+ background: COLORS.neutral.white,
566
+ backgroundDisabled: COLORS.neutral.gray100,
567
+ border: COLORS.border.light,
568
+ placeholder: COLORS.text.placeholder,
569
+ ring: COLORS.primary.blueAlpha30,
570
+ optionPointed: COLORS.neutral.gray100,
571
+ optionPointedText: COLORS.text.primary,
572
+ optionSelected: COLORS.primary.blue,
573
+ optionSelectedText: COLORS.neutral.white,
574
+ dropdownBackground: COLORS.neutral.white,
575
+ dropdownBorder: COLORS.border.light,
576
+ dropdownText: COLORS.text.primary,
577
+ tagBackground: COLORS.primary.blue
578
+ },
579
+ dark: {
580
+ background: COLORS.neutral.gray800,
581
+ backgroundDisabled: COLORS.neutral.gray700,
582
+ border: COLORS.border.dark,
583
+ placeholder: COLORS.text.placeholder,
584
+ ring: COLORS.primary.blueAlpha50,
585
+ optionPointed: COLORS.neutral.gray700,
586
+ optionPointedText: COLORS.neutral.gray50,
587
+ optionSelected: COLORS.primary.blue,
588
+ optionSelectedText: COLORS.neutral.white,
589
+ dropdownBackground: COLORS.neutral.gray800,
590
+ dropdownBorder: COLORS.border.dark,
591
+ dropdownText: COLORS.neutral.gray50,
592
+ tagBackground: COLORS.primary.blue
593
+ }
594
+ };
595
+
596
+ // vue-script:/Users/nlit/projects/langie-sdk/src/components/LanguageSelect.vue?type=script
597
+ var _hoisted_1 = {
598
+ key: 0,
599
+ class: "multiselect-single-label"
600
+ };
601
+ var _hoisted_2 = ["src", "alt"];
602
+ var _hoisted_3 = { class: "language-text" };
603
+ var _hoisted_4 = { class: "native-name" };
604
+ var _hoisted_5 = ["data-lang-code"];
605
+ var _hoisted_6 = ["src", "alt"];
606
+ var _hoisted_7 = { class: "language-text" };
607
+ var _hoisted_8 = { class: "native-name" };
608
+ var _hoisted_9 = { class: "multiselect-no-options" };
609
+ var LanguageSelect_default = /* @__PURE__ */ (0, import_vue.defineComponent)({
610
+ __name: "LanguageSelect",
611
+ props: {
612
+ modelValue: {
613
+ type: Object,
614
+ default: void 0
615
+ },
616
+ languages: {
617
+ type: Array,
618
+ default: () => []
619
+ },
620
+ placeholder: {
621
+ type: String,
622
+ default: "Select language"
623
+ },
624
+ disabled: {
625
+ type: Boolean,
626
+ default: false
627
+ },
628
+ isDark: {
629
+ type: Boolean,
630
+ default: false
631
+ }
632
+ },
633
+ emits: ["update:modelValue"],
634
+ setup(__props, { emit: __emit }) {
635
+ (0, import_vue.useCssVars)((_ctx) => ({
636
+ "25bc3fde-THEME_COLORS.light.background": (0, import_vue2.unref)(THEME_COLORS).light.background,
637
+ "25bc3fde-THEME_COLORS.light.backgroundDisabled": (0, import_vue2.unref)(THEME_COLORS).light.backgroundDisabled,
638
+ "25bc3fde-THEME_COLORS.light.border": (0, import_vue2.unref)(THEME_COLORS).light.border,
639
+ "25bc3fde-THEME_COLORS.light.ring": (0, import_vue2.unref)(THEME_COLORS).light.ring,
640
+ "25bc3fde-THEME_COLORS.light.placeholder": (0, import_vue2.unref)(THEME_COLORS).light.placeholder,
641
+ "25bc3fde-THEME_COLORS.light.optionPointed": (0, import_vue2.unref)(THEME_COLORS).light.optionPointed,
642
+ "25bc3fde-THEME_COLORS.light.optionPointedText": (0, import_vue2.unref)(THEME_COLORS).light.optionPointedText,
643
+ "25bc3fde-THEME_COLORS.light.optionSelected": (0, import_vue2.unref)(THEME_COLORS).light.optionSelected,
644
+ "25bc3fde-THEME_COLORS.light.optionSelectedText": (0, import_vue2.unref)(THEME_COLORS).light.optionSelectedText,
645
+ "25bc3fde-THEME_COLORS.light.dropdownBackground": (0, import_vue2.unref)(THEME_COLORS).light.dropdownBackground,
646
+ "25bc3fde-THEME_COLORS.light.dropdownBorder": (0, import_vue2.unref)(THEME_COLORS).light.dropdownBorder,
647
+ "25bc3fde-THEME_COLORS.light.dropdownText": (0, import_vue2.unref)(THEME_COLORS).light.dropdownText,
648
+ "25bc3fde-THEME_COLORS.light.tagBackground": (0, import_vue2.unref)(THEME_COLORS).light.tagBackground,
649
+ "25bc3fde-THEME_COLORS.dark.background": (0, import_vue2.unref)(THEME_COLORS).dark.background,
650
+ "25bc3fde-THEME_COLORS.dark.backgroundDisabled": (0, import_vue2.unref)(THEME_COLORS).dark.backgroundDisabled,
651
+ "25bc3fde-THEME_COLORS.dark.border": (0, import_vue2.unref)(THEME_COLORS).dark.border,
652
+ "25bc3fde-THEME_COLORS.dark.placeholder": (0, import_vue2.unref)(THEME_COLORS).dark.placeholder,
653
+ "25bc3fde-THEME_COLORS.dark.ring": (0, import_vue2.unref)(THEME_COLORS).dark.ring,
654
+ "25bc3fde-THEME_COLORS.dark.optionPointed": (0, import_vue2.unref)(THEME_COLORS).dark.optionPointed,
655
+ "25bc3fde-THEME_COLORS.dark.optionPointedText": (0, import_vue2.unref)(THEME_COLORS).dark.optionPointedText,
656
+ "25bc3fde-THEME_COLORS.dark.optionSelected": (0, import_vue2.unref)(THEME_COLORS).dark.optionSelected,
657
+ "25bc3fde-THEME_COLORS.dark.optionSelectedText": (0, import_vue2.unref)(THEME_COLORS).dark.optionSelectedText,
658
+ "25bc3fde-THEME_COLORS.dark.dropdownBackground": (0, import_vue2.unref)(THEME_COLORS).dark.dropdownBackground,
659
+ "25bc3fde-THEME_COLORS.dark.dropdownBorder": (0, import_vue2.unref)(THEME_COLORS).dark.dropdownBorder,
660
+ "25bc3fde-THEME_COLORS.dark.dropdownText": (0, import_vue2.unref)(THEME_COLORS).dark.dropdownText,
661
+ "25bc3fde-COLORS.border.flag": (0, import_vue2.unref)(COLORS).border.flag,
662
+ "25bc3fde-COLORS.border.dark": (0, import_vue2.unref)(COLORS).border.dark,
663
+ "25bc3fde-COLORS.text.secondary": (0, import_vue2.unref)(COLORS).text.secondary,
664
+ "25bc3fde-COLORS.neutral.gray400": (0, import_vue2.unref)(COLORS).neutral.gray400
665
+ }));
666
+ const getFlagCode = (lang) => {
667
+ const flagCode = lang.flag_country || lang.code;
668
+ return flagCode;
669
+ };
670
+ const getFlagImageUrl = (lang) => {
671
+ const flagCode = getFlagCode(lang);
672
+ return `/flags/${flagCode}.svg`;
673
+ };
674
+ const props = __props;
675
+ const emit = __emit;
676
+ const isLoading = (0, import_vue3.computed)(() => {
677
+ return props.languages.length <= 0;
678
+ });
679
+ const searchQuery = (0, import_vue3.ref)("");
680
+ const validLanguages = (0, import_vue3.computed)(() => {
681
+ return props.languages.filter((lang) => lang && lang.code && lang.name && lang.native_name);
682
+ });
683
+ const fuse = (0, import_vue3.computed)(() => {
684
+ if (!validLanguages.value.length) return null;
685
+ return new import_fuse.default(validLanguages.value, {
686
+ keys: ["name", "native_name", "code"],
687
+ includeScore: true,
688
+ threshold: 0.6,
689
+ // Use highest threshold to catch all cases
690
+ isCaseSensitive: false,
691
+ minMatchCharLength: 1
692
+ // Allow single character matches
693
+ });
694
+ });
695
+ const multiselectKey = (0, import_vue3.computed)(() => {
696
+ const hasApiData = props.languages.length > 0 && props.languages[0].flag_country !== null;
697
+ return hasApiData ? "api-data" : "fallback-data";
698
+ });
699
+ const selectedLanguageKey = (0, import_vue3.computed)(() => {
700
+ if (!props.modelValue || !props.modelValue.code) return "no-selection";
701
+ const key = `${props.modelValue.code}-${props.modelValue.flag_country || "fallback"}`;
702
+ return key;
703
+ });
704
+ const selectedLanguage = (0, import_vue3.computed)({
705
+ get: () => props.modelValue || null,
706
+ set: (value) => {
707
+ if (value && value.code) {
708
+ emit("update:modelValue", value);
709
+ }
710
+ }
711
+ });
712
+ const filteredLanguages = (0, import_vue3.computed)(() => {
713
+ const query = searchQuery.value.trim();
714
+ let results;
715
+ if (!query) {
716
+ results = validLanguages.value;
717
+ } else {
718
+ if (!fuse.value) return [];
719
+ const aliasResult = applyLanguageAlias(query);
720
+ const searchTerm = Array.isArray(aliasResult.primary) ? aliasResult.primary[0] : aliasResult.primary;
721
+ const fuseResults = fuse.value.search(searchTerm);
722
+ results = fuseResults.map((result) => result.item);
723
+ if (searchTerm !== query) {
724
+ const originalResults = fuse.value.search(query);
725
+ originalResults.forEach((result) => {
726
+ if (!results.some((r) => r.code === result.item.code)) {
727
+ results.push(result.item);
728
+ }
729
+ });
730
+ }
731
+ if (aliasResult.suggestions.length > 0) {
732
+ aliasResult.suggestions.forEach((suggestion) => {
733
+ const suggestedLang = validLanguages.value.find((lang) => {
734
+ const langName = lang.name.toLowerCase();
735
+ const suggestion_lower = suggestion.toLowerCase();
736
+ return langName === suggestion_lower || // Exact match
737
+ langName.includes(suggestion_lower) || // Contains match
738
+ lang.code.toLowerCase() === suggestion_lower || // Code match
739
+ langName.startsWith(suggestion_lower) || // Starts with match
740
+ // Handle common variations
741
+ suggestion_lower === "tatar" && langName.includes("tatar") || suggestion_lower === "belarusian" && (langName.includes("belarus") || langName.includes("belarusian")) || suggestion_lower === "moldovan" && (langName.includes("moldov") || langName.includes("moldova"));
742
+ });
743
+ if (suggestedLang && !results.some((r) => r.code === suggestedLang.code)) {
744
+ results.push(suggestedLang);
745
+ }
746
+ });
747
+ }
748
+ if (query.length === 2) {
749
+ const lowerQuery = query.toLowerCase();
750
+ const manualResults = validLanguages.value.filter(
751
+ (lang) => lang.name.toLowerCase().startsWith(lowerQuery) || lang.native_name.toLowerCase().startsWith(lowerQuery)
752
+ );
753
+ manualResults.forEach((lang) => {
754
+ if (!results.some((r) => r.code === lang.code)) {
755
+ results.push(lang);
756
+ }
757
+ });
758
+ }
759
+ }
760
+ const filtered = results.filter(
761
+ (lang) => !props.modelValue || !props.modelValue.code || lang.code !== props.modelValue.code
762
+ );
763
+ return filtered;
764
+ });
765
+ function handleSearch(query) {
766
+ searchQuery.value = query;
767
+ if (query.trim()) {
768
+ (0, import_vue3.nextTick)(() => {
769
+ const dropdown = document.querySelector(".multiselect-dropdown");
770
+ const firstOption = dropdown?.querySelector(".multiselect-option");
771
+ if (firstOption) {
772
+ firstOption.scrollIntoView({ behavior: "smooth", block: "nearest" });
773
+ firstOption.classList.add("multiselect-option-is-pointed");
774
+ }
775
+ });
776
+ }
777
+ }
778
+ function handleKeydown(event) {
779
+ const keyboardEvent = event;
780
+ if (keyboardEvent.key === "Tab" || keyboardEvent.key === "Enter") {
781
+ const dropdown = document.querySelector(".multiselect-dropdown");
782
+ const firstOption = dropdown?.querySelector(".multiselect-option");
783
+ if (firstOption && searchQuery.value.trim()) {
784
+ const langCode = firstOption.getAttribute("data-lang-code");
785
+ if (langCode) {
786
+ const language = validLanguages.value.find((lang) => lang.code === langCode);
787
+ if (language) {
788
+ selectedLanguage.value = language;
789
+ searchQuery.value = "";
790
+ keyboardEvent.preventDefault();
791
+ }
792
+ }
793
+ }
794
+ }
795
+ }
796
+ const onFlagError = (event) => {
797
+ const target = event.target;
798
+ const currentSrc = target.src;
799
+ if (currentSrc && currentSrc.includes("/flags/")) {
800
+ const match = currentSrc.match(/\/flags\/([a-z]{2})\.svg/);
801
+ if (match) {
802
+ const countryCode = match[1];
803
+ target.src = `https://flagcdn.com/${countryCode}.svg`;
804
+ target.onerror = () => {
805
+ target.style.display = "none";
806
+ };
807
+ return;
808
+ }
809
+ }
810
+ target.style.display = "none";
811
+ };
812
+ return (_ctx, _cache) => {
813
+ return (0, import_vue2.openBlock)(), (0, import_vue2.createElementBlock)(
814
+ "div",
815
+ {
816
+ class: (0, import_vue2.normalizeClass)(["language-select", { "is-dark": __props.isDark }])
817
+ },
818
+ [
819
+ (0, import_vue2.createCommentVNode)(" Show multiselect when we have languages OR when not loading "),
820
+ validLanguages.value.length > 0 || !isLoading.value ? ((0, import_vue2.openBlock)(), (0, import_vue2.createBlock)((0, import_vue2.unref)(import_multiselect.default), {
821
+ key: multiselectKey.value,
822
+ modelValue: selectedLanguage.value,
823
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedLanguage.value = $event),
824
+ options: filteredLanguages.value,
825
+ searchable: true,
826
+ onSearchChange: handleSearch,
827
+ "can-clear": false,
828
+ "allow-empty": false,
829
+ object: true,
830
+ placeholder: validLanguages.value.length === 0 ? "No languages available" : __props.placeholder,
831
+ disabled: props.disabled || validLanguages.value.length === 0,
832
+ loading: isLoading.value,
833
+ "track-by": "name",
834
+ label: "name",
835
+ "value-prop": "code",
836
+ "filter-results": false,
837
+ onKeydown: handleKeydown
838
+ }, {
839
+ singlelabel: (0, import_vue2.withCtx)(({ value }) => [
840
+ value ? ((0, import_vue2.openBlock)(), (0, import_vue2.createElementBlock)("div", _hoisted_1, [
841
+ value.code ? ((0, import_vue2.openBlock)(), (0, import_vue2.createElementBlock)("img", {
842
+ key: selectedLanguageKey.value,
843
+ src: getFlagImageUrl(value),
844
+ class: "lang-flag",
845
+ alt: `${value.native_name || value.name} flag`,
846
+ onError: onFlagError
847
+ }, null, 40, _hoisted_2)) : (0, import_vue2.createCommentVNode)("v-if", true),
848
+ (0, import_vue2.createElementVNode)("span", _hoisted_3, [
849
+ (0, import_vue2.createTextVNode)(
850
+ (0, import_vue2.toDisplayString)(value.name) + " ",
851
+ 1
852
+ /* TEXT */
853
+ ),
854
+ (0, import_vue2.createElementVNode)(
855
+ "span",
856
+ _hoisted_4,
857
+ "(" + (0, import_vue2.toDisplayString)(value.native_name || value.name) + ")",
858
+ 1
859
+ /* TEXT */
860
+ )
861
+ ])
862
+ ])) : (0, import_vue2.createCommentVNode)("v-if", true)
863
+ ]),
864
+ option: (0, import_vue2.withCtx)(({ option }) => [
865
+ (0, import_vue2.createElementVNode)("div", {
866
+ class: "multiselect-option",
867
+ "data-lang-code": option.code
868
+ }, [
869
+ ((0, import_vue2.openBlock)(), (0, import_vue2.createElementBlock)("img", {
870
+ key: `${option.code}-${option.flag_country || "fallback"}`,
871
+ src: getFlagImageUrl(option),
872
+ class: "lang-flag",
873
+ alt: `${option.name} flag`,
874
+ onError: onFlagError
875
+ }, null, 40, _hoisted_6)),
876
+ (0, import_vue2.createElementVNode)("span", _hoisted_7, [
877
+ (0, import_vue2.createTextVNode)(
878
+ (0, import_vue2.toDisplayString)(option.name) + " ",
879
+ 1
880
+ /* TEXT */
881
+ ),
882
+ (0, import_vue2.createElementVNode)(
883
+ "span",
884
+ _hoisted_8,
885
+ "(" + (0, import_vue2.toDisplayString)(option.native_name || option.name) + ")",
886
+ 1
887
+ /* TEXT */
888
+ )
889
+ ])
890
+ ], 8, _hoisted_5)
891
+ ]),
892
+ noresults: (0, import_vue2.withCtx)(() => _cache[1] || (_cache[1] = [
893
+ (0, import_vue2.createElementVNode)(
894
+ "div",
895
+ { class: "multiselect-no-results" },
896
+ "No languages found.",
897
+ -1
898
+ /* CACHED */
899
+ )
900
+ ])),
901
+ nooptions: (0, import_vue2.withCtx)(() => [
902
+ (0, import_vue2.createElementVNode)(
903
+ "div",
904
+ _hoisted_9,
905
+ (0, import_vue2.toDisplayString)(validLanguages.value.length === 0 ? "Please provide languages via the :languages prop" : "No languages available."),
906
+ 1
907
+ /* TEXT */
908
+ )
909
+ ]),
910
+ _: 1
911
+ /* STABLE */
912
+ }, 8, ["modelValue", "options", "placeholder", "disabled", "loading"])) : isLoading.value && validLanguages.value.length === 0 ? ((0, import_vue2.openBlock)(), (0, import_vue2.createElementBlock)(
913
+ import_vue2.Fragment,
914
+ { key: 1 },
915
+ [
916
+ (0, import_vue2.createCommentVNode)(" Only show skeleton loader when actually loading AND we have no languages yet "),
917
+ _cache[2] || (_cache[2] = (0, import_vue2.createElementVNode)(
918
+ "div",
919
+ { class: "skeleton-loader" },
920
+ null,
921
+ -1
922
+ /* CACHED */
923
+ ))
924
+ ],
925
+ 2112
926
+ /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
927
+ )) : (0, import_vue2.createCommentVNode)("v-if", true)
928
+ ],
929
+ 2
930
+ /* CLASS */
931
+ );
932
+ };
933
+ }
934
+ });
935
+
936
+ // src/components/LanguageSelect.vue
937
+ var LanguageSelect_default2 = LanguageSelect_default;
938
+ LanguageSelect_default.__scopeId = "data-v-25bc3fde";
939
+
940
+ // vue-script:/Users/nlit/projects/langie-sdk/src/components/InterfaceLanguageSelect.vue?type=script
941
+ var import_vue6 = require("vue");
942
+ var import_vue7 = require("vue");
943
+ var import_vue8 = require("vue");
944
+
945
+ // src/useLangie.ts
946
+ var import_vue5 = require("vue");
947
+
948
+ // src/composables/useLangie-core.ts
949
+ var import_vue4 = require("vue");
950
+
951
+ // src/constants.ts
952
+ var DEFAULT_API_HOST = "https://api.langie.uk/v1";
953
+ var API_FIELD_TEXT = "t";
954
+ var API_FIELD_FROM = "from";
955
+ var API_FIELD_TO = "to";
956
+ var API_FIELD_CTX = "ctx";
957
+ var API_FIELD_TRANSLATIONS = "translations";
958
+ var API_FIELD_ERROR = "error";
959
+
960
+ // src/utils/debug.ts
961
+ var import_meta = {};
962
+ function devDebug(...args) {
963
+ if (import_meta.env && import_meta.env.DEV) {
964
+ console.debug(...args);
965
+ }
966
+ }
967
+
968
+ // src/utils/getCountryCode.ts
969
+ var ct = __toESM(require("countries-and-timezones"), 1);
970
+ async function getCountryCode() {
971
+ const localeCountry = getCountryCodeFromBrowser();
972
+ if (localeCountry) return localeCountry;
973
+ const timezoneCountry = getCountryFromTimezone();
974
+ if (timezoneCountry) return timezoneCountry;
975
+ return await getCountryFromIP();
976
+ }
977
+ function getCountryFromTimezone() {
978
+ try {
979
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
980
+ return getCountryFromTimezoneString(timezone);
981
+ } catch (error) {
982
+ return null;
983
+ }
984
+ }
985
+ function getCountryFromTimezoneString(timezone) {
986
+ try {
987
+ const country = ct.getCountryForTimezone(timezone);
988
+ return country?.id || null;
989
+ } catch (error) {
990
+ return null;
991
+ }
992
+ }
993
+ async function getCountryFromIP() {
994
+ try {
995
+ const response = await fetch("https://ipapi.co/json/");
996
+ const data = await response.json();
997
+ return data.country_code || null;
998
+ } catch (error) {
999
+ return null;
1000
+ }
1001
+ }
1002
+ function getCountryCodeFromBrowser() {
1003
+ const langs = navigator.languages || [navigator.language];
1004
+ for (const locale of langs) {
1005
+ const parts = locale.split("-");
1006
+ if (parts.length > 1) {
1007
+ return parts[1].toUpperCase();
1008
+ }
1009
+ }
1010
+ return null;
1011
+ }
1012
+
1013
+ // src/utils/cache.ts
1014
+ var DEFAULT_TTL = 7 * 24 * 60 * 60 * 1e3;
1015
+ var DEFAULT_MAX_SIZE = 2 * 1024 * 1024;
1016
+ var DEFAULT_MAX_ITEMS = 1e3;
1017
+ var CacheManager = class {
1018
+ options;
1019
+ constructor(options = {}) {
1020
+ this.options = {
1021
+ ttl: options.ttl || DEFAULT_TTL,
1022
+ maxSize: options.maxSize || DEFAULT_MAX_SIZE,
1023
+ maxItems: options.maxItems || DEFAULT_MAX_ITEMS
1024
+ };
1025
+ }
1026
+ set(key, data, ttl) {
1027
+ if (typeof window === "undefined") return false;
1028
+ try {
1029
+ const item = {
1030
+ data,
1031
+ timestamp: Date.now(),
1032
+ ttl: ttl || this.options.ttl
1033
+ };
1034
+ const serialized = JSON.stringify(item);
1035
+ const size = new Blob([serialized]).size;
1036
+ if (size > this.options.maxSize) {
1037
+ console.warn(`[CacheManager] Item size ${size} exceeds max size ${this.options.maxSize}`);
1038
+ return false;
1039
+ }
1040
+ this.cleanup();
1041
+ const currentSize = this.getCurrentSize();
1042
+ if (currentSize + size > this.options.maxSize) {
1043
+ console.warn(`[CacheManager] Cache would exceed max size after adding item`);
1044
+ return false;
1045
+ }
1046
+ localStorage.setItem(key, serialized);
1047
+ return true;
1048
+ } catch (error) {
1049
+ console.warn(`[CacheManager] Failed to set cache item ${key}:`, error);
1050
+ return false;
1051
+ }
1052
+ }
1053
+ get(key) {
1054
+ if (typeof window === "undefined") return null;
1055
+ try {
1056
+ const item = localStorage.getItem(key);
1057
+ if (!item) return null;
1058
+ const cacheItem = JSON.parse(item);
1059
+ const now = Date.now();
1060
+ if (now - cacheItem.timestamp > cacheItem.ttl) {
1061
+ localStorage.removeItem(key);
1062
+ return null;
1063
+ }
1064
+ return cacheItem.data;
1065
+ } catch (error) {
1066
+ console.warn(`[CacheManager] Failed to get cache item ${key}:`, error);
1067
+ localStorage.removeItem(key);
1068
+ return null;
1069
+ }
1070
+ }
1071
+ remove(key) {
1072
+ if (typeof window === "undefined") return false;
1073
+ try {
1074
+ localStorage.removeItem(key);
1075
+ return true;
1076
+ } catch (error) {
1077
+ console.warn(`[CacheManager] Failed to remove cache item ${key}:`, error);
1078
+ return false;
1079
+ }
1080
+ }
1081
+ clear(pattern) {
1082
+ if (typeof window === "undefined") return;
1083
+ try {
1084
+ if (pattern) {
1085
+ Object.keys(localStorage).forEach((key) => {
1086
+ if (key.includes(pattern)) {
1087
+ localStorage.removeItem(key);
1088
+ }
1089
+ });
1090
+ } else {
1091
+ Object.keys(localStorage).forEach((key) => {
1092
+ if (key.startsWith("langie_")) {
1093
+ localStorage.removeItem(key);
1094
+ }
1095
+ });
1096
+ }
1097
+ } catch (error) {
1098
+ console.warn("[CacheManager] Failed to clear cache:", error);
1099
+ }
1100
+ }
1101
+ cleanup() {
1102
+ if (typeof window === "undefined") return;
1103
+ try {
1104
+ const now = Date.now();
1105
+ const items = [];
1106
+ Object.keys(localStorage).forEach((key) => {
1107
+ if (key.startsWith("langie_")) {
1108
+ try {
1109
+ const item = localStorage.getItem(key);
1110
+ if (item) {
1111
+ const cacheItem = JSON.parse(item);
1112
+ const size = new Blob([item]).size;
1113
+ if (now - cacheItem.timestamp > cacheItem.ttl) {
1114
+ localStorage.removeItem(key);
1115
+ return;
1116
+ }
1117
+ items.push({
1118
+ key,
1119
+ size,
1120
+ timestamp: cacheItem.timestamp
1121
+ });
1122
+ }
1123
+ } catch (error) {
1124
+ localStorage.removeItem(key);
1125
+ }
1126
+ }
1127
+ });
1128
+ items.sort((a, b) => a.timestamp - b.timestamp);
1129
+ while (items.length > this.options.maxItems) {
1130
+ const oldest = items.shift();
1131
+ if (oldest) {
1132
+ localStorage.removeItem(oldest.key);
1133
+ }
1134
+ }
1135
+ let totalSize = items.reduce((sum, item) => sum + item.size, 0);
1136
+ while (totalSize > this.options.maxSize && items.length > 0) {
1137
+ const oldest = items.shift();
1138
+ if (oldest) {
1139
+ localStorage.removeItem(oldest.key);
1140
+ totalSize -= oldest.size;
1141
+ }
1142
+ }
1143
+ } catch (error) {
1144
+ console.warn("[CacheManager] Failed to cleanup cache:", error);
1145
+ }
1146
+ }
1147
+ getCurrentSize() {
1148
+ if (typeof window === "undefined") return 0;
1149
+ try {
1150
+ let totalSize = 0;
1151
+ Object.keys(localStorage).forEach((key) => {
1152
+ if (key.startsWith("langie_")) {
1153
+ const item = localStorage.getItem(key);
1154
+ if (item) {
1155
+ totalSize += new Blob([item]).size;
1156
+ }
1157
+ }
1158
+ });
1159
+ return totalSize;
1160
+ } catch (error) {
1161
+ console.warn("[CacheManager] Failed to calculate cache size:", error);
1162
+ return 0;
1163
+ }
1164
+ }
1165
+ getStats() {
1166
+ if (typeof window === "undefined") {
1167
+ return { size: 0, items: 0, maxSize: this.options.maxSize, maxItems: this.options.maxItems };
1168
+ }
1169
+ try {
1170
+ let totalSize = 0;
1171
+ let itemCount = 0;
1172
+ Object.keys(localStorage).forEach((key) => {
1173
+ if (key.startsWith("langie_")) {
1174
+ const item = localStorage.getItem(key);
1175
+ if (item) {
1176
+ totalSize += new Blob([item]).size;
1177
+ itemCount++;
1178
+ }
1179
+ }
1180
+ });
1181
+ return {
1182
+ size: totalSize,
1183
+ items: itemCount,
1184
+ maxSize: this.options.maxSize,
1185
+ maxItems: this.options.maxItems
1186
+ };
1187
+ } catch (error) {
1188
+ console.warn("[CacheManager] Failed to get cache stats:", error);
1189
+ return { size: 0, items: 0, maxSize: this.options.maxSize, maxItems: this.options.maxItems };
1190
+ }
1191
+ }
1192
+ };
1193
+ var cacheManager = new CacheManager();
1194
+ var setCache = (key, data, ttl) => {
1195
+ return cacheManager.set(key, data, ttl);
1196
+ };
1197
+ var getCache = (key) => {
1198
+ return cacheManager.get(key);
1199
+ };
1200
+ var clearCache = (pattern) => {
1201
+ return cacheManager.clear(pattern);
1202
+ };
1203
+
1204
+ // src/composables/useLangie-core.ts
1205
+ var availableLanguages = (0, import_vue4.ref)([]);
1206
+ var translations = (0, import_vue4.reactive)({});
1207
+ var uiTranslations = (0, import_vue4.reactive)({});
1208
+ var currentLanguage = (0, import_vue4.ref)("en");
1209
+ var _translatorHost = DEFAULT_API_HOST;
1210
+ var _autoSelected = false;
1211
+ var _languagesCache = null;
1212
+ var _languagesPromise = null;
1213
+ function useLangieCore(options = {}) {
1214
+ if (options.translatorHost) {
1215
+ _translatorHost = options.translatorHost;
1216
+ }
1217
+ const translatorHost = _translatorHost;
1218
+ const defaultLanguage = options.defaultLanguage || "en";
1219
+ const isLoading = (0, import_vue4.ref)(false);
1220
+ if (defaultLanguage !== "en" && currentLanguage.value === "en") {
1221
+ currentLanguage.value = defaultLanguage;
1222
+ }
1223
+ if (typeof window !== "undefined" && currentLanguage.value === "en") {
1224
+ const savedLanguage = localStorage.getItem("interface_language");
1225
+ if (savedLanguage) {
1226
+ currentLanguage.value = savedLanguage;
1227
+ }
1228
+ }
1229
+ if (typeof window !== "undefined") {
1230
+ const cachedLanguages = getCache("langie_languages_cache");
1231
+ if (cachedLanguages && availableLanguages.value.length === 0) {
1232
+ availableLanguages.value = cachedLanguages;
1233
+ _languagesCache = cachedLanguages;
1234
+ devDebug("[useLangie] Loaded languages from cache:", cachedLanguages.length);
1235
+ } else if (cachedLanguages) {
1236
+ devDebug(
1237
+ "[useLangie] Cache exists but languages already loaded:",
1238
+ availableLanguages.value.length
1239
+ );
1240
+ } else {
1241
+ devDebug("[useLangie] No cached languages found");
1242
+ }
1243
+ }
1244
+ const setLanguage = (lang) => {
1245
+ if (lang && lang !== currentLanguage.value) {
1246
+ }
1247
+ currentLanguage.value = lang;
1248
+ if (typeof window !== "undefined") {
1249
+ localStorage.setItem("interface_language", lang);
1250
+ }
1251
+ };
1252
+ const fetchLanguages = async (opts = {}) => {
1253
+ const { force = false, country: explicitCountry } = opts;
1254
+ devDebug("[useLangie] fetchLanguages called:", {
1255
+ force,
1256
+ hasCache: !!_languagesCache,
1257
+ hasPromise: !!_languagesPromise,
1258
+ availableLanguagesLength: availableLanguages.value.length
1259
+ });
1260
+ if (!force) {
1261
+ if (_languagesCache) {
1262
+ devDebug("[useLangie] Returning cached languages:", _languagesCache.length);
1263
+ return _languagesCache;
1264
+ }
1265
+ if (_languagesPromise) {
1266
+ devDebug("[useLangie] Returning existing promise");
1267
+ return _languagesPromise;
1268
+ }
1269
+ }
1270
+ try {
1271
+ let countryHint = explicitCountry || null;
1272
+ if (!countryHint && !_languagesCache && availableLanguages.value && availableLanguages.value.length) {
1273
+ const currentLang = currentLanguage.value;
1274
+ const entry = availableLanguages.value.find(
1275
+ (l) => l.code === currentLang
1276
+ );
1277
+ if (entry) {
1278
+ const c = Array.isArray(entry.flag_country) ? entry.flag_country[0] : typeof entry.flag_country === "string" ? entry.flag_country.split(",")[0] : null;
1279
+ if (c) countryHint = c.toUpperCase();
1280
+ }
1281
+ }
1282
+ if (!countryHint && !_languagesCache && typeof window !== "undefined") {
1283
+ const cc = await getCountryCode();
1284
+ countryHint = cc;
1285
+ }
1286
+ let url = "/languages";
1287
+ const language = typeof navigator !== "undefined" && navigator.languages && navigator.languages[0] || typeof navigator !== "undefined" && navigator.language || "";
1288
+ const timezone = typeof Intl !== "undefined" && Intl.DateTimeFormat().resolvedOptions().timeZone || "";
1289
+ const params = new URLSearchParams();
1290
+ if (countryHint) params.append("country", countryHint);
1291
+ if (language) params.append("language", language);
1292
+ if (timezone) params.append("timezone", timezone);
1293
+ if (Array.from(params).length > 0) url += `?${params.toString()}`;
1294
+ _languagesPromise = fetch(`${translatorHost}${url}`).then((res) => res.json());
1295
+ const response = await _languagesPromise;
1296
+ const rawList = Array.isArray(response) ? response : response.languages || [];
1297
+ const mapped = rawList.map(
1298
+ (lang) => {
1299
+ let flag = lang.flag_country || lang.code;
1300
+ if (Array.isArray(flag)) {
1301
+ flag = flag[0];
1302
+ }
1303
+ return {
1304
+ ...lang,
1305
+ value: lang.code,
1306
+ flag_country: flag
1307
+ };
1308
+ }
1309
+ );
1310
+ const filtered = mapped.filter((l) => {
1311
+ if (l.code.startsWith("sr")) {
1312
+ return l.code === "sr-latn" || l.code === "sr-cyrl";
1313
+ }
1314
+ return true;
1315
+ });
1316
+ availableLanguages.value = filtered;
1317
+ devDebug("[useLangie] Set availableLanguages:", filtered.length);
1318
+ if (typeof window !== "undefined") {
1319
+ const saved = setCache("langie_languages_cache", filtered, 7 * 24 * 60 * 60 * 1e3);
1320
+ devDebug(
1321
+ "[useLangie] Saved languages to cache:",
1322
+ saved ? "success" : "failed",
1323
+ filtered.length
1324
+ );
1325
+ }
1326
+ if (!_autoSelected && !localStorage.getItem("interface_language")) {
1327
+ const locale = typeof navigator !== "undefined" ? navigator.languages?.[0] || navigator.language || "" : "";
1328
+ const browserCode = locale.split("-")[0];
1329
+ if (browserCode) {
1330
+ let pick = void 0;
1331
+ if (browserCode === "sr") {
1332
+ const isLatin = /latn/i.test(locale) || locale === "sr";
1333
+ const target = isLatin ? "sr-latn" : "sr-cyrl";
1334
+ pick = mapped.find((l) => l.value === target);
1335
+ } else if (browserCode === "sh") {
1336
+ pick = mapped.find((l) => l.value === "sr-latn") || mapped.find((l) => l.code.startsWith("sr"));
1337
+ } else {
1338
+ pick = mapped.find((l) => l.value === browserCode);
1339
+ if (!pick) {
1340
+ pick = mapped.find((l) => l.code.startsWith(browserCode));
1341
+ }
1342
+ }
1343
+ if (pick && pick.value) {
1344
+ setLanguage(pick.value);
1345
+ }
1346
+ }
1347
+ _autoSelected = true;
1348
+ }
1349
+ _languagesCache = filtered;
1350
+ _languagesPromise = null;
1351
+ return filtered;
1352
+ } catch (error) {
1353
+ devDebug("[useLangie] Language fetch error:", { error });
1354
+ return [];
1355
+ }
1356
+ };
1357
+ const clearTranslations = () => {
1358
+ Object.keys(translations).forEach((key) => delete translations[key]);
1359
+ Object.keys(uiTranslations).forEach((key) => delete uiTranslations[key]);
1360
+ if (typeof window !== "undefined") {
1361
+ clearCache("translations_cache");
1362
+ clearCache("ui_translations_cache");
1363
+ }
1364
+ };
1365
+ return {
1366
+ availableLanguages,
1367
+ translations,
1368
+ uiTranslations,
1369
+ currentLanguage,
1370
+ isLoading,
1371
+ setLanguage,
1372
+ fetchLanguages,
1373
+ clearTranslations,
1374
+ translatorHost
1375
+ };
1376
+ }
1377
+
1378
+ // src/composables/useLangie-batching.ts
1379
+ var TranslationBatching = class {
1380
+ constructor(options = {}, translatorHost, currentLanguage2, onBatchComplete) {
1381
+ this.options = options;
1382
+ this.translatorHost = translatorHost;
1383
+ this.currentLanguage = currentLanguage2;
1384
+ this.onBatchComplete = onBatchComplete;
1385
+ }
1386
+ pendingRequests = /* @__PURE__ */ new Set();
1387
+ queueMap = /* @__PURE__ */ new Map();
1388
+ flushTimeout = null;
1389
+ queuedThisTick = /* @__PURE__ */ new Set();
1390
+ clearQueuedThisTickScheduled = false;
1391
+ firstItemTime = null;
1392
+ get initialBatchDelay() {
1393
+ return this.options.initialBatchDelay ?? 50;
1394
+ }
1395
+ get followupBatchDelay() {
1396
+ return this.options.followupBatchDelay ?? 10;
1397
+ }
1398
+ get maxBatchSize() {
1399
+ return this.options.maxBatchSize ?? 50;
1400
+ }
1401
+ get maxWaitTime() {
1402
+ return this.options.maxWaitTime ?? 1e3;
1403
+ }
1404
+ scheduleClearQueuedThisTick() {
1405
+ if (this.clearQueuedThisTickScheduled) return;
1406
+ this.clearQueuedThisTickScheduled = true;
1407
+ queueMicrotask(() => {
1408
+ this.queuedThisTick.clear();
1409
+ this.clearQueuedThisTickScheduled = false;
1410
+ });
1411
+ }
1412
+ flushQueues = async () => {
1413
+ const allRequests = [];
1414
+ for (const [batchKey, map] of Array.from(this.queueMap.entries())) {
1415
+ if (!map || map.size === 0) {
1416
+ this.queueMap.delete(batchKey);
1417
+ continue;
1418
+ }
1419
+ const [from, to] = batchKey.split("|");
1420
+ for (const [cacheKey, item] of map.entries()) {
1421
+ allRequests.push({
1422
+ [API_FIELD_TEXT]: item[API_FIELD_TEXT],
1423
+ [API_FIELD_CTX]: item[API_FIELD_CTX],
1424
+ [API_FIELD_FROM]: from,
1425
+ [API_FIELD_TO]: to,
1426
+ cacheKey,
1427
+ __explicitToLang: item.__explicitToLang
1428
+ });
1429
+ }
1430
+ this.queueMap.delete(batchKey);
1431
+ }
1432
+ if (allRequests.length > 0) {
1433
+ devDebug(
1434
+ "[TranslationBatching] Sending batch:",
1435
+ allRequests.length,
1436
+ "translation items",
1437
+ allRequests
1438
+ );
1439
+ const chunks = this.chunkArray(allRequests, this.maxBatchSize);
1440
+ for (const chunk of chunks) {
1441
+ try {
1442
+ await this.fetchAndCacheBatchMixed(chunk);
1443
+ } catch (error) {
1444
+ devDebug("[TranslationBatching] Batch translation error:", error);
1445
+ chunk.forEach((req) => this.pendingRequests.delete(req.cacheKey));
1446
+ }
1447
+ }
1448
+ }
1449
+ this.firstItemTime = null;
1450
+ };
1451
+ chunkArray(array, size) {
1452
+ const chunks = [];
1453
+ for (let i = 0; i < array.length; i += size) {
1454
+ chunks.push(array.slice(i, i + size));
1455
+ }
1456
+ return chunks;
1457
+ }
1458
+ scheduleFlush = () => {
1459
+ if (this.flushTimeout) {
1460
+ clearTimeout(this.flushTimeout);
1461
+ }
1462
+ let totalItems = 0;
1463
+ for (const map of this.queueMap.values()) {
1464
+ totalItems += map.size;
1465
+ }
1466
+ if (this.firstItemTime && Date.now() - this.firstItemTime >= this.maxWaitTime) {
1467
+ devDebug("[TranslationBatching] Flushing due to maximum wait time:", totalItems, "items");
1468
+ this.flushQueues();
1469
+ return;
1470
+ }
1471
+ const delay = this.queueMap.size === 1 ? this.initialBatchDelay : this.followupBatchDelay;
1472
+ devDebug(
1473
+ "[TranslationBatching] Scheduling flush in",
1474
+ delay,
1475
+ "ms",
1476
+ Array.from(this.queueMap.entries())
1477
+ );
1478
+ this.flushTimeout = setTimeout(() => {
1479
+ this.flushQueues();
1480
+ this.flushTimeout = null;
1481
+ }, delay);
1482
+ };
1483
+ queueTranslation(text, ctx, from, to, cacheKey, explicitToLang) {
1484
+ if (this.pendingRequests.has(cacheKey) || this.queuedThisTick.has(cacheKey)) {
1485
+ devDebug("[TranslationBatching] Skipping duplicate:", cacheKey);
1486
+ return;
1487
+ }
1488
+ if (this.firstItemTime === null) {
1489
+ this.firstItemTime = Date.now();
1490
+ }
1491
+ this.queuedThisTick.add(cacheKey);
1492
+ this.scheduleClearQueuedThisTick();
1493
+ this.pendingRequests.add(cacheKey);
1494
+ const batchKey = `${from}|${to}`;
1495
+ if (!this.queueMap.has(batchKey)) {
1496
+ this.queueMap.set(batchKey, /* @__PURE__ */ new Map());
1497
+ }
1498
+ this.queueMap.get(batchKey).set(cacheKey, {
1499
+ [API_FIELD_TEXT]: text,
1500
+ [API_FIELD_CTX]: ctx,
1501
+ __explicitToLang: explicitToLang
1502
+ });
1503
+ devDebug("[TranslationBatching] Queued translation:", {
1504
+ text,
1505
+ ctx,
1506
+ from,
1507
+ to,
1508
+ cacheKey,
1509
+ batchKey,
1510
+ explicitToLang
1511
+ });
1512
+ this.scheduleFlush();
1513
+ }
1514
+ async fetchAndCacheBatchMixed(requests) {
1515
+ const grouped = {};
1516
+ requests.forEach((req) => {
1517
+ const key = `${req.from}|${req.to}`;
1518
+ if (!grouped[key]) grouped[key] = [];
1519
+ grouped[key].push(req);
1520
+ });
1521
+ const allResults = [];
1522
+ const allRequests = [];
1523
+ for (const [langPair, batchRequests] of Object.entries(grouped)) {
1524
+ const [from, to] = langPair.split("|");
1525
+ try {
1526
+ const contexts = [...new Set(batchRequests.map((req) => req[API_FIELD_CTX]))];
1527
+ const useGlobalContext = contexts.length === 1 && contexts[0] === "ui";
1528
+ devDebug(
1529
+ "[TranslationBatching] Sending batch for",
1530
+ langPair,
1531
+ "with",
1532
+ batchRequests.length,
1533
+ "items",
1534
+ batchRequests
1535
+ );
1536
+ const response = await fetch(`${this.translatorHost}/translate`, {
1537
+ method: "POST",
1538
+ headers: {
1539
+ "Content-Type": "application/json"
1540
+ },
1541
+ body: JSON.stringify({
1542
+ translations: batchRequests.map((req) => ({
1543
+ [API_FIELD_TEXT]: req[API_FIELD_TEXT],
1544
+ ...useGlobalContext ? {} : { [API_FIELD_CTX]: req[API_FIELD_CTX] }
1545
+ })),
1546
+ [API_FIELD_FROM]: from,
1547
+ [API_FIELD_TO]: to,
1548
+ ...useGlobalContext ? { [API_FIELD_CTX]: "ui" } : {}
1549
+ })
1550
+ });
1551
+ let result;
1552
+ try {
1553
+ result = await response.json();
1554
+ } catch (parseError) {
1555
+ devDebug("[TranslationBatching] Failed to parse response as JSON:", parseError);
1556
+ throw new Error(`Translation request failed: ${response.status}`);
1557
+ }
1558
+ if (!response.ok) {
1559
+ devDebug(
1560
+ "[TranslationBatching] Translation request failed:",
1561
+ response.status,
1562
+ response.statusText
1563
+ );
1564
+ if (result && result[API_FIELD_ERROR]) {
1565
+ devDebug(
1566
+ "[TranslationBatching] HTTP error with API error message:",
1567
+ result[API_FIELD_ERROR]
1568
+ );
1569
+ const errorResponses = batchRequests.map((req) => ({
1570
+ [API_FIELD_TEXT]: req[API_FIELD_TEXT],
1571
+ [API_FIELD_ERROR]: result[API_FIELD_ERROR]
1572
+ }));
1573
+ allResults.push({ [API_FIELD_TRANSLATIONS]: errorResponses });
1574
+ allRequests.push(...batchRequests);
1575
+ batchRequests.forEach((req) => {
1576
+ this.pendingRequests.delete(req.cacheKey);
1577
+ });
1578
+ this.onBatchComplete(allResults, allRequests);
1579
+ return;
1580
+ }
1581
+ throw new Error(`Translation request failed: ${response.status}`);
1582
+ }
1583
+ if (result[API_FIELD_ERROR]) {
1584
+ devDebug("[TranslationBatching] Top-level API error:", result[API_FIELD_ERROR]);
1585
+ const errorResponses = batchRequests.map((req) => ({
1586
+ [API_FIELD_TEXT]: req[API_FIELD_TEXT],
1587
+ [API_FIELD_ERROR]: result[API_FIELD_ERROR]
1588
+ }));
1589
+ allResults.push({ [API_FIELD_TRANSLATIONS]: errorResponses });
1590
+ allRequests.push(...batchRequests);
1591
+ batchRequests.forEach((req) => {
1592
+ this.pendingRequests.delete(req.cacheKey);
1593
+ });
1594
+ } else {
1595
+ if (result[API_FIELD_TRANSLATIONS]) {
1596
+ result[API_FIELD_TRANSLATIONS].forEach((translation, index) => {
1597
+ if (translation[API_FIELD_ERROR]) {
1598
+ const originalText = batchRequests[index]?.[API_FIELD_TEXT];
1599
+ devDebug(
1600
+ "[TranslationBatching] Translation error for",
1601
+ originalText,
1602
+ ":",
1603
+ translation[API_FIELD_ERROR]
1604
+ );
1605
+ }
1606
+ });
1607
+ }
1608
+ allResults.push(result);
1609
+ allRequests.push(...batchRequests);
1610
+ batchRequests.forEach((req) => {
1611
+ this.pendingRequests.delete(req.cacheKey);
1612
+ });
1613
+ }
1614
+ } catch (error) {
1615
+ devDebug("[TranslationBatching] Batch request failed for", langPair, ":", error);
1616
+ batchRequests.forEach((req) => {
1617
+ this.pendingRequests.delete(req.cacheKey);
1618
+ });
1619
+ throw error;
1620
+ }
1621
+ }
1622
+ this.onBatchComplete(allResults, allRequests);
1623
+ }
1624
+ clearPending(cacheKey) {
1625
+ this.pendingRequests.delete(cacheKey);
1626
+ }
1627
+ clearAllPending() {
1628
+ this.pendingRequests.clear();
1629
+ }
1630
+ cleanup() {
1631
+ this.clearAllPending();
1632
+ this.queueMap.clear();
1633
+ this.queuedThisTick.clear();
1634
+ if (this.flushTimeout) {
1635
+ clearTimeout(this.flushTimeout);
1636
+ this.flushTimeout = null;
1637
+ }
1638
+ this.clearQueuedThisTickScheduled = false;
1639
+ this.firstItemTime = null;
1640
+ }
1641
+ getStats() {
1642
+ return {
1643
+ pendingRequests: this.pendingRequests.size,
1644
+ queuedBatches: this.queueMap.size,
1645
+ queuedThisTick: this.queuedThisTick.size,
1646
+ hasFlushTimeout: !!this.flushTimeout
1647
+ };
1648
+ }
1649
+ };
1650
+
1651
+ // src/useLangie.ts
1652
+ var globalLangieInstance = null;
1653
+ if (typeof window !== "undefined" && window.__LANGIE_SINGLETON__) {
1654
+ globalLangieInstance = window.__LANGIE_SINGLETON__;
1655
+ }
1656
+ function safeLocalStorageAccess(operation) {
1657
+ if (typeof window === "undefined") return void 0;
1658
+ try {
1659
+ return operation();
1660
+ } catch (e) {
1661
+ devDebug("[useLangie] localStorage error:", e);
1662
+ return void 0;
1663
+ }
1664
+ }
1665
+ if (!globalLangieInstance && typeof window !== "undefined") {
1666
+ const stored = safeLocalStorageAccess(() => localStorage.getItem("__LANGIE_SINGLETON_URL__"));
1667
+ if (stored) {
1668
+ const storedOptions = { translatorHost: stored };
1669
+ globalLangieInstance = createLangieInstance(storedOptions);
1670
+ }
1671
+ }
1672
+ function createLangieInstance(options = {}) {
1673
+ const core = useLangieCore(options);
1674
+ const {
1675
+ availableLanguages: availableLanguages2,
1676
+ translations: translations2,
1677
+ uiTranslations: uiTranslations2,
1678
+ currentLanguage: currentLanguage2,
1679
+ isLoading,
1680
+ setLanguage,
1681
+ fetchLanguages,
1682
+ translatorHost,
1683
+ clearTranslations
1684
+ } = core;
1685
+ const ltDefaults = {
1686
+ ctx: "ui",
1687
+ orig: ""
1688
+ };
1689
+ const setLtDefaults = (defaults) => {
1690
+ Object.assign(ltDefaults, defaults);
1691
+ };
1692
+ const getLtDefaults = () => ({ ...ltDefaults });
1693
+ const CACHE_KEY = "langie_translations_cache";
1694
+ const UI_CACHE_KEY = "langie_ui_translations_cache";
1695
+ const LANGUAGES_CACHE_KEY = "langie_languages_cache";
1696
+ const loadCachedTranslations = () => {
1697
+ if (typeof window === "undefined") return;
1698
+ const cachedTranslations = getCache(CACHE_KEY);
1699
+ const cachedUiTranslations = getCache(UI_CACHE_KEY);
1700
+ if (cachedTranslations) {
1701
+ const currentLang = currentLanguage2.value;
1702
+ const langTranslations = cachedTranslations[currentLang] || {};
1703
+ Object.assign(translations2, langTranslations);
1704
+ }
1705
+ if (cachedUiTranslations) {
1706
+ const currentLang = currentLanguage2.value;
1707
+ const langUiTranslations = cachedUiTranslations[currentLang] || {};
1708
+ Object.assign(uiTranslations2, langUiTranslations);
1709
+ }
1710
+ };
1711
+ const saveCachedTranslations = () => {
1712
+ if (typeof window === "undefined") return;
1713
+ const existingTranslations = getCache(CACHE_KEY) || {};
1714
+ const existingUiTranslations = getCache(UI_CACHE_KEY) || {};
1715
+ const currentLang = currentLanguage2.value;
1716
+ existingTranslations[currentLang] = { ...translations2 };
1717
+ existingUiTranslations[currentLang] = { ...uiTranslations2 };
1718
+ setCache(CACHE_KEY, existingTranslations, 7 * 24 * 60 * 60 * 1e3);
1719
+ setCache(UI_CACHE_KEY, existingUiTranslations, 7 * 24 * 60 * 60 * 1e3);
1720
+ };
1721
+ const loadCachedLanguages = () => {
1722
+ if (typeof window === "undefined") return;
1723
+ const cachedLanguages = getCache(LANGUAGES_CACHE_KEY);
1724
+ if (cachedLanguages) {
1725
+ availableLanguages2.value = cachedLanguages;
1726
+ }
1727
+ };
1728
+ loadCachedTranslations();
1729
+ loadCachedLanguages();
1730
+ (0, import_vue5.watch)(currentLanguage2, () => {
1731
+ Object.keys(translations2).forEach((key) => delete translations2[key]);
1732
+ Object.keys(uiTranslations2).forEach((key) => delete uiTranslations2[key]);
1733
+ loadCachedTranslations();
1734
+ });
1735
+ const batching = new TranslationBatching(
1736
+ {
1737
+ initialBatchDelay: options.initialBatchDelay,
1738
+ followupBatchDelay: options.followupBatchDelay,
1739
+ maxBatchSize: options.maxBatchSize,
1740
+ maxWaitTime: options.maxWaitTime
1741
+ },
1742
+ translatorHost,
1743
+ () => currentLanguage2.value,
1744
+ (results, requests) => {
1745
+ requests.forEach((req) => {
1746
+ const cacheKey = `${req[API_FIELD_TEXT]}|${req[API_FIELD_CTX]}`;
1747
+ const languageCacheKey = `${cacheKey}|${req[API_FIELD_FROM]}|${req[API_FIELD_TO]}`;
1748
+ recentlyQueued.delete(languageCacheKey);
1749
+ });
1750
+ let translationsArray = [];
1751
+ results.forEach((result) => {
1752
+ if (Array.isArray(result)) {
1753
+ translationsArray = translationsArray.concat(result);
1754
+ } else if (result.translations && Array.isArray(result.translations)) {
1755
+ translationsArray = translationsArray.concat(result.translations);
1756
+ }
1757
+ });
1758
+ translationsArray.forEach((translation, idx) => {
1759
+ const request = requests[idx];
1760
+ if (!request) {
1761
+ devDebug("[useLangie] No matching request for translation:", translation);
1762
+ return;
1763
+ }
1764
+ const originalText = request[API_FIELD_TEXT];
1765
+ const originalCtx = request[API_FIELD_CTX] ?? (ltDefaults.ctx || "ui");
1766
+ if (translation[API_FIELD_ERROR]) {
1767
+ devDebug(
1768
+ "[useLangie] Translation error for",
1769
+ originalText,
1770
+ ":",
1771
+ translation[API_FIELD_ERROR]
1772
+ );
1773
+ const errorKey = `${originalText}|${originalCtx}|${request[API_FIELD_FROM]}|${request[API_FIELD_TO]}`;
1774
+ translationErrors.set(errorKey, translation[API_FIELD_ERROR]);
1775
+ return;
1776
+ }
1777
+ if (translation[API_FIELD_FROM] && !translation[API_FIELD_TEXT]) {
1778
+ return;
1779
+ }
1780
+ const translatedText = translation[API_FIELD_TEXT];
1781
+ if (translatedText) {
1782
+ const requestedLanguage = request[API_FIELD_TO];
1783
+ const explicitToLang = request.__explicitToLang;
1784
+ if (!explicitToLang && requestedLanguage !== currentLanguage2.value) {
1785
+ devDebug("[useLangie] Skipping outdated translation:", {
1786
+ original: originalText,
1787
+ translated: translatedText,
1788
+ requestedLanguage,
1789
+ currentLanguage: currentLanguage2.value
1790
+ });
1791
+ return;
1792
+ }
1793
+ if (translatedText === originalText) {
1794
+ devDebug("[useLangie] Skipping cache for identical translation:", {
1795
+ original: originalText,
1796
+ translated: translatedText,
1797
+ context: originalCtx
1798
+ });
1799
+ return;
1800
+ }
1801
+ const effectiveCtx = originalCtx;
1802
+ const cacheKey = `${originalText}|${effectiveCtx}`;
1803
+ const cache = effectiveCtx === "ui" ? uiTranslations2 : translations2;
1804
+ cache[cacheKey] = translatedText;
1805
+ devDebug("[useLangie] Cached translation:", {
1806
+ original: originalText,
1807
+ translated: translatedText,
1808
+ context: effectiveCtx,
1809
+ cacheKey,
1810
+ language: requestedLanguage
1811
+ });
1812
+ saveCachedTranslations();
1813
+ }
1814
+ });
1815
+ }
1816
+ );
1817
+ const recentlyQueued = /* @__PURE__ */ new Set();
1818
+ const pendingTimeouts = /* @__PURE__ */ new Set();
1819
+ const translationErrors = /* @__PURE__ */ new Map();
1820
+ const translateInternal = (text, ctx, originalLang, toLang, reactive2 = false) => {
1821
+ if (reactive2) {
1822
+ void currentLanguage2.value;
1823
+ }
1824
+ const from = originalLang || ltDefaults.orig || "";
1825
+ const to = toLang || currentLanguage2.value;
1826
+ if (from === to) {
1827
+ return text;
1828
+ }
1829
+ const effectiveCtx = ctx !== void 0 ? ctx : ltDefaults.ctx || "ui";
1830
+ const cacheKey = `${text}|${effectiveCtx}`;
1831
+ const cache = effectiveCtx === "ui" ? uiTranslations2 : translations2;
1832
+ if (cache[cacheKey]) {
1833
+ return cache[cacheKey];
1834
+ }
1835
+ const errorKey = `${text}|${effectiveCtx}|${from}|${to}`;
1836
+ if (translationErrors.has(errorKey)) {
1837
+ return text;
1838
+ }
1839
+ const languageCacheKey = `${cacheKey}|${from}|${to}`;
1840
+ if (recentlyQueued.has(languageCacheKey)) {
1841
+ return text;
1842
+ }
1843
+ batching.queueTranslation(text, effectiveCtx, from, to, cacheKey, toLang !== void 0);
1844
+ recentlyQueued.add(languageCacheKey);
1845
+ const clearDelay = 100;
1846
+ const timeoutId = setTimeout(() => {
1847
+ recentlyQueued.delete(languageCacheKey);
1848
+ pendingTimeouts.delete(timeoutId);
1849
+ }, clearDelay);
1850
+ pendingTimeouts.add(timeoutId);
1851
+ return text;
1852
+ };
1853
+ const l = (text, ctx, originalLang, toLang) => translateInternal(text, ctx, originalLang, toLang, false);
1854
+ const lr = (text, ctx, originalLang, toLang) => translateInternal(text, ctx, originalLang, toLang, true);
1855
+ const fetchAndCacheBatch = async (items, from, to = currentLanguage2.value, globalCtx) => {
1856
+ if (items.length === 0) return;
1857
+ const effectiveFrom = from || ltDefaults.orig || "";
1858
+ if (effectiveFrom === to) {
1859
+ return;
1860
+ }
1861
+ isLoading.value = true;
1862
+ try {
1863
+ const effectiveCtx = globalCtx || ltDefaults.ctx || "ui";
1864
+ const response = await fetch(`${translatorHost}/translate`, {
1865
+ method: "POST",
1866
+ headers: {
1867
+ "Content-Type": "application/json"
1868
+ },
1869
+ body: JSON.stringify({
1870
+ translations: items.map((item) => ({
1871
+ [API_FIELD_TEXT]: item[API_FIELD_TEXT],
1872
+ [API_FIELD_CTX]: item[API_FIELD_CTX] || effectiveCtx
1873
+ })),
1874
+ [API_FIELD_FROM]: effectiveFrom,
1875
+ [API_FIELD_TO]: to
1876
+ })
1877
+ });
1878
+ if (!response.ok) {
1879
+ throw new Error(`Translation request failed: ${response.status}`);
1880
+ }
1881
+ const result = await response.json();
1882
+ if (result[API_FIELD_ERROR]) {
1883
+ devDebug("[useLangie] Top-level API error:", result[API_FIELD_ERROR]);
1884
+ const errorResponses = items.map((item) => ({
1885
+ [API_FIELD_TEXT]: item[API_FIELD_TEXT],
1886
+ [API_FIELD_ERROR]: result[API_FIELD_ERROR]
1887
+ }));
1888
+ errorResponses.forEach((translation, index) => {
1889
+ const item = items[index];
1890
+ const originalText = item?.[API_FIELD_TEXT];
1891
+ if (!originalText) {
1892
+ return;
1893
+ }
1894
+ if (translation[API_FIELD_ERROR]) {
1895
+ devDebug(
1896
+ "[useLangie] Translation error for",
1897
+ originalText,
1898
+ ":",
1899
+ translation[API_FIELD_ERROR]
1900
+ );
1901
+ const errorKey = `${originalText}|${item[API_FIELD_CTX] || effectiveCtx}|${effectiveFrom}|${to}`;
1902
+ translationErrors.set(errorKey, translation[API_FIELD_ERROR]);
1903
+ return;
1904
+ }
1905
+ });
1906
+ return;
1907
+ }
1908
+ if (result[API_FIELD_TRANSLATIONS]) {
1909
+ result[API_FIELD_TRANSLATIONS].forEach(
1910
+ (translation, index) => {
1911
+ const item = items[index];
1912
+ const originalText = item?.[API_FIELD_TEXT];
1913
+ if (!originalText) {
1914
+ return;
1915
+ }
1916
+ if (translation[API_FIELD_ERROR]) {
1917
+ devDebug(
1918
+ "[useLangie] Translation error for",
1919
+ originalText,
1920
+ ":",
1921
+ translation[API_FIELD_ERROR]
1922
+ );
1923
+ return;
1924
+ }
1925
+ if (translation[API_FIELD_FROM] && !translation[API_FIELD_TEXT]) {
1926
+ return;
1927
+ }
1928
+ const translatedText = translation[API_FIELD_TEXT];
1929
+ if (translatedText) {
1930
+ if (to !== currentLanguage2.value) {
1931
+ devDebug("[useLangie] Skipping outdated translation (batch):", {
1932
+ original: originalText,
1933
+ translated: translatedText,
1934
+ requestedLanguage: to,
1935
+ currentLanguage: currentLanguage2.value
1936
+ });
1937
+ return;
1938
+ }
1939
+ if (translatedText === originalText) {
1940
+ devDebug("[useLangie] Skipping cache for identical translation (batch):", {
1941
+ original: originalText,
1942
+ translated: translatedText,
1943
+ context: item[API_FIELD_CTX] || effectiveCtx
1944
+ });
1945
+ return;
1946
+ }
1947
+ const originalCtx = item[API_FIELD_CTX];
1948
+ const translationCtx = originalCtx !== void 0 ? originalCtx : effectiveCtx;
1949
+ const cacheKey = `${originalText}|${translationCtx}`;
1950
+ const cache = translationCtx === "ui" ? uiTranslations2 : translations2;
1951
+ cache[cacheKey] = translatedText;
1952
+ devDebug("[useLangie] Cached translation (batch):", {
1953
+ original: originalText,
1954
+ translated: translatedText,
1955
+ context: translationCtx,
1956
+ cacheKey,
1957
+ language: to
1958
+ });
1959
+ saveCachedTranslations();
1960
+ }
1961
+ }
1962
+ );
1963
+ }
1964
+ } catch (error) {
1965
+ console.error("[useLangie] Translation error:", error);
1966
+ } finally {
1967
+ isLoading.value = false;
1968
+ }
1969
+ };
1970
+ (0, import_vue5.watch)(currentLanguage2, () => {
1971
+ recentlyQueued.clear();
1972
+ loadCachedTranslations();
1973
+ batching.cleanup();
1974
+ });
1975
+ return {
1976
+ // Core functionality
1977
+ availableLanguages: availableLanguages2,
1978
+ translations: translations2,
1979
+ uiTranslations: uiTranslations2,
1980
+ currentLanguage: currentLanguage2,
1981
+ isLoading,
1982
+ setLanguage,
1983
+ fetchLanguages,
1984
+ translatorHost,
1985
+ // Translation functions
1986
+ l,
1987
+ lr,
1988
+ fetchAndCacheBatch,
1989
+ // Error handling
1990
+ getTranslationError: (text, ctx, from, to) => {
1991
+ const effectiveCtx = ctx !== void 0 ? ctx : ltDefaults.ctx || "ui";
1992
+ const effectiveFrom = from || ltDefaults.orig || "";
1993
+ const effectiveTo = to || currentLanguage2.value;
1994
+ const errorKey = `${text}|${effectiveCtx}|${effectiveFrom}|${effectiveTo}`;
1995
+ return translationErrors.get(errorKey) || null;
1996
+ },
1997
+ // Utility functions
1998
+ cleanup: () => {
1999
+ clearTranslations();
2000
+ batching.cleanup();
2001
+ pendingTimeouts.forEach((id) => clearTimeout(id));
2002
+ pendingTimeouts.clear();
2003
+ translationErrors.clear();
2004
+ },
2005
+ getBatchingStats: () => batching.getStats(),
2006
+ // lt component defaults management
2007
+ setLtDefaults,
2008
+ getLtDefaults
2009
+ };
2010
+ }
2011
+ function getGlobalLangieInstance() {
2012
+ if (typeof window !== "undefined") {
2013
+ return window.__LANGIE_SINGLETON__ || null;
2014
+ }
2015
+ return globalLangieInstance;
2016
+ }
2017
+ function setGlobalLangieInstance(instance, options) {
2018
+ if (typeof window !== "undefined") {
2019
+ ;
2020
+ window.__LANGIE_SINGLETON__ = instance;
2021
+ if (options && options.translatorHost) {
2022
+ safeLocalStorageAccess(
2023
+ () => localStorage.setItem("__LANGIE_SINGLETON_URL__", options.translatorHost)
2024
+ );
2025
+ }
2026
+ }
2027
+ globalLangieInstance = instance;
2028
+ }
2029
+ function useLangie(options = {}) {
2030
+ const globalInstance = getGlobalLangieInstance();
2031
+ if (globalInstance) {
2032
+ const currentHost = globalInstance.translatorHost;
2033
+ const newHost = options.translatorHost;
2034
+ if (!options.translatorHost || currentHost === newHost) {
2035
+ return globalInstance;
2036
+ }
2037
+ }
2038
+ const instance = createLangieInstance(options);
2039
+ setGlobalLangieInstance(instance, options);
2040
+ return instance;
2041
+ }
2042
+
2043
+ // vue-script:/Users/nlit/projects/langie-sdk/src/components/InterfaceLanguageSelect.vue?type=script
2044
+ var _hoisted_12 = { class: "interface-language-select-wrapper" };
2045
+ var _hoisted_22 = { class: "loader-text" };
2046
+ var InterfaceLanguageSelect_default = /* @__PURE__ */ (0, import_vue6.defineComponent)({
2047
+ __name: "InterfaceLanguageSelect",
2048
+ props: {
2049
+ placeholder: {
2050
+ type: String,
2051
+ default: "Select interface language"
2052
+ },
2053
+ disabled: {
2054
+ type: Boolean,
2055
+ default: false
2056
+ },
2057
+ isDark: {
2058
+ type: Boolean,
2059
+ default: false
2060
+ },
2061
+ translatorHost: {
2062
+ type: String,
2063
+ default: ""
2064
+ },
2065
+ apiKey: {
2066
+ type: String,
2067
+ default: ""
2068
+ },
2069
+ languages: {
2070
+ type: Array,
2071
+ default: () => []
2072
+ }
2073
+ },
2074
+ emits: ["update:modelValue"],
2075
+ setup(__props, { emit: __emit }) {
2076
+ const isChangingLanguage = (0, import_vue8.ref)(false);
2077
+ const props = __props;
2078
+ const emit = __emit;
2079
+ const { availableLanguages: availableLanguages2, currentLanguage: currentLanguage2, setLanguage, fetchLanguages, lr } = useLangie();
2080
+ const effectiveLanguages = (0, import_vue8.computed)(() => {
2081
+ const languages = props.languages && props.languages.length > 0 ? props.languages : availableLanguages2.value;
2082
+ const processed = languages.map((lang) => ({
2083
+ ...lang,
2084
+ native_name: lang.native_name || lang.name,
2085
+ flag_country: lang.flag_country || lang.code
2086
+ }));
2087
+ return processed;
2088
+ });
2089
+ const currentLanguageObject = (0, import_vue8.computed)(() => {
2090
+ if (!currentLanguage2.value) return null;
2091
+ return effectiveLanguages.value.find((lang) => lang.code === currentLanguage2.value) || null;
2092
+ });
2093
+ function detectBrowserLanguage(languages) {
2094
+ if (languages.length === 0) return null;
2095
+ const browserLanguages = navigator.languages || [navigator.language || "en"];
2096
+ for (const browserLang of browserLanguages) {
2097
+ const langCode = browserLang.toLowerCase().split("-")[0];
2098
+ const exactMatch = languages.find((lang) => lang.code.toLowerCase() === langCode);
2099
+ if (exactMatch) {
2100
+ return exactMatch.code;
2101
+ }
2102
+ }
2103
+ for (const browserLang of browserLanguages) {
2104
+ const fullLangCode = browserLang.toLowerCase();
2105
+ const localeMatch = languages.find((lang) => lang.code.toLowerCase() === fullLangCode);
2106
+ if (localeMatch) {
2107
+ return localeMatch.code;
2108
+ }
2109
+ }
2110
+ return null;
2111
+ }
2112
+ async function handleLanguageChange(selectedLanguage) {
2113
+ if (selectedLanguage) {
2114
+ isChangingLanguage.value = true;
2115
+ try {
2116
+ setLanguage(selectedLanguage.code);
2117
+ localStorage.setItem("interface_language", selectedLanguage.code);
2118
+ emit("update:modelValue", selectedLanguage);
2119
+ } finally {
2120
+ isChangingLanguage.value = false;
2121
+ }
2122
+ }
2123
+ }
2124
+ (0, import_vue8.watch)(currentLanguage2, (newLangCode) => {
2125
+ if (newLangCode) {
2126
+ localStorage.setItem("interface_language", newLangCode);
2127
+ }
2128
+ });
2129
+ (0, import_vue8.watch)(
2130
+ () => effectiveLanguages.value,
2131
+ (newLanguages) => {
2132
+ if (newLanguages.length > 0 && !currentLanguage2.value) {
2133
+ const savedLanguageCode = localStorage.getItem("interface_language");
2134
+ if (savedLanguageCode) {
2135
+ const savedLangExists = newLanguages.find((lang) => lang.code === savedLanguageCode);
2136
+ if (savedLangExists) {
2137
+ setLanguage(savedLanguageCode);
2138
+ return;
2139
+ }
2140
+ }
2141
+ const browserLang = detectBrowserLanguage(newLanguages);
2142
+ if (browserLang) {
2143
+ setLanguage(browserLang);
2144
+ }
2145
+ }
2146
+ },
2147
+ { immediate: true }
2148
+ );
2149
+ (0, import_vue8.onMounted)(async () => {
2150
+ if (!props.languages || props.languages.length === 0) {
2151
+ const countryCode = await getCountryCode();
2152
+ await fetchLanguages({ country: countryCode || void 0 });
2153
+ }
2154
+ const savedLanguageCode = localStorage.getItem("interface_language");
2155
+ if (savedLanguageCode && savedLanguageCode !== currentLanguage2.value) {
2156
+ const currentLanguages = effectiveLanguages.value;
2157
+ const savedLangExists = currentLanguages.find((lang) => lang.code === savedLanguageCode);
2158
+ if (savedLangExists) {
2159
+ setLanguage(savedLanguageCode);
2160
+ } else if (currentLanguages.length > 0) {
2161
+ const browserLang = detectBrowserLanguage(currentLanguages);
2162
+ if (browserLang) {
2163
+ setLanguage(browserLang);
2164
+ }
2165
+ }
2166
+ } else if (!currentLanguage2.value && effectiveLanguages.value.length > 0) {
2167
+ const browserLang = detectBrowserLanguage(effectiveLanguages.value);
2168
+ if (browserLang) {
2169
+ setLanguage(browserLang);
2170
+ }
2171
+ }
2172
+ });
2173
+ (0, import_vue8.watch)(
2174
+ currentLanguageObject,
2175
+ (newValue) => {
2176
+ if (newValue) {
2177
+ emit("update:modelValue", newValue);
2178
+ }
2179
+ },
2180
+ { immediate: true }
2181
+ );
2182
+ return (_ctx, _cache) => {
2183
+ return (0, import_vue7.openBlock)(), (0, import_vue7.createElementBlock)("div", _hoisted_12, [
2184
+ ((0, import_vue7.openBlock)(), (0, import_vue7.createBlock)(LanguageSelect_default2, {
2185
+ key: `interface-lang-${effectiveLanguages.value.length}-${effectiveLanguages.value[0]?.code || "empty"}`,
2186
+ "model-value": currentLanguageObject.value,
2187
+ languages: effectiveLanguages.value,
2188
+ placeholder: props.placeholder,
2189
+ disabled: props.disabled || isChangingLanguage.value,
2190
+ "is-dark": props.isDark,
2191
+ "onUpdate:modelValue": handleLanguageChange
2192
+ }, null, 8, ["model-value", "languages", "placeholder", "disabled", "is-dark"])),
2193
+ (0, import_vue7.createCommentVNode)(" Loading overlay "),
2194
+ isChangingLanguage.value ? ((0, import_vue7.openBlock)(), (0, import_vue7.createElementBlock)(
2195
+ "div",
2196
+ {
2197
+ key: 0,
2198
+ class: (0, import_vue7.normalizeClass)(["language-change-loader", { "is-dark": props.isDark }])
2199
+ },
2200
+ [
2201
+ _cache[0] || (_cache[0] = (0, import_vue7.createElementVNode)(
2202
+ "div",
2203
+ { class: "loader-spinner" },
2204
+ null,
2205
+ -1
2206
+ /* CACHED */
2207
+ )),
2208
+ (0, import_vue7.createElementVNode)(
2209
+ "span",
2210
+ _hoisted_22,
2211
+ (0, import_vue7.toDisplayString)((0, import_vue7.unref)(lr)("Changing language...", "ui")),
2212
+ 1
2213
+ /* TEXT */
2214
+ )
2215
+ ],
2216
+ 2
2217
+ /* CLASS */
2218
+ )) : (0, import_vue7.createCommentVNode)("v-if", true)
2219
+ ]);
2220
+ };
2221
+ }
2222
+ });
2223
+
2224
+ // src/components/InterfaceLanguageSelect.vue
2225
+ var InterfaceLanguageSelect_default2 = InterfaceLanguageSelect_default;
2226
+ InterfaceLanguageSelect_default.__scopeId = "data-v-7192f8c0";
2227
+
2228
+ // vue-script:/Users/nlit/projects/langie-sdk/src/components/lt.vue?type=script
2229
+ var import_vue9 = require("vue");
2230
+ var import_vue10 = require("vue");
2231
+ var import_vue11 = require("vue");
2232
+ var import_vue12 = require("vue");
2233
+ var lt_default = /* @__PURE__ */ (0, import_vue9.defineComponent)({
2234
+ __name: "lt",
2235
+ props: {
2236
+ // Message key (optional, otherwise slot content is used)
2237
+ msg: {
2238
+ type: String,
2239
+ default: void 0
2240
+ },
2241
+ // Translation context shorthand
2242
+ ctx: {
2243
+ type: String,
2244
+ required: false,
2245
+ default: "ui"
2246
+ },
2247
+ // Original language shorthand
2248
+ orig: {
2249
+ type: String,
2250
+ required: false,
2251
+ default: void 0
2252
+ }
2253
+ },
2254
+ setup(__props) {
2255
+ const isNuxt = (0, import_vue11.computed)(() => {
2256
+ if (typeof window !== "undefined") {
2257
+ return !!window.__NUXT__;
2258
+ }
2259
+ if (typeof process !== "undefined") {
2260
+ return !!process.env.NUXT_SSR_BASE || !!process.env.NUXT_PUBLIC_BASE_URL;
2261
+ }
2262
+ return false;
2263
+ });
2264
+ const props = __props;
2265
+ const slots = (0, import_vue11.useSlots)();
2266
+ const { lr, currentLanguage: currentLanguage2, uiTranslations: uiTranslations2, translations: translations2, getLtDefaults } = useLangie();
2267
+ const keyStr = (0, import_vue11.computed)(() => {
2268
+ if (props.msg) return props.msg;
2269
+ const slotContent = slots.default ? slots.default().map((n) => n.children).join("") : "";
2270
+ return (slotContent || "").trim();
2271
+ });
2272
+ const forceUpdate = (0, import_vue12.ref)(0);
2273
+ (0, import_vue11.watch)(
2274
+ [uiTranslations2, translations2],
2275
+ () => {
2276
+ (0, import_vue12.nextTick)(() => {
2277
+ forceUpdate.value++;
2278
+ });
2279
+ },
2280
+ { deep: true }
2281
+ );
2282
+ const translated = (0, import_vue11.computed)(() => {
2283
+ if (isNuxt.value && typeof window === "undefined") {
2284
+ return keyStr.value;
2285
+ }
2286
+ const globalDefaults = getLtDefaults();
2287
+ const effectiveCtx = props.ctx ?? globalDefaults.ctx;
2288
+ const effectiveOrig = props.orig ?? globalDefaults.orig;
2289
+ void currentLanguage2.value;
2290
+ void forceUpdate.value;
2291
+ const cacheKey = `${keyStr.value}|${effectiveCtx}`;
2292
+ const cache = effectiveCtx === "ui" ? uiTranslations2 : translations2;
2293
+ void cache[cacheKey];
2294
+ const result = lr(keyStr.value, effectiveCtx, effectiveOrig);
2295
+ return result;
2296
+ });
2297
+ return (_ctx, _cache) => {
2298
+ return (0, import_vue10.openBlock)(), (0, import_vue10.createBlock)(import_vue10.Transition, {
2299
+ name: "fade",
2300
+ mode: "out-in"
2301
+ }, {
2302
+ default: (0, import_vue10.withCtx)(() => [
2303
+ ((0, import_vue10.openBlock)(), (0, import_vue10.createElementBlock)(
2304
+ "span",
2305
+ { key: translated.value },
2306
+ (0, import_vue10.toDisplayString)(translated.value),
2307
+ 1
2308
+ /* TEXT */
2309
+ ))
2310
+ ]),
2311
+ _: 1
2312
+ /* STABLE */
2313
+ });
2314
+ };
2315
+ }
2316
+ });
2317
+
2318
+ // src/components/lt.vue
2319
+ var lt_default2 = lt_default;
2320
+ lt_default.__scopeId = "data-v-14a7b6f6";
2321
+ // Annotate the CommonJS export names for ESM import in node:
2322
+ 0 && (module.exports = {
2323
+ InterfaceLanguageSelect,
2324
+ LanguageSelect,
2325
+ lt
2326
+ });
2327
+ //# sourceMappingURL=index.cjs.map