@hua-labs/i18n-core 2.2.0 → 2.2.1

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/index.cjs CHANGED
@@ -10,9 +10,17 @@ var React__default = /*#__PURE__*/_interopDefault(React);
10
10
  // src/index.ts
11
11
 
12
12
  // src/types/index.ts
13
- var PLURAL_CATEGORIES = /* @__PURE__ */ new Set(["zero", "one", "two", "few", "many", "other"]);
13
+ var PLURAL_CATEGORIES = /* @__PURE__ */ new Set([
14
+ "zero",
15
+ "one",
16
+ "two",
17
+ "few",
18
+ "many",
19
+ "other"
20
+ ]);
14
21
  function isPluralValue(value) {
15
- if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
22
+ if (typeof value !== "object" || value === null || Array.isArray(value))
23
+ return false;
16
24
  const obj = value;
17
25
  const keys = Object.keys(obj);
18
26
  return keys.length > 0 && keys.every((k) => PLURAL_CATEGORIES.has(k)) && Object.values(obj).every((v) => typeof v === "string") && typeof obj.other === "string";
@@ -110,7 +118,9 @@ var Translator = class {
110
118
  this.currentLang = config.defaultLanguage;
111
119
  if (config.initialTranslations) {
112
120
  this.allTranslations = config.initialTranslations;
113
- for (const [language, namespaces] of Object.entries(config.initialTranslations)) {
121
+ for (const [language, namespaces] of Object.entries(
122
+ config.initialTranslations
123
+ )) {
114
124
  for (const namespace of Object.keys(namespaces)) {
115
125
  this.loadedNamespaces.add(`${language}:${namespace}`);
116
126
  }
@@ -208,9 +218,15 @@ var Translator = class {
208
218
  }
209
219
  }
210
220
  if (this.config.debug) {
211
- console.log("\u{1F30D} [TRANSLATOR] Initializing translator with languages:", languages);
221
+ console.log(
222
+ "\u{1F30D} [TRANSLATOR] Initializing translator with languages:",
223
+ languages
224
+ );
212
225
  console.log("\u{1F4CD} [TRANSLATOR] Current language:", this.currentLang);
213
- console.log("\u{1F4E6} [TRANSLATOR] Config namespaces:", this.config.namespaces);
226
+ console.log(
227
+ "\u{1F4E6} [TRANSLATOR] Config namespaces:",
228
+ this.config.namespaces
229
+ );
214
230
  }
215
231
  for (const language of languages) {
216
232
  if (this.config.debug) {
@@ -223,12 +239,23 @@ var Translator = class {
223
239
  const cacheKey = `${language}:${namespace}`;
224
240
  if (skipNamespaces.has(cacheKey)) {
225
241
  if (this.config.debug) {
226
- console.log("\u23ED\uFE0F [TRANSLATOR] Skipping", namespace, "for", language, "(already loaded from SSR)");
242
+ console.log(
243
+ "\u23ED\uFE0F [TRANSLATOR] Skipping",
244
+ namespace,
245
+ "for",
246
+ language,
247
+ "(already loaded from SSR)"
248
+ );
227
249
  }
228
250
  continue;
229
251
  }
230
252
  if (this.config.debug) {
231
- console.log("Loading namespace:", namespace, "for language:", language);
253
+ console.log(
254
+ "Loading namespace:",
255
+ namespace,
256
+ "for language:",
257
+ language
258
+ );
232
259
  }
233
260
  try {
234
261
  const data = await this.safeLoadTranslations(language, namespace);
@@ -248,7 +275,10 @@ var Translator = class {
248
275
  if (isRecoverableError(translationError)) {
249
276
  if (language !== this.config.fallbackLanguage) {
250
277
  try {
251
- const fallbackData = await this.safeLoadTranslations(this.config.fallbackLanguage || "en", namespace);
278
+ const fallbackData = await this.safeLoadTranslations(
279
+ this.config.fallbackLanguage || "en",
280
+ namespace
281
+ );
252
282
  this.allTranslations[language][namespace] = fallbackData;
253
283
  this.loadedNamespaces.add(`${language}:${namespace}`);
254
284
  if (this.config.debug) {
@@ -286,7 +316,9 @@ var Translator = class {
286
316
  this.logError(this.initializationError);
287
317
  this.isInitialized = true;
288
318
  if (this.config.debug) {
289
- console.warn("Translator initialized with errors, using fallback translations");
319
+ console.warn(
320
+ "Translator initialized with errors, using fallback translations"
321
+ );
290
322
  }
291
323
  }
292
324
  }
@@ -301,7 +333,10 @@ var Translator = class {
301
333
  const result = this.findInNamespace(namespace, actualKey, targetLang);
302
334
  if (result) {
303
335
  if (this.config.debug) {
304
- console.log(`\u2705 [TRANSLATOR] Found fallback translation from initialTranslations:`, result);
336
+ console.log(
337
+ `\u2705 [TRANSLATOR] Found fallback translation from initialTranslations:`,
338
+ result
339
+ );
305
340
  }
306
341
  return result;
307
342
  }
@@ -365,10 +400,17 @@ var Translator = class {
365
400
  }
366
401
  if (!this.isInitialized) {
367
402
  const raw = this.translateBeforeInitialized(key, targetLang);
403
+ if ((!raw || raw === key) && params && typeof params === "object" && "defaultValue" in params && typeof params.defaultValue === "string") {
404
+ return this.interpolate(params.defaultValue, params);
405
+ }
368
406
  return params ? this.interpolate(raw, params) : raw;
369
407
  }
370
408
  const { namespace, key: actualKey } = this.parseKey(key);
371
- let result = this.findInNamespace(namespace, actualKey, targetLang);
409
+ let result = this.findInNamespace(
410
+ namespace,
411
+ actualKey,
412
+ targetLang
413
+ );
372
414
  if (result) {
373
415
  this.cacheStats.hits++;
374
416
  return params ? this.interpolate(result, params) : result;
@@ -382,6 +424,9 @@ var Translator = class {
382
424
  return params ? this.interpolate(result, params) : result;
383
425
  }
384
426
  this.cacheStats.misses++;
427
+ if (params && typeof params === "object" && "defaultValue" in params && typeof params.defaultValue === "string") {
428
+ return this.interpolate(params.defaultValue, params);
429
+ }
385
430
  if (this.config.debug) {
386
431
  const missing = this.config.missingKeyHandler?.(key, targetLang, namespace) || key;
387
432
  return params ? this.interpolate(missing, params) : missing;
@@ -398,11 +443,16 @@ var Translator = class {
398
443
  if (!this.loadedNamespaces.has(cacheKey) && !this.loadingPromises.has(cacheKey)) {
399
444
  this.loadTranslationData(language, namespace).catch((error) => {
400
445
  if (this.config.debug) {
401
- console.warn(`\u26A0\uFE0F [TRANSLATOR] Auto-load failed for ${language}/${namespace}:`, error);
446
+ console.warn(
447
+ `\u26A0\uFE0F [TRANSLATOR] Auto-load failed for ${language}/${namespace}:`,
448
+ error
449
+ );
402
450
  }
403
451
  });
404
452
  if (this.config.debug) {
405
- console.warn(`\u274C [TRANSLATOR] No translations found for ${language}/${namespace}, attempting auto-load...`);
453
+ console.warn(
454
+ `\u274C [TRANSLATOR] No translations found for ${language}/${namespace}, attempting auto-load...`
455
+ );
406
456
  }
407
457
  }
408
458
  return "";
@@ -422,7 +472,9 @@ var Translator = class {
422
472
  return nestedValue[Math.floor(Math.random() * nestedValue.length)];
423
473
  }
424
474
  if (this.config.debug) {
425
- console.warn(`\u274C [TRANSLATOR] No match found for key: ${key} in ${language}/${namespace}`);
475
+ console.warn(
476
+ `\u274C [TRANSLATOR] No match found for key: ${key} in ${language}/${namespace}`
477
+ );
426
478
  }
427
479
  return "";
428
480
  }
@@ -488,7 +540,10 @@ var Translator = class {
488
540
  if (actualKey in fallbackTranslations) {
489
541
  return fallbackTranslations[actualKey];
490
542
  }
491
- const fallbackNestedValue = this.getNestedValue(fallbackTranslations, actualKey);
543
+ const fallbackNestedValue = this.getNestedValue(
544
+ fallbackTranslations,
545
+ actualKey
546
+ );
492
547
  if (fallbackNestedValue !== void 0) {
493
548
  return fallbackNestedValue;
494
549
  }
@@ -534,7 +589,9 @@ var Translator = class {
534
589
  const raw = this.getRawValue(key, targetLang);
535
590
  const mergedParams = { count, ...params };
536
591
  if (isPluralValue(raw)) {
537
- const category = this.getPluralRules(targetLang).select(count);
592
+ const category = this.getPluralRules(targetLang).select(
593
+ count
594
+ );
538
595
  const text = raw[category] ?? raw.other;
539
596
  return this.interpolate(text, mergedParams);
540
597
  }
@@ -577,7 +634,9 @@ var Translator = class {
577
634
  });
578
635
  }
579
636
  if (this.config.debug) {
580
- console.log(`\u{1F310} [TRANSLATOR] Language changed: ${previousLanguage} -> ${language}`);
637
+ console.log(
638
+ `\u{1F310} [TRANSLATOR] Language changed: ${previousLanguage} -> ${language}`
639
+ );
581
640
  }
582
641
  }
583
642
  /**
@@ -689,7 +748,11 @@ var Translator = class {
689
748
  */
690
749
  logError(error) {
691
750
  if (this.config.errorHandler) {
692
- this.config.errorHandler(error, error.language || "", error.namespace || "");
751
+ this.config.errorHandler(
752
+ error,
753
+ error.language || "",
754
+ error.namespace || ""
755
+ );
693
756
  }
694
757
  }
695
758
  /**
@@ -712,7 +775,9 @@ var Translator = class {
712
775
  if (attempt === maxRetries) {
713
776
  break;
714
777
  }
715
- await new Promise((resolve) => setTimeout(resolve, Math.pow(2, attempt) * 1e3));
778
+ await new Promise(
779
+ (resolve) => setTimeout(resolve, Math.pow(2, attempt) * 1e3)
780
+ );
716
781
  }
717
782
  }
718
783
  throw lastError;
@@ -722,21 +787,29 @@ var Translator = class {
722
787
  */
723
788
  async safeLoadTranslations(language, namespace) {
724
789
  if (this.config.debug) {
725
- console.log(`\u{1F4E5} [TRANSLATOR] safeLoadTranslations called:`, { language, namespace });
790
+ console.log(`\u{1F4E5} [TRANSLATOR] safeLoadTranslations called:`, {
791
+ language,
792
+ namespace
793
+ });
726
794
  }
727
795
  const loadOperation = async () => {
728
796
  if (!this.config.loadTranslations) {
729
797
  throw new Error("No translation loader configured");
730
798
  }
731
799
  if (this.config.debug) {
732
- console.log(`\u{1F504} [TRANSLATOR] Calling loadTranslations for:`, { language, namespace });
800
+ console.log(`\u{1F504} [TRANSLATOR] Calling loadTranslations for:`, {
801
+ language,
802
+ namespace
803
+ });
733
804
  }
734
805
  const data = await this.config.loadTranslations(language, namespace);
735
806
  if (this.config.debug) {
736
807
  console.log(`\u{1F4E6} [TRANSLATOR] loadTranslations returned:`, data);
737
808
  }
738
809
  if (!isTranslationNamespace(data)) {
739
- throw new Error(`Invalid translation data for ${language}:${namespace}`);
810
+ throw new Error(
811
+ `Invalid translation data for ${language}:${namespace}`
812
+ );
740
813
  }
741
814
  return data;
742
815
  };
@@ -749,7 +822,10 @@ var Translator = class {
749
822
  language,
750
823
  namespace
751
824
  );
752
- return this.retryOperation(loadOperation, translationError, { language, namespace });
825
+ return this.retryOperation(loadOperation, translationError, {
826
+ language,
827
+ namespace
828
+ });
753
829
  }
754
830
  }
755
831
  /**
@@ -786,35 +862,30 @@ var Translator = class {
786
862
  if (!this.isInitialized) {
787
863
  await this.initialize();
788
864
  }
789
- const translated = this.translate(key);
790
- if (!params) {
791
- return translated;
792
- }
793
- return this.interpolate(translated, params);
865
+ return this.translate(key, params);
794
866
  }
795
867
  /**
796
868
  * 동기 번역 (고급 기능)
797
869
  */
798
870
  translateSync(key, params) {
799
871
  if (!this.isInitialized) {
872
+ if (params && typeof params === "object" && "defaultValue" in params && typeof params.defaultValue === "string") {
873
+ return this.interpolate(params.defaultValue, params);
874
+ }
800
875
  if (this.config.debug) {
801
876
  console.warn("Translator not initialized for sync translation");
802
877
  }
803
878
  const { namespace } = this.parseKey(key);
804
879
  return this.config.missingKeyHandler?.(key, this.currentLang, namespace) || key;
805
880
  }
806
- const translated = this.translate(key);
807
- if (!params) {
808
- return translated;
809
- }
810
- return this.interpolate(translated, params);
881
+ return this.translate(key, params);
811
882
  }
812
883
  /**
813
884
  * 키 파싱 (네임스페이스:키 형식)
814
- *
885
+ *
815
886
  * - 콜론(:)만 네임스페이스 구분자로 사용
816
887
  * - 점(.)은 키 이름의 일부로 취급 (중첩 객체 접근용)
817
- *
888
+ *
818
889
  * @example
819
890
  * parseKey("home:hero.badge") → { namespace: "home", key: "hero.badge" }
820
891
  * parseKey("hero.badge") → { namespace: "common", key: "hero.badge" }
@@ -823,7 +894,10 @@ var Translator = class {
823
894
  parseKey(key) {
824
895
  const colonIndex = key.indexOf(":");
825
896
  if (colonIndex !== -1) {
826
- return { namespace: key.substring(0, colonIndex), key: key.substring(colonIndex + 1) };
897
+ return {
898
+ namespace: key.substring(0, colonIndex),
899
+ key: key.substring(colonIndex + 1)
900
+ };
827
901
  }
828
902
  return { namespace: "common", key };
829
903
  }
@@ -862,7 +936,9 @@ var Translator = class {
862
936
  this.loadedNamespaces.add(cacheKey);
863
937
  this.setCacheEntry(cacheKey, data);
864
938
  if (this.config.debug) {
865
- console.log(`\u2705 [TRANSLATOR] Auto-loaded and saved ${language}/${namespace}`);
939
+ console.log(
940
+ `\u2705 [TRANSLATOR] Auto-loaded and saved ${language}/${namespace}`
941
+ );
866
942
  }
867
943
  this.notifyTranslationLoaded(language, namespace);
868
944
  return data;
@@ -880,7 +956,9 @@ var Translator = class {
880
956
  try {
881
957
  const data = await this.config.loadTranslations(language, namespace);
882
958
  if (!isTranslationNamespace(data)) {
883
- throw new Error(`Invalid translation data for ${language}:${namespace}`);
959
+ throw new Error(
960
+ `Invalid translation data for ${language}:${namespace}`
961
+ );
884
962
  }
885
963
  return data;
886
964
  } catch (error) {
@@ -903,12 +981,20 @@ function ssrTranslate({
903
981
  missingKeyHandler = (key2) => key2
904
982
  }) {
905
983
  const { namespace, key: actualKey } = parseKey(key);
906
- let result = ssrFindInNamespace(translations, namespace, actualKey, language);
984
+ let result = ssrFindInNamespace(
985
+ translations,
986
+ namespace,
987
+ actualKey,
988
+ language);
907
989
  if (result) {
908
990
  return result;
909
991
  }
910
992
  if (language !== fallbackLanguage) {
911
- result = ssrFindInNamespace(translations, namespace, actualKey, fallbackLanguage);
993
+ result = ssrFindInNamespace(
994
+ translations,
995
+ namespace,
996
+ actualKey,
997
+ fallbackLanguage);
912
998
  if (result) {
913
999
  return result;
914
1000
  }
@@ -947,7 +1033,10 @@ function isStringValue(value) {
947
1033
  function parseKey(key) {
948
1034
  const colonIndex = key.indexOf(":");
949
1035
  if (colonIndex !== -1) {
950
- return { namespace: key.substring(0, colonIndex), key: key.substring(colonIndex + 1) };
1036
+ return {
1037
+ namespace: key.substring(0, colonIndex),
1038
+ key: key.substring(colonIndex + 1)
1039
+ };
951
1040
  }
952
1041
  return { namespace: "common", key };
953
1042
  }
@@ -969,7 +1058,11 @@ function serverTranslate({
969
1058
  return cached;
970
1059
  }
971
1060
  }
972
- const result = findInTranslations(translations, key, language, fallbackLanguage);
1061
+ const result = findInTranslations(
1062
+ translations,
1063
+ key,
1064
+ language,
1065
+ fallbackLanguage);
973
1066
  if (cache && result) {
974
1067
  const cacheKey = `${language}:${key}`;
975
1068
  cache.set(cacheKey, result);
@@ -985,7 +1078,12 @@ function findInTranslations(translations, key, language, fallbackLanguage, missi
985
1078
  return result;
986
1079
  }
987
1080
  if (language !== fallbackLanguage) {
988
- result = findInNamespace(translations, namespace, actualKey, fallbackLanguage);
1081
+ result = findInNamespace(
1082
+ translations,
1083
+ namespace,
1084
+ actualKey,
1085
+ fallbackLanguage
1086
+ );
989
1087
  if (result) {
990
1088
  return result;
991
1089
  }
@@ -1231,7 +1329,9 @@ function I18nProvider({
1231
1329
  config,
1232
1330
  children
1233
1331
  }) {
1234
- const [currentLanguage, setCurrentLanguageState] = React.useState(() => resolveInitialLanguage(config));
1332
+ const [currentLanguage, setCurrentLanguageState] = React.useState(
1333
+ () => resolveInitialLanguage(config)
1334
+ );
1235
1335
  const [isLoading, setIsLoading] = React.useState(true);
1236
1336
  const [isInitialized, setIsInitialized] = React.useState(false);
1237
1337
  const [error, setError] = React.useState(null);
@@ -1252,7 +1352,9 @@ function I18nProvider({
1252
1352
  const translatorLang = translator.getCurrentLanguage();
1253
1353
  if (translatorLang !== currentLanguage) {
1254
1354
  if (config.debug) {
1255
- console.log(`\u{1F504} [USEI18N] Syncing translator language: ${translatorLang} -> ${currentLanguage} (already initialized)`);
1355
+ console.log(
1356
+ `\u{1F504} [USEI18N] Syncing translator language: ${translatorLang} -> ${currentLanguage} (already initialized)`
1357
+ );
1256
1358
  }
1257
1359
  translator.setLanguage(currentLanguage);
1258
1360
  }
@@ -1277,13 +1379,18 @@ function I18nProvider({
1277
1379
  await translator.initialize();
1278
1380
  setIsInitialized(true);
1279
1381
  if (config.debug) {
1280
- console.log("\u2705 [USEI18N] Translator initialization completed successfully");
1382
+ console.log(
1383
+ "\u2705 [USEI18N] Translator initialization completed successfully"
1384
+ );
1281
1385
  }
1282
1386
  } catch (err) {
1283
1387
  const initError = err;
1284
1388
  setError(initError);
1285
1389
  if (config.debug) {
1286
- console.error("\u274C [USEI18N] Failed to initialize translator:", initError);
1390
+ console.error(
1391
+ "\u274C [USEI18N] Failed to initialize translator:",
1392
+ initError
1393
+ );
1287
1394
  }
1288
1395
  setIsInitialized(true);
1289
1396
  } finally {
@@ -1311,7 +1418,9 @@ function I18nProvider({
1311
1418
  const unsubscribe = translator.onLanguageChanged((newLanguage) => {
1312
1419
  if (newLanguage !== currentLanguage) {
1313
1420
  if (config.debug) {
1314
- console.log(`\u{1F504} [USEI18N] Language changed event: ${currentLanguage} -> ${newLanguage}`);
1421
+ console.log(
1422
+ `\u{1F504} [USEI18N] Language changed event: ${currentLanguage} -> ${newLanguage}`
1423
+ );
1315
1424
  }
1316
1425
  setCurrentLanguageState(newLanguage);
1317
1426
  setTranslationVersion((prev) => prev + 1);
@@ -1333,38 +1442,46 @@ function I18nProvider({
1333
1442
  }
1334
1443
  });
1335
1444
  }, [config.autoLanguageSync, config.platformAdapter, currentLanguage]);
1336
- const setLanguage = React.useCallback(async (language) => {
1337
- if (!translator) {
1338
- return;
1339
- }
1340
- const currentLang = translator.getCurrentLanguage();
1341
- if (currentLang === language) {
1342
- if (config.debug) {
1343
- console.log(`\u23ED\uFE0F [USEI18N] Language unchanged, skipping: ${language}`);
1445
+ const setLanguage = React.useCallback(
1446
+ async (language) => {
1447
+ if (!translator) {
1448
+ return;
1344
1449
  }
1345
- return;
1346
- }
1347
- if (config.debug) {
1348
- if (config.debug) {
1349
- console.log(`\u{1F504} [USEI18N] setLanguage called: ${currentLang} -> ${language}`);
1450
+ const currentLang = translator.getCurrentLanguage();
1451
+ if (currentLang === language) {
1452
+ if (config.debug) {
1453
+ console.log(`\u23ED\uFE0F [USEI18N] Language unchanged, skipping: ${language}`);
1454
+ }
1455
+ return;
1350
1456
  }
1351
- }
1352
- setIsLoading(true);
1353
- try {
1354
- translator.setLanguage(language);
1355
- setCurrentLanguageState(language);
1356
- await new Promise((resolve) => setTimeout(resolve, 0));
1357
1457
  if (config.debug) {
1358
- console.log(`\u2705 [USEI18N] Language changed to ${language}`);
1458
+ if (config.debug) {
1459
+ console.log(
1460
+ `\u{1F504} [USEI18N] setLanguage called: ${currentLang} -> ${language}`
1461
+ );
1462
+ }
1359
1463
  }
1360
- } catch (error2) {
1361
- if (config.debug) {
1362
- console.error(`\u274C [USEI18N] Failed to change language to ${language}:`, error2);
1464
+ setIsLoading(true);
1465
+ try {
1466
+ translator.setLanguage(language);
1467
+ setCurrentLanguageState(language);
1468
+ await new Promise((resolve) => setTimeout(resolve, 0));
1469
+ if (config.debug) {
1470
+ console.log(`\u2705 [USEI18N] Language changed to ${language}`);
1471
+ }
1472
+ } catch (error2) {
1473
+ if (config.debug) {
1474
+ console.error(
1475
+ `\u274C [USEI18N] Failed to change language to ${language}:`,
1476
+ error2
1477
+ );
1478
+ }
1479
+ } finally {
1480
+ setIsLoading(false);
1363
1481
  }
1364
- } finally {
1365
- setIsLoading(false);
1366
- }
1367
- }, [translator, config.debug]);
1482
+ },
1483
+ [translator, config.debug]
1484
+ );
1368
1485
  const parseKey2 = React.useCallback((key) => {
1369
1486
  const parts = key.split(":");
1370
1487
  if (parts.length >= 2) {
@@ -1372,246 +1489,336 @@ function I18nProvider({
1372
1489
  }
1373
1490
  return { namespace: "common", key };
1374
1491
  }, []);
1375
- const resolveNestedKey = React.useCallback((obj, key) => {
1376
- if (key in obj && typeof obj[key] === "string") {
1377
- return obj[key];
1378
- }
1379
- const parts = key.split(".");
1380
- let current = obj;
1381
- for (const part of parts) {
1382
- if (current && typeof current === "object" && current !== null && part in current) {
1383
- current = current[part];
1384
- } else {
1385
- return null;
1492
+ const resolveNestedKey = React.useCallback(
1493
+ (obj, key) => {
1494
+ if (key in obj && typeof obj[key] === "string") {
1495
+ return obj[key];
1496
+ }
1497
+ const parts = key.split(".");
1498
+ let current = obj;
1499
+ for (const part of parts) {
1500
+ if (current && typeof current === "object" && current !== null && part in current) {
1501
+ current = current[part];
1502
+ } else {
1503
+ return null;
1504
+ }
1386
1505
  }
1387
- }
1388
- return typeof current === "string" ? current : null;
1389
- }, []);
1390
- const findInSSRTranslations = React.useCallback((key, targetLang) => {
1391
- if (!config.initialTranslations) {
1392
- return null;
1393
- }
1394
- const { namespace, key: actualKey } = parseKey2(key);
1395
- const ssrTranslations = config.initialTranslations[targetLang]?.[namespace];
1396
- if (ssrTranslations) {
1397
- const value2 = resolveNestedKey(ssrTranslations, actualKey);
1398
- if (value2 !== null) {
1399
- return value2;
1506
+ return typeof current === "string" ? current : null;
1507
+ },
1508
+ []
1509
+ );
1510
+ const findInSSRTranslations = React.useCallback(
1511
+ (key, targetLang) => {
1512
+ if (!config.initialTranslations) {
1513
+ return null;
1400
1514
  }
1401
- }
1402
- const fallbackLang = config.fallbackLanguage || "en";
1403
- if (targetLang !== fallbackLang) {
1404
- const fallbackTranslations = config.initialTranslations[fallbackLang]?.[namespace];
1405
- if (fallbackTranslations) {
1406
- const value2 = resolveNestedKey(fallbackTranslations, actualKey);
1515
+ const { namespace, key: actualKey } = parseKey2(key);
1516
+ const ssrTranslations = config.initialTranslations[targetLang]?.[namespace];
1517
+ if (ssrTranslations) {
1518
+ const value2 = resolveNestedKey(
1519
+ ssrTranslations,
1520
+ actualKey
1521
+ );
1407
1522
  if (value2 !== null) {
1408
1523
  return value2;
1409
1524
  }
1410
1525
  }
1411
- }
1412
- return null;
1413
- }, [config.initialTranslations, config.fallbackLanguage, parseKey2, resolveNestedKey]);
1414
- const findInDefaultTranslations = React.useCallback((key, targetLang) => {
1415
- const { namespace, key: actualKey } = parseKey2(key);
1416
- const defaultTranslations = getDefaultTranslations(targetLang, namespace);
1417
- const fallbackTranslations = getDefaultTranslations(config.fallbackLanguage || "en", namespace);
1418
- return resolveNestedKey(defaultTranslations, actualKey) || resolveNestedKey(fallbackTranslations, actualKey) || null;
1419
- }, [config.fallbackLanguage, parseKey2, resolveNestedKey]);
1420
- const t = React.useCallback((key, paramsOrLang, language) => {
1421
- if (!translator) {
1422
- return key;
1423
- }
1424
- let params;
1425
- let lang;
1426
- if (typeof paramsOrLang === "string") {
1427
- lang = paramsOrLang;
1428
- } else if (typeof paramsOrLang === "object" && paramsOrLang !== null) {
1429
- params = paramsOrLang;
1430
- lang = language;
1431
- }
1432
- const targetLang = lang || currentLanguage;
1433
- try {
1434
- const result = translator.translate(key, params || lang, params ? lang : void 0);
1435
- if (result && result !== key && result !== "") {
1436
- return result;
1526
+ const fallbackLang = config.fallbackLanguage || "en";
1527
+ if (targetLang !== fallbackLang) {
1528
+ const fallbackTranslations = config.initialTranslations[fallbackLang]?.[namespace];
1529
+ if (fallbackTranslations) {
1530
+ const value2 = resolveNestedKey(
1531
+ fallbackTranslations,
1532
+ actualKey
1533
+ );
1534
+ if (value2 !== null) {
1535
+ return value2;
1536
+ }
1537
+ }
1437
1538
  }
1438
- } catch (error2) {
1439
- }
1440
- const interpolate = (text) => {
1441
- if (!params) return text;
1442
- return text.replace(/\{\{(\w+)\}\}/g, (match, k) => {
1443
- const value2 = params[k];
1444
- return value2 !== void 0 ? String(value2) : match;
1445
- });
1446
- };
1447
- const ssrResult = findInSSRTranslations(key, targetLang);
1448
- if (ssrResult) {
1449
- return interpolate(ssrResult);
1450
- }
1451
- const defaultResult = findInDefaultTranslations(key, targetLang);
1452
- if (defaultResult) {
1453
- return interpolate(defaultResult);
1454
- }
1455
- if (config.debug) {
1456
- return interpolate(key);
1457
- }
1458
- return "";
1459
- }, [translator, config.debug, currentLanguage, config.fallbackLanguage, translationVersion, findInSSRTranslations, findInDefaultTranslations]);
1460
- const tAsync = React.useCallback(async (key, params) => {
1461
- if (!translator) {
1462
- if (config.debug) {
1463
- console.warn("Translator not initialized");
1539
+ return null;
1540
+ },
1541
+ [
1542
+ config.initialTranslations,
1543
+ config.fallbackLanguage,
1544
+ parseKey2,
1545
+ resolveNestedKey
1546
+ ]
1547
+ );
1548
+ const findInDefaultTranslations = React.useCallback(
1549
+ (key, targetLang) => {
1550
+ const { namespace, key: actualKey } = parseKey2(key);
1551
+ const defaultTranslations = getDefaultTranslations(targetLang, namespace);
1552
+ const fallbackTranslations = getDefaultTranslations(
1553
+ config.fallbackLanguage || "en",
1554
+ namespace
1555
+ );
1556
+ return resolveNestedKey(
1557
+ defaultTranslations,
1558
+ actualKey
1559
+ ) || resolveNestedKey(
1560
+ fallbackTranslations,
1561
+ actualKey
1562
+ ) || null;
1563
+ },
1564
+ [config.fallbackLanguage, parseKey2, resolveNestedKey]
1565
+ );
1566
+ const t = React.useCallback(
1567
+ (key, paramsOrLang, language) => {
1568
+ if (!translator) {
1569
+ return key;
1570
+ }
1571
+ let params;
1572
+ let lang;
1573
+ if (typeof paramsOrLang === "string") {
1574
+ lang = paramsOrLang;
1575
+ } else if (typeof paramsOrLang === "object" && paramsOrLang !== null) {
1576
+ params = paramsOrLang;
1577
+ lang = language;
1578
+ }
1579
+ const targetLang = lang || currentLanguage;
1580
+ try {
1581
+ const result = translator.translate(
1582
+ key,
1583
+ params || lang,
1584
+ params ? lang : void 0
1585
+ );
1586
+ if (result && result !== key && result !== "") {
1587
+ return result;
1588
+ }
1589
+ } catch (error2) {
1464
1590
  }
1465
- return key;
1466
- }
1467
- setIsLoading(true);
1468
- try {
1469
- const result = await translator.translateAsync(key, params);
1470
- return result;
1471
- } catch (error2) {
1472
- if (config.debug) {
1473
- console.error("Translation error:", error2);
1591
+ const interpolate = (text) => {
1592
+ if (!params) return text;
1593
+ return text.replace(/\{\{(\w+)\}\}/g, (match, k) => {
1594
+ const value2 = params[k];
1595
+ return value2 !== void 0 ? String(value2) : match;
1596
+ });
1597
+ };
1598
+ const ssrResult = findInSSRTranslations(key, targetLang);
1599
+ if (ssrResult) {
1600
+ return interpolate(ssrResult);
1474
1601
  }
1475
- return key;
1476
- } finally {
1477
- setIsLoading(false);
1478
- }
1479
- }, [translator, config.debug]);
1480
- const tSync = React.useCallback((key, namespace, params) => {
1481
- if (!translator) {
1482
- if (config.debug) {
1483
- console.warn("Translator not initialized");
1602
+ const defaultResult = findInDefaultTranslations(key, targetLang);
1603
+ if (defaultResult) {
1604
+ return interpolate(defaultResult);
1484
1605
  }
1485
- return key;
1486
- }
1487
- return translator.translateSync(key, params);
1488
- }, [translator, config.debug]);
1489
- const getRawValue = React.useCallback((key, language) => {
1490
- if (!translator || !isInitialized) {
1491
- return void 0;
1492
- }
1493
- return translator.getRawValue(key, language);
1494
- }, [translator, isInitialized]);
1495
- const tArray = React.useCallback((key, language) => {
1496
- if (!translator || !isInitialized) {
1497
- return [];
1498
- }
1499
- return translator.tArray(key, language);
1500
- }, [translator, isInitialized, translationVersion, currentLanguage]);
1501
- const tPlural = React.useCallback((key, count, params, language) => {
1502
- if (!translator || !isInitialized) {
1503
- return key;
1504
- }
1505
- return translator.tPlural(key, count, params, language);
1506
- }, [translator, isInitialized, translationVersion, currentLanguage]);
1507
- const debug = React.useMemo(() => ({
1508
- getCurrentLanguage: () => {
1509
- try {
1510
- return translator?.getCurrentLanguage() || currentLanguage;
1511
- } catch {
1512
- return currentLanguage;
1606
+ if (typeof paramsOrLang === "object" && paramsOrLang !== null && "defaultValue" in paramsOrLang && typeof paramsOrLang.defaultValue === "string") {
1607
+ return interpolate(paramsOrLang.defaultValue);
1513
1608
  }
1514
- },
1515
- getSupportedLanguages: () => {
1516
- try {
1517
- return translator?.getSupportedLanguages() || config.supportedLanguages?.map((l) => l.code) || [];
1518
- } catch {
1519
- return config.supportedLanguages?.map((l) => l.code) || [];
1609
+ if (config.debug) {
1610
+ return interpolate(key);
1520
1611
  }
1612
+ return "";
1521
1613
  },
1522
- getLoadedNamespaces: () => {
1523
- try {
1524
- const debugInfo = translator?.debug();
1525
- if (debugInfo && debugInfo.loadedNamespaces) {
1526
- return Array.from(debugInfo.loadedNamespaces);
1527
- }
1528
- if (debugInfo && debugInfo.allTranslations) {
1529
- const namespaces = /* @__PURE__ */ new Set();
1530
- Object.values(debugInfo.allTranslations).forEach((langData) => {
1531
- if (langData && typeof langData === "object") {
1532
- Object.keys(langData).forEach((namespace) => {
1533
- namespaces.add(namespace);
1534
- });
1535
- }
1536
- });
1537
- return Array.from(namespaces);
1614
+ [
1615
+ translator,
1616
+ config.debug,
1617
+ currentLanguage,
1618
+ config.fallbackLanguage,
1619
+ translationVersion,
1620
+ findInSSRTranslations,
1621
+ findInDefaultTranslations
1622
+ ]
1623
+ );
1624
+ const tAsync = React.useCallback(
1625
+ async (key, params) => {
1626
+ if (!translator) {
1627
+ if (config.debug) {
1628
+ console.warn("Translator not initialized");
1538
1629
  }
1539
- return [];
1540
- } catch (error2) {
1541
- return [];
1630
+ return key;
1542
1631
  }
1543
- },
1544
- getAllTranslations: () => {
1632
+ setIsLoading(true);
1545
1633
  try {
1546
- return translator?.debug()?.allTranslations || {};
1634
+ const result = await translator.translateAsync(key, params);
1635
+ return result;
1547
1636
  } catch (error2) {
1548
- return {};
1637
+ if (config.debug) {
1638
+ console.error("Translation error:", error2);
1639
+ }
1640
+ return key;
1641
+ } finally {
1642
+ setIsLoading(false);
1549
1643
  }
1550
1644
  },
1551
- isReady: () => {
1552
- try {
1553
- return translator?.isReady() || isInitialized;
1554
- } catch {
1555
- return isInitialized;
1645
+ [translator, config.debug]
1646
+ );
1647
+ const tSync = React.useCallback(
1648
+ (key, namespace, params) => {
1649
+ if (!translator) {
1650
+ if (config.debug) {
1651
+ console.warn("Translator not initialized");
1652
+ }
1653
+ return key;
1556
1654
  }
1655
+ return translator.translateSync(key, params);
1557
1656
  },
1558
- getInitializationError: () => {
1559
- try {
1560
- return translator?.getInitializationError() || error;
1561
- } catch {
1562
- return error;
1563
- }
1657
+ [translator, config.debug]
1658
+ );
1659
+ const getRawValue = React.useCallback(
1660
+ (key, language) => {
1661
+ if (!translator || !isInitialized) {
1662
+ return void 0;
1663
+ }
1664
+ return translator.getRawValue(key, language);
1564
1665
  },
1565
- clearCache: () => {
1566
- try {
1567
- translator?.clearCache();
1568
- } catch {
1666
+ [translator, isInitialized]
1667
+ );
1668
+ const tArray = React.useCallback(
1669
+ (key, language) => {
1670
+ if (!translator || !isInitialized) {
1671
+ return [];
1569
1672
  }
1673
+ return translator.tArray(key, language);
1570
1674
  },
1571
- getCacheStats: () => {
1572
- try {
1573
- const debugInfo = translator?.debug();
1574
- if (debugInfo && debugInfo.cacheStats) {
1575
- return {
1576
- size: debugInfo.cacheSize || 0,
1577
- hits: debugInfo.cacheStats.hits || 0,
1578
- misses: debugInfo.cacheStats.misses || 0
1579
- };
1580
- }
1581
- return { size: 0, hits: 0, misses: 0 };
1582
- } catch (error2) {
1583
- return { size: 0, hits: 0, misses: 0 };
1584
- }
1675
+ [translator, isInitialized, translationVersion, currentLanguage]
1676
+ );
1677
+ const tPlural = React.useCallback(
1678
+ (key, count, params, language) => {
1679
+ if (!translator || !isInitialized) {
1680
+ return key;
1681
+ }
1682
+ return translator.tPlural(key, count, params, language);
1585
1683
  },
1586
- reloadTranslations: async () => {
1587
- if (translator) {
1588
- setIsLoading(true);
1589
- setError(null);
1684
+ [translator, isInitialized, translationVersion, currentLanguage]
1685
+ );
1686
+ const debug = React.useMemo(
1687
+ () => ({
1688
+ getCurrentLanguage: () => {
1689
+ try {
1690
+ return translator?.getCurrentLanguage() || currentLanguage;
1691
+ } catch {
1692
+ return currentLanguage;
1693
+ }
1694
+ },
1695
+ getSupportedLanguages: () => {
1696
+ try {
1697
+ return translator?.getSupportedLanguages() || config.supportedLanguages?.map((l) => l.code) || [];
1698
+ } catch {
1699
+ return config.supportedLanguages?.map((l) => l.code) || [];
1700
+ }
1701
+ },
1702
+ getLoadedNamespaces: () => {
1703
+ try {
1704
+ const debugInfo = translator?.debug();
1705
+ if (debugInfo && debugInfo.loadedNamespaces) {
1706
+ return Array.from(debugInfo.loadedNamespaces);
1707
+ }
1708
+ if (debugInfo && debugInfo.allTranslations) {
1709
+ const namespaces = /* @__PURE__ */ new Set();
1710
+ Object.values(debugInfo.allTranslations).forEach(
1711
+ (langData) => {
1712
+ if (langData && typeof langData === "object") {
1713
+ Object.keys(langData).forEach((namespace) => {
1714
+ namespaces.add(namespace);
1715
+ });
1716
+ }
1717
+ }
1718
+ );
1719
+ return Array.from(namespaces);
1720
+ }
1721
+ return [];
1722
+ } catch (error2) {
1723
+ return [];
1724
+ }
1725
+ },
1726
+ getAllTranslations: () => {
1727
+ try {
1728
+ return translator?.debug()?.allTranslations || {};
1729
+ } catch (error2) {
1730
+ return {};
1731
+ }
1732
+ },
1733
+ isReady: () => {
1734
+ try {
1735
+ return translator?.isReady() || isInitialized;
1736
+ } catch {
1737
+ return isInitialized;
1738
+ }
1739
+ },
1740
+ getInitializationError: () => {
1741
+ try {
1742
+ return translator?.getInitializationError() || error;
1743
+ } catch {
1744
+ return error;
1745
+ }
1746
+ },
1747
+ clearCache: () => {
1590
1748
  try {
1591
- await translator.initialize();
1592
- } catch (err) {
1593
- setError(err);
1594
- } finally {
1595
- setIsLoading(false);
1749
+ translator?.clearCache();
1750
+ } catch {
1751
+ }
1752
+ },
1753
+ getCacheStats: () => {
1754
+ try {
1755
+ const debugInfo = translator?.debug();
1756
+ if (debugInfo && debugInfo.cacheStats) {
1757
+ return {
1758
+ size: debugInfo.cacheSize || 0,
1759
+ hits: debugInfo.cacheStats.hits || 0,
1760
+ misses: debugInfo.cacheStats.misses || 0
1761
+ };
1762
+ }
1763
+ return { size: 0, hits: 0, misses: 0 };
1764
+ } catch (error2) {
1765
+ return { size: 0, hits: 0, misses: 0 };
1766
+ }
1767
+ },
1768
+ reloadTranslations: async () => {
1769
+ if (translator) {
1770
+ setIsLoading(true);
1771
+ setError(null);
1772
+ try {
1773
+ await translator.initialize();
1774
+ } catch (err) {
1775
+ setError(err);
1776
+ } finally {
1777
+ setIsLoading(false);
1778
+ }
1596
1779
  }
1597
1780
  }
1598
- }
1599
- }), [translator, currentLanguage, error, isInitialized, config.supportedLanguages]);
1600
- const value = React.useMemo(() => ({
1601
- currentLanguage,
1602
- setLanguage,
1603
- t,
1604
- tPlural,
1605
- tArray,
1606
- tAsync,
1607
- tSync,
1608
- getRawValue,
1609
- isLoading,
1610
- error,
1611
- supportedLanguages: config.supportedLanguages,
1612
- debug,
1613
- isInitialized
1614
- }), [currentLanguage, setLanguage, t, tPlural, tArray, tAsync, tSync, getRawValue, isLoading, error, config.supportedLanguages, debug, isInitialized]);
1781
+ }),
1782
+ [
1783
+ translator,
1784
+ currentLanguage,
1785
+ error,
1786
+ isInitialized,
1787
+ config.supportedLanguages
1788
+ ]
1789
+ );
1790
+ const value = React.useMemo(
1791
+ () => ({
1792
+ currentLanguage,
1793
+ setLanguage,
1794
+ t,
1795
+ tPlural,
1796
+ tArray,
1797
+ tAsync,
1798
+ tSync,
1799
+ getRawValue,
1800
+ isLoading,
1801
+ error,
1802
+ supportedLanguages: config.supportedLanguages,
1803
+ debug,
1804
+ isInitialized
1805
+ }),
1806
+ [
1807
+ currentLanguage,
1808
+ setLanguage,
1809
+ t,
1810
+ tPlural,
1811
+ tArray,
1812
+ tAsync,
1813
+ tSync,
1814
+ getRawValue,
1815
+ isLoading,
1816
+ error,
1817
+ config.supportedLanguages,
1818
+ debug,
1819
+ isInitialized
1820
+ ]
1821
+ );
1615
1822
  return /* @__PURE__ */ jsxRuntime.jsx(I18nContext.Provider, { value, children });
1616
1823
  }
1617
1824
  function useI18n() {
@@ -1621,7 +1828,12 @@ function useI18n() {
1621
1828
  currentLanguage: "ko",
1622
1829
  setLanguage: () => {
1623
1830
  },
1624
- t: (key) => key,
1831
+ t: (key, paramsOrLang) => {
1832
+ if (typeof paramsOrLang === "object" && paramsOrLang !== null && "defaultValue" in paramsOrLang && typeof paramsOrLang.defaultValue === "string") {
1833
+ return paramsOrLang.defaultValue;
1834
+ }
1835
+ return key;
1836
+ },
1625
1837
  tPlural: (key) => key,
1626
1838
  tAsync: async (key) => key,
1627
1839
  tSync: (key) => key,