@playcraft/adsdk 1.0.18-beta.2 → 1.0.18-beta.4

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/esm/index.js CHANGED
@@ -1,3 +1,23 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+
1
21
  // src/events.ts
2
22
  var registeredEvents = {};
3
23
  function onEvent(event, fn, context, once) {
@@ -512,6 +532,7 @@ function detectCandidates() {
512
532
  var SUPPORTED_LANG_CODES = [
513
533
  "en",
514
534
  "zh",
535
+ "zh-TW",
515
536
  "ja",
516
537
  "ko",
517
538
  "de",
@@ -528,9 +549,31 @@ var SUPPORTED_LANG_CODES = [
528
549
  "ms",
529
550
  "id"
530
551
  ];
552
+ var LANG_TAG_TO_I18N_CODE = {
553
+ // 简体中文 → zh
554
+ "zh": "zh",
555
+ "zh-cn": "zh",
556
+ "zh-sg": "zh",
557
+ "zh-my": "zh",
558
+ "zh-hans": "zh",
559
+ "zh-hans-cn": "zh",
560
+ "zh-hans-sg": "zh",
561
+ "zh-hans-my": "zh",
562
+ // 繁体中文 → zh-TW
563
+ "zh-tw": "zh-TW",
564
+ "zh-hk": "zh-TW",
565
+ "zh-mo": "zh-TW",
566
+ "zh-hant": "zh-TW",
567
+ "zh-hant-tw": "zh-TW",
568
+ "zh-hant-hk": "zh-TW",
569
+ "zh-hant-mo": "zh-TW"
570
+ };
531
571
  function normalizeLangTag(tag) {
532
572
  if (!tag || typeof tag !== "string") return void 0;
533
- const primary = tag.split(/[-_]/)[0].toLowerCase();
573
+ const lower = tag.toLowerCase();
574
+ const mapped = LANG_TAG_TO_I18N_CODE[lower];
575
+ if (mapped) return mapped;
576
+ const primary = lower.split(/[-_]/)[0];
534
577
  return SUPPORTED_LANG_CODES.indexOf(primary) >= 0 ? primary : void 0;
535
578
  }
536
579
  function getLanguageCode() {
@@ -541,97 +584,6 @@ function getLanguageCode() {
541
584
  }
542
585
  return "en";
543
586
  }
544
- var LANGUAGE_MAP = {
545
- // 英语
546
- "en": "EN",
547
- // 中文(简体)
548
- "zh": "CN_S",
549
- "zh-cn": "CN_S",
550
- "zh-sg": "CN_S",
551
- "zh-my": "CN_S",
552
- "zh-hans": "CN_S",
553
- "zh-hans-cn": "CN_S",
554
- "zh-hans-sg": "CN_S",
555
- "zh-hans-my": "CN_S",
556
- // 中文(繁体)
557
- "zh-tw": "CN_T",
558
- "zh-hk": "CN_T",
559
- "zh-mo": "CN_T",
560
- "zh-hant": "CN_T",
561
- "zh-hant-tw": "CN_T",
562
- "zh-hant-hk": "CN_T",
563
- "zh-hant-mo": "CN_T",
564
- // 德语
565
- "de": "DE",
566
- // 法语
567
- "fr": "FR",
568
- // 西班牙语
569
- "es": "ES",
570
- // 日语
571
- "ja": "JA",
572
- // 韩语
573
- "ko": "KO",
574
- // 葡萄牙语
575
- "pt": "PT",
576
- // 意大利语
577
- "it": "IT",
578
- // 印地语
579
- "hi": "HI",
580
- // 孟加拉语
581
- "bn": "BN",
582
- // 乌尔都语
583
- "ur": "UR",
584
- // 阿拉伯语
585
- "ar": "AR",
586
- // 土耳其语
587
- "tr": "TR",
588
- // 俄语
589
- "ru": "RU",
590
- // 马来语
591
- "ms": "MS",
592
- // 印尼语
593
- "id": "ID"
594
- };
595
- var SUPPORTED_PROJECT_LANGUAGES = /* @__PURE__ */ new Set([
596
- "EN",
597
- "CN_S",
598
- "CN_T",
599
- "DE",
600
- "FR",
601
- "ES",
602
- "JA",
603
- "KO",
604
- "PT",
605
- "IT",
606
- "HI",
607
- "BN",
608
- "UR",
609
- "AR",
610
- "TR",
611
- "RU",
612
- "MS",
613
- "IN",
614
- "ID"
615
- ]);
616
- function resolveLanguageTag(tag) {
617
- if (!tag || typeof tag !== "string") return void 0;
618
- const normalized = tag.trim();
619
- if (!normalized) return void 0;
620
- const projectCode = normalized.toUpperCase().replace(/-/g, "_");
621
- if (SUPPORTED_PROJECT_LANGUAGES.has(projectCode)) return projectCode;
622
- const lower = normalized.toLowerCase();
623
- if (LANGUAGE_MAP[lower]) return LANGUAGE_MAP[lower];
624
- const primary = lower.split(/[-_]/)[0];
625
- return LANGUAGE_MAP[primary];
626
- }
627
- function getLanguage() {
628
- const candidates = detectCandidates();
629
- for (const tag of candidates) {
630
- const code = resolveLanguageTag(tag);
631
- if (code) return code;
632
- }
633
- return "EN";
634
- }
635
587
 
636
588
  // src/theme-config.ts
637
589
  function extractDefaultsFromSchema(schema) {
@@ -651,11 +603,34 @@ function extractDefaultsFromSchema(schema) {
651
603
  }
652
604
  return void 0;
653
605
  }
606
+ var LANG_FALLBACK_MAP = {
607
+ // 繁体中文:优先查专用键,没有则回退通用简体,最后回退 en
608
+ "zh-TW": ["zh-TW", "zh", "en"]
609
+ };
654
610
  function lookupI18nRuntime(runtime, key, langCode) {
655
- var _a, _b;
611
+ var _a;
656
612
  const map = runtime[key];
657
613
  if (!map || typeof map !== "object") return void 0;
658
- return (_b = (_a = map[langCode]) != null ? _a : map["en"]) != null ? _b : Object.values(map)[0];
614
+ const fallbackChain = (_a = LANG_FALLBACK_MAP[langCode]) != null ? _a : [langCode, "en"];
615
+ for (const code of fallbackChain) {
616
+ const val = map[code];
617
+ if (val && val.length > 0) return val;
618
+ }
619
+ return Object.values(map).find((v) => typeof v === "string" && v.length > 0);
620
+ }
621
+ function mergeI18nRuntimes(runtimes) {
622
+ const merged = {};
623
+ for (const runtime of runtimes) {
624
+ if (!runtime) continue;
625
+ for (const [key, langMap] of Object.entries(runtime)) {
626
+ if (!merged[key]) {
627
+ merged[key] = __spreadValues({}, langMap);
628
+ } else {
629
+ merged[key] = __spreadValues(__spreadValues({}, merged[key]), langMap);
630
+ }
631
+ }
632
+ }
633
+ return merged;
659
634
  }
660
635
  function resolveI18nRefs(config, i18nRecord, langCode) {
661
636
  var _a;
@@ -669,6 +644,9 @@ function resolveI18nRefs(config, i18nRecord, langCode) {
669
644
  const resolved = lookupI18nRuntime(runtime, i18nKey, langCode);
670
645
  if (resolved !== void 0) {
671
646
  config[key] = resolved;
647
+ } else {
648
+ console.warn(`[i18n] Missing translation for key "${i18nKey}" (lang: ${langCode}), using key name as fallback`);
649
+ config[key] = i18nKey;
672
650
  }
673
651
  }
674
652
  } else if (value !== null && typeof value === "object" && !Array.isArray(value)) {
@@ -703,11 +681,12 @@ function deepMerge(target, source) {
703
681
  return target;
704
682
  }
705
683
  function setConfig(configList, config) {
684
+ var _a;
706
685
  const { assetRecordByPath, i18nRecord } = config;
707
686
  const resolvedConfigs = configList.map((item) => {
708
- var _a;
687
+ var _a2;
709
688
  if (!item) return {};
710
- return item.$schema ? (_a = extractDefaultsFromSchema(item)) != null ? _a : {} : item;
689
+ return item.$schema ? (_a2 = extractDefaultsFromSchema(item)) != null ? _a2 : {} : item;
711
690
  });
712
691
  const [first, ...rest] = resolvedConfigs;
713
692
  const mergedConfig = JSON.parse(JSON.stringify(first));
@@ -717,7 +696,8 @@ function setConfig(configList, config) {
717
696
  if (i18nRecord) {
718
697
  const langCode = getLanguageCode();
719
698
  console.log("detect target langCode", langCode);
720
- resolveI18nRefs(mergedConfig, i18nRecord, langCode);
699
+ const runtime = Array.isArray(i18nRecord.runtime) ? mergeI18nRuntimes(i18nRecord.runtime) : (_a = i18nRecord.runtime) != null ? _a : {};
700
+ resolveI18nRefs(mergedConfig, __spreadProps(__spreadValues({}, i18nRecord), { runtime }), langCode);
721
701
  }
722
702
  resolveImagePaths(mergedConfig, assetRecordByPath);
723
703
  _cachedConfig = mergedConfig;
@@ -1534,19 +1514,6 @@ var _sdk = class _sdk {
1534
1514
  static getLanguageCode() {
1535
1515
  return getLanguageCode();
1536
1516
  }
1537
- /**
1538
- * 获取当前用户语言的业务代号。
1539
- * 多源探测(querystring → localStorage → cookie → navigator → html tag),
1540
- * 并映射到业务语言代号(区分简繁中文)。
1541
- *
1542
- * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
1543
- *
1544
- * @example
1545
- * const lang = sdk.getLanguage(); // 'CN_S'
1546
- */
1547
- static getLanguage() {
1548
- return getLanguage();
1549
- }
1550
1517
  /**
1551
1518
  * 设置主题配置,支持传入多份 JSON5 配置。
1552
1519
  * 每一份配置都可以是 JSON Schema(带 $schema 字段),会自动提取其中的 default 值。
@@ -1609,7 +1576,7 @@ var _sdk = class _sdk {
1609
1576
  }
1610
1577
  };
1611
1578
  /** Current version of the SDK */
1612
- _sdk.version = "1.0.18-beta.2";
1579
+ _sdk.version = "1.0.18-beta.4";
1613
1580
  /** Current maximum width of the playable ad container in pixels */
1614
1581
  _sdk.maxWidth = Math.floor(window.innerWidth);
1615
1582
  /** Current maximum height of the playable ad container in pixels */
@@ -1639,7 +1606,6 @@ export {
1639
1606
  sdk as default,
1640
1607
  disableCustomCursor,
1641
1608
  enableCustomCursor,
1642
- getLanguage,
1643
1609
  getLanguageCode,
1644
1610
  hideWechatGuide,
1645
1611
  removeWechatGuide,
@@ -1,5 +1,25 @@
1
1
  "use strict";
2
2
  (() => {
3
+ var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
9
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
+ var __spreadValues = (a, b) => {
11
+ for (var prop in b || (b = {}))
12
+ if (__hasOwnProp.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
14
+ if (__getOwnPropSymbols)
15
+ for (var prop of __getOwnPropSymbols(b)) {
16
+ if (__propIsEnum.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
18
+ }
19
+ return a;
20
+ };
21
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
22
+
3
23
  // src/events.ts
4
24
  var registeredEvents = {};
5
25
  function onEvent(event, fn, context, once) {
@@ -750,6 +770,7 @@
750
770
  var SUPPORTED_LANG_CODES = [
751
771
  "en",
752
772
  "zh",
773
+ "zh-TW",
753
774
  "ja",
754
775
  "ko",
755
776
  "de",
@@ -766,9 +787,31 @@
766
787
  "ms",
767
788
  "id"
768
789
  ];
790
+ var LANG_TAG_TO_I18N_CODE = {
791
+ // 简体中文 → zh
792
+ "zh": "zh",
793
+ "zh-cn": "zh",
794
+ "zh-sg": "zh",
795
+ "zh-my": "zh",
796
+ "zh-hans": "zh",
797
+ "zh-hans-cn": "zh",
798
+ "zh-hans-sg": "zh",
799
+ "zh-hans-my": "zh",
800
+ // 繁体中文 → zh-TW
801
+ "zh-tw": "zh-TW",
802
+ "zh-hk": "zh-TW",
803
+ "zh-mo": "zh-TW",
804
+ "zh-hant": "zh-TW",
805
+ "zh-hant-tw": "zh-TW",
806
+ "zh-hant-hk": "zh-TW",
807
+ "zh-hant-mo": "zh-TW"
808
+ };
769
809
  function normalizeLangTag(tag) {
770
810
  if (!tag || typeof tag !== "string") return void 0;
771
- const primary = tag.split(/[-_]/)[0].toLowerCase();
811
+ const lower = tag.toLowerCase();
812
+ const mapped = LANG_TAG_TO_I18N_CODE[lower];
813
+ if (mapped) return mapped;
814
+ const primary = lower.split(/[-_]/)[0];
772
815
  return SUPPORTED_LANG_CODES.indexOf(primary) >= 0 ? primary : void 0;
773
816
  }
774
817
  function getLanguageCode() {
@@ -779,97 +822,6 @@
779
822
  }
780
823
  return "en";
781
824
  }
782
- var LANGUAGE_MAP = {
783
- // 英语
784
- "en": "EN",
785
- // 中文(简体)
786
- "zh": "CN_S",
787
- "zh-cn": "CN_S",
788
- "zh-sg": "CN_S",
789
- "zh-my": "CN_S",
790
- "zh-hans": "CN_S",
791
- "zh-hans-cn": "CN_S",
792
- "zh-hans-sg": "CN_S",
793
- "zh-hans-my": "CN_S",
794
- // 中文(繁体)
795
- "zh-tw": "CN_T",
796
- "zh-hk": "CN_T",
797
- "zh-mo": "CN_T",
798
- "zh-hant": "CN_T",
799
- "zh-hant-tw": "CN_T",
800
- "zh-hant-hk": "CN_T",
801
- "zh-hant-mo": "CN_T",
802
- // 德语
803
- "de": "DE",
804
- // 法语
805
- "fr": "FR",
806
- // 西班牙语
807
- "es": "ES",
808
- // 日语
809
- "ja": "JA",
810
- // 韩语
811
- "ko": "KO",
812
- // 葡萄牙语
813
- "pt": "PT",
814
- // 意大利语
815
- "it": "IT",
816
- // 印地语
817
- "hi": "HI",
818
- // 孟加拉语
819
- "bn": "BN",
820
- // 乌尔都语
821
- "ur": "UR",
822
- // 阿拉伯语
823
- "ar": "AR",
824
- // 土耳其语
825
- "tr": "TR",
826
- // 俄语
827
- "ru": "RU",
828
- // 马来语
829
- "ms": "MS",
830
- // 印尼语
831
- "id": "ID"
832
- };
833
- var SUPPORTED_PROJECT_LANGUAGES = /* @__PURE__ */ new Set([
834
- "EN",
835
- "CN_S",
836
- "CN_T",
837
- "DE",
838
- "FR",
839
- "ES",
840
- "JA",
841
- "KO",
842
- "PT",
843
- "IT",
844
- "HI",
845
- "BN",
846
- "UR",
847
- "AR",
848
- "TR",
849
- "RU",
850
- "MS",
851
- "IN",
852
- "ID"
853
- ]);
854
- function resolveLanguageTag(tag) {
855
- if (!tag || typeof tag !== "string") return void 0;
856
- const normalized = tag.trim();
857
- if (!normalized) return void 0;
858
- const projectCode = normalized.toUpperCase().replace(/-/g, "_");
859
- if (SUPPORTED_PROJECT_LANGUAGES.has(projectCode)) return projectCode;
860
- const lower = normalized.toLowerCase();
861
- if (LANGUAGE_MAP[lower]) return LANGUAGE_MAP[lower];
862
- const primary = lower.split(/[-_]/)[0];
863
- return LANGUAGE_MAP[primary];
864
- }
865
- function getLanguage() {
866
- const candidates = detectCandidates();
867
- for (const tag of candidates) {
868
- const code = resolveLanguageTag(tag);
869
- if (code) return code;
870
- }
871
- return "EN";
872
- }
873
825
 
874
826
  // src/theme-config.ts
875
827
  function extractDefaultsFromSchema(schema) {
@@ -889,11 +841,34 @@
889
841
  }
890
842
  return void 0;
891
843
  }
844
+ var LANG_FALLBACK_MAP = {
845
+ // 繁体中文:优先查专用键,没有则回退通用简体,最后回退 en
846
+ "zh-TW": ["zh-TW", "zh", "en"]
847
+ };
892
848
  function lookupI18nRuntime(runtime, key, langCode) {
893
- var _a, _b;
849
+ var _a;
894
850
  const map = runtime[key];
895
851
  if (!map || typeof map !== "object") return void 0;
896
- return (_b = (_a = map[langCode]) != null ? _a : map["en"]) != null ? _b : Object.values(map)[0];
852
+ const fallbackChain = (_a = LANG_FALLBACK_MAP[langCode]) != null ? _a : [langCode, "en"];
853
+ for (const code of fallbackChain) {
854
+ const val = map[code];
855
+ if (val && val.length > 0) return val;
856
+ }
857
+ return Object.values(map).find((v) => typeof v === "string" && v.length > 0);
858
+ }
859
+ function mergeI18nRuntimes(runtimes) {
860
+ const merged = {};
861
+ for (const runtime of runtimes) {
862
+ if (!runtime) continue;
863
+ for (const [key, langMap] of Object.entries(runtime)) {
864
+ if (!merged[key]) {
865
+ merged[key] = __spreadValues({}, langMap);
866
+ } else {
867
+ merged[key] = __spreadValues(__spreadValues({}, merged[key]), langMap);
868
+ }
869
+ }
870
+ }
871
+ return merged;
897
872
  }
898
873
  function resolveI18nRefs(config, i18nRecord, langCode) {
899
874
  var _a;
@@ -907,6 +882,9 @@
907
882
  const resolved = lookupI18nRuntime(runtime, i18nKey, langCode);
908
883
  if (resolved !== void 0) {
909
884
  config[key] = resolved;
885
+ } else {
886
+ console.warn(`[i18n] Missing translation for key "${i18nKey}" (lang: ${langCode}), using key name as fallback`);
887
+ config[key] = i18nKey;
910
888
  }
911
889
  }
912
890
  } else if (value !== null && typeof value === "object" && !Array.isArray(value)) {
@@ -941,11 +919,12 @@
941
919
  return target;
942
920
  }
943
921
  function setConfig(configList, config) {
922
+ var _a;
944
923
  const { assetRecordByPath, i18nRecord } = config;
945
924
  const resolvedConfigs = configList.map((item) => {
946
- var _a;
925
+ var _a2;
947
926
  if (!item) return {};
948
- return item.$schema ? (_a = extractDefaultsFromSchema(item)) != null ? _a : {} : item;
927
+ return item.$schema ? (_a2 = extractDefaultsFromSchema(item)) != null ? _a2 : {} : item;
949
928
  });
950
929
  const [first, ...rest] = resolvedConfigs;
951
930
  const mergedConfig = JSON.parse(JSON.stringify(first));
@@ -955,7 +934,8 @@
955
934
  if (i18nRecord) {
956
935
  const langCode = getLanguageCode();
957
936
  console.log("detect target langCode", langCode);
958
- resolveI18nRefs(mergedConfig, i18nRecord, langCode);
937
+ const runtime = Array.isArray(i18nRecord.runtime) ? mergeI18nRuntimes(i18nRecord.runtime) : (_a = i18nRecord.runtime) != null ? _a : {};
938
+ resolveI18nRefs(mergedConfig, __spreadProps(__spreadValues({}, i18nRecord), { runtime }), langCode);
959
939
  }
960
940
  resolveImagePaths(mergedConfig, assetRecordByPath);
961
941
  _cachedConfig = mergedConfig;
@@ -1772,19 +1752,6 @@
1772
1752
  static getLanguageCode() {
1773
1753
  return getLanguageCode();
1774
1754
  }
1775
- /**
1776
- * 获取当前用户语言的业务代号。
1777
- * 多源探测(querystring → localStorage → cookie → navigator → html tag),
1778
- * 并映射到业务语言代号(区分简繁中文)。
1779
- *
1780
- * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
1781
- *
1782
- * @example
1783
- * const lang = sdk.getLanguage(); // 'CN_S'
1784
- */
1785
- static getLanguage() {
1786
- return getLanguage();
1787
- }
1788
1755
  /**
1789
1756
  * 设置主题配置,支持传入多份 JSON5 配置。
1790
1757
  * 每一份配置都可以是 JSON Schema(带 $schema 字段),会自动提取其中的 default 值。
@@ -1847,7 +1814,7 @@
1847
1814
  }
1848
1815
  };
1849
1816
  /** Current version of the SDK */
1850
- _sdk.version = "1.0.18-beta.2";
1817
+ _sdk.version = "1.0.18-beta.4";
1851
1818
  /** Current maximum width of the playable ad container in pixels */
1852
1819
  _sdk.maxWidth = Math.floor(window.innerWidth);
1853
1820
  /** Current maximum height of the playable ad container in pixels */
package/dist/index.d.mts CHANGED
@@ -1,11 +1,15 @@
1
1
  /**
2
- * i18n 数据结构(仅 runtime,SDK 只处理游戏内运行时多语言):
2
+ * i18n 数据结构(仅 runtime,SDK 只处理游戏内运行时多语言)
3
3
  * runtime: { [key]: { [langCode]: "文案" } }
4
4
  *
5
+ * 当传入数组时,按顺序深度合并(后面的优先级更高),
6
+ * 支持全局 i18n + 主题级 i18n 分文件管理:
7
+ * runtime: [I18nRuntime, themeI18n] // 主题级覆盖全局
8
+ *
5
9
  * xplatform(配置平台 UI 标题)由外部配置平台自行解析,不传入 SDK。
6
10
  */
7
11
  type I18nRecord = {
8
- runtime?: Record<string, Record<string, string>>;
12
+ runtime?: Record<string, Record<string, string>> | Record<string, Record<string, string>>[];
9
13
  };
10
14
 
11
15
  type EventName = 'playcraftInit' | 'playcraftReady' | 'playcraftStart' | 'playcraftInteractive' | 'playcraftInteraction' | 'playcraftChallengeStart' | 'playcraftChallengeProgress' | 'playcraftChallengeSuccess' | 'playcraftChallengeFailed' | 'playcraftResize' | 'playcraftPause' | 'playcraftResume' | 'playcraftVolume' | 'playcraftRetry' | 'playcraftFinish' | 'playcraftInstall';
@@ -272,17 +276,6 @@ declare class sdk {
272
276
  * const langCode = sdk.getLanguageCode(); // 'zh'
273
277
  */
274
278
  static getLanguageCode(): string;
275
- /**
276
- * 获取当前用户语言的业务代号。
277
- * 多源探测(querystring → localStorage → cookie → navigator → html tag),
278
- * 并映射到业务语言代号(区分简繁中文)。
279
- *
280
- * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
281
- *
282
- * @example
283
- * const lang = sdk.getLanguage(); // 'CN_S'
284
- */
285
- static getLanguage(): string;
286
279
  /**
287
280
  * 设置主题配置,支持传入多份 JSON5 配置。
288
281
  * 每一份配置都可以是 JSON Schema(带 $schema 字段),会自动提取其中的 default 值。
@@ -374,14 +367,8 @@ declare function removeWechatGuide(): void;
374
367
  /**
375
368
  * 多源探测当前用户语言,并归一化为 i18n 简码。
376
369
  *
377
- * @returns i18n 简码:en | zh | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
370
+ * @returns i18n 简码:en | zh | zh-TW | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
378
371
  */
379
372
  declare function getLanguageCode(): string;
380
- /**
381
- * 多源探测当前用户语言,返回业务语言代号。
382
- *
383
- * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
384
- */
385
- declare function getLanguage(): string;
386
373
 
387
- export { type CursorOptions, type I18nRecord, sdk as default, disableCustomCursor, enableCustomCursor, getLanguage, getLanguageCode, hideWechatGuide, removeWechatGuide, sdk, showWechatGuide };
374
+ export { type CursorOptions, type I18nRecord, sdk as default, disableCustomCursor, enableCustomCursor, getLanguageCode, hideWechatGuide, removeWechatGuide, sdk, showWechatGuide };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,15 @@
1
1
  /**
2
- * i18n 数据结构(仅 runtime,SDK 只处理游戏内运行时多语言):
2
+ * i18n 数据结构(仅 runtime,SDK 只处理游戏内运行时多语言)
3
3
  * runtime: { [key]: { [langCode]: "文案" } }
4
4
  *
5
+ * 当传入数组时,按顺序深度合并(后面的优先级更高),
6
+ * 支持全局 i18n + 主题级 i18n 分文件管理:
7
+ * runtime: [I18nRuntime, themeI18n] // 主题级覆盖全局
8
+ *
5
9
  * xplatform(配置平台 UI 标题)由外部配置平台自行解析,不传入 SDK。
6
10
  */
7
11
  type I18nRecord = {
8
- runtime?: Record<string, Record<string, string>>;
12
+ runtime?: Record<string, Record<string, string>> | Record<string, Record<string, string>>[];
9
13
  };
10
14
 
11
15
  type EventName = 'playcraftInit' | 'playcraftReady' | 'playcraftStart' | 'playcraftInteractive' | 'playcraftInteraction' | 'playcraftChallengeStart' | 'playcraftChallengeProgress' | 'playcraftChallengeSuccess' | 'playcraftChallengeFailed' | 'playcraftResize' | 'playcraftPause' | 'playcraftResume' | 'playcraftVolume' | 'playcraftRetry' | 'playcraftFinish' | 'playcraftInstall';
@@ -272,17 +276,6 @@ declare class sdk {
272
276
  * const langCode = sdk.getLanguageCode(); // 'zh'
273
277
  */
274
278
  static getLanguageCode(): string;
275
- /**
276
- * 获取当前用户语言的业务代号。
277
- * 多源探测(querystring → localStorage → cookie → navigator → html tag),
278
- * 并映射到业务语言代号(区分简繁中文)。
279
- *
280
- * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
281
- *
282
- * @example
283
- * const lang = sdk.getLanguage(); // 'CN_S'
284
- */
285
- static getLanguage(): string;
286
279
  /**
287
280
  * 设置主题配置,支持传入多份 JSON5 配置。
288
281
  * 每一份配置都可以是 JSON Schema(带 $schema 字段),会自动提取其中的 default 值。
@@ -374,14 +367,8 @@ declare function removeWechatGuide(): void;
374
367
  /**
375
368
  * 多源探测当前用户语言,并归一化为 i18n 简码。
376
369
  *
377
- * @returns i18n 简码:en | zh | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
370
+ * @returns i18n 简码:en | zh | zh-TW | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
378
371
  */
379
372
  declare function getLanguageCode(): string;
380
- /**
381
- * 多源探测当前用户语言,返回业务语言代号。
382
- *
383
- * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
384
- */
385
- declare function getLanguage(): string;
386
373
 
387
- export { type CursorOptions, type I18nRecord, sdk as default, disableCustomCursor, enableCustomCursor, getLanguage, getLanguageCode, hideWechatGuide, removeWechatGuide, sdk, showWechatGuide };
374
+ export { type CursorOptions, type I18nRecord, sdk as default, disableCustomCursor, enableCustomCursor, getLanguageCode, hideWechatGuide, removeWechatGuide, sdk, showWechatGuide };
package/dist/index.js CHANGED
@@ -1,8 +1,25 @@
1
1
  "use strict";
2
2
  var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __spreadValues = (a, b) => {
12
+ for (var prop in b || (b = {}))
13
+ if (__hasOwnProp.call(b, prop))
14
+ __defNormalProp(a, prop, b[prop]);
15
+ if (__getOwnPropSymbols)
16
+ for (var prop of __getOwnPropSymbols(b)) {
17
+ if (__propIsEnum.call(b, prop))
18
+ __defNormalProp(a, prop, b[prop]);
19
+ }
20
+ return a;
21
+ };
22
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
6
23
  var __export = (target, all) => {
7
24
  for (var name in all)
8
25
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -23,7 +40,6 @@ __export(index_exports, {
23
40
  default: () => sdk,
24
41
  disableCustomCursor: () => disableCustomCursor,
25
42
  enableCustomCursor: () => enableCustomCursor,
26
- getLanguage: () => getLanguage,
27
43
  getLanguageCode: () => getLanguageCode,
28
44
  hideWechatGuide: () => hideWechatGuide,
29
45
  removeWechatGuide: () => removeWechatGuide,
@@ -546,6 +562,7 @@ function detectCandidates() {
546
562
  var SUPPORTED_LANG_CODES = [
547
563
  "en",
548
564
  "zh",
565
+ "zh-TW",
549
566
  "ja",
550
567
  "ko",
551
568
  "de",
@@ -562,9 +579,31 @@ var SUPPORTED_LANG_CODES = [
562
579
  "ms",
563
580
  "id"
564
581
  ];
582
+ var LANG_TAG_TO_I18N_CODE = {
583
+ // 简体中文 → zh
584
+ "zh": "zh",
585
+ "zh-cn": "zh",
586
+ "zh-sg": "zh",
587
+ "zh-my": "zh",
588
+ "zh-hans": "zh",
589
+ "zh-hans-cn": "zh",
590
+ "zh-hans-sg": "zh",
591
+ "zh-hans-my": "zh",
592
+ // 繁体中文 → zh-TW
593
+ "zh-tw": "zh-TW",
594
+ "zh-hk": "zh-TW",
595
+ "zh-mo": "zh-TW",
596
+ "zh-hant": "zh-TW",
597
+ "zh-hant-tw": "zh-TW",
598
+ "zh-hant-hk": "zh-TW",
599
+ "zh-hant-mo": "zh-TW"
600
+ };
565
601
  function normalizeLangTag(tag) {
566
602
  if (!tag || typeof tag !== "string") return void 0;
567
- const primary = tag.split(/[-_]/)[0].toLowerCase();
603
+ const lower = tag.toLowerCase();
604
+ const mapped = LANG_TAG_TO_I18N_CODE[lower];
605
+ if (mapped) return mapped;
606
+ const primary = lower.split(/[-_]/)[0];
568
607
  return SUPPORTED_LANG_CODES.indexOf(primary) >= 0 ? primary : void 0;
569
608
  }
570
609
  function getLanguageCode() {
@@ -575,97 +614,6 @@ function getLanguageCode() {
575
614
  }
576
615
  return "en";
577
616
  }
578
- var LANGUAGE_MAP = {
579
- // 英语
580
- "en": "EN",
581
- // 中文(简体)
582
- "zh": "CN_S",
583
- "zh-cn": "CN_S",
584
- "zh-sg": "CN_S",
585
- "zh-my": "CN_S",
586
- "zh-hans": "CN_S",
587
- "zh-hans-cn": "CN_S",
588
- "zh-hans-sg": "CN_S",
589
- "zh-hans-my": "CN_S",
590
- // 中文(繁体)
591
- "zh-tw": "CN_T",
592
- "zh-hk": "CN_T",
593
- "zh-mo": "CN_T",
594
- "zh-hant": "CN_T",
595
- "zh-hant-tw": "CN_T",
596
- "zh-hant-hk": "CN_T",
597
- "zh-hant-mo": "CN_T",
598
- // 德语
599
- "de": "DE",
600
- // 法语
601
- "fr": "FR",
602
- // 西班牙语
603
- "es": "ES",
604
- // 日语
605
- "ja": "JA",
606
- // 韩语
607
- "ko": "KO",
608
- // 葡萄牙语
609
- "pt": "PT",
610
- // 意大利语
611
- "it": "IT",
612
- // 印地语
613
- "hi": "HI",
614
- // 孟加拉语
615
- "bn": "BN",
616
- // 乌尔都语
617
- "ur": "UR",
618
- // 阿拉伯语
619
- "ar": "AR",
620
- // 土耳其语
621
- "tr": "TR",
622
- // 俄语
623
- "ru": "RU",
624
- // 马来语
625
- "ms": "MS",
626
- // 印尼语
627
- "id": "ID"
628
- };
629
- var SUPPORTED_PROJECT_LANGUAGES = /* @__PURE__ */ new Set([
630
- "EN",
631
- "CN_S",
632
- "CN_T",
633
- "DE",
634
- "FR",
635
- "ES",
636
- "JA",
637
- "KO",
638
- "PT",
639
- "IT",
640
- "HI",
641
- "BN",
642
- "UR",
643
- "AR",
644
- "TR",
645
- "RU",
646
- "MS",
647
- "IN",
648
- "ID"
649
- ]);
650
- function resolveLanguageTag(tag) {
651
- if (!tag || typeof tag !== "string") return void 0;
652
- const normalized = tag.trim();
653
- if (!normalized) return void 0;
654
- const projectCode = normalized.toUpperCase().replace(/-/g, "_");
655
- if (SUPPORTED_PROJECT_LANGUAGES.has(projectCode)) return projectCode;
656
- const lower = normalized.toLowerCase();
657
- if (LANGUAGE_MAP[lower]) return LANGUAGE_MAP[lower];
658
- const primary = lower.split(/[-_]/)[0];
659
- return LANGUAGE_MAP[primary];
660
- }
661
- function getLanguage() {
662
- const candidates = detectCandidates();
663
- for (const tag of candidates) {
664
- const code = resolveLanguageTag(tag);
665
- if (code) return code;
666
- }
667
- return "EN";
668
- }
669
617
 
670
618
  // src/theme-config.ts
671
619
  function extractDefaultsFromSchema(schema) {
@@ -685,11 +633,34 @@ function extractDefaultsFromSchema(schema) {
685
633
  }
686
634
  return void 0;
687
635
  }
636
+ var LANG_FALLBACK_MAP = {
637
+ // 繁体中文:优先查专用键,没有则回退通用简体,最后回退 en
638
+ "zh-TW": ["zh-TW", "zh", "en"]
639
+ };
688
640
  function lookupI18nRuntime(runtime, key, langCode) {
689
- var _a, _b;
641
+ var _a;
690
642
  const map = runtime[key];
691
643
  if (!map || typeof map !== "object") return void 0;
692
- return (_b = (_a = map[langCode]) != null ? _a : map["en"]) != null ? _b : Object.values(map)[0];
644
+ const fallbackChain = (_a = LANG_FALLBACK_MAP[langCode]) != null ? _a : [langCode, "en"];
645
+ for (const code of fallbackChain) {
646
+ const val = map[code];
647
+ if (val && val.length > 0) return val;
648
+ }
649
+ return Object.values(map).find((v) => typeof v === "string" && v.length > 0);
650
+ }
651
+ function mergeI18nRuntimes(runtimes) {
652
+ const merged = {};
653
+ for (const runtime of runtimes) {
654
+ if (!runtime) continue;
655
+ for (const [key, langMap] of Object.entries(runtime)) {
656
+ if (!merged[key]) {
657
+ merged[key] = __spreadValues({}, langMap);
658
+ } else {
659
+ merged[key] = __spreadValues(__spreadValues({}, merged[key]), langMap);
660
+ }
661
+ }
662
+ }
663
+ return merged;
693
664
  }
694
665
  function resolveI18nRefs(config, i18nRecord, langCode) {
695
666
  var _a;
@@ -703,6 +674,9 @@ function resolveI18nRefs(config, i18nRecord, langCode) {
703
674
  const resolved = lookupI18nRuntime(runtime, i18nKey, langCode);
704
675
  if (resolved !== void 0) {
705
676
  config[key] = resolved;
677
+ } else {
678
+ console.warn(`[i18n] Missing translation for key "${i18nKey}" (lang: ${langCode}), using key name as fallback`);
679
+ config[key] = i18nKey;
706
680
  }
707
681
  }
708
682
  } else if (value !== null && typeof value === "object" && !Array.isArray(value)) {
@@ -737,11 +711,12 @@ function deepMerge(target, source) {
737
711
  return target;
738
712
  }
739
713
  function setConfig(configList, config) {
714
+ var _a;
740
715
  const { assetRecordByPath, i18nRecord } = config;
741
716
  const resolvedConfigs = configList.map((item) => {
742
- var _a;
717
+ var _a2;
743
718
  if (!item) return {};
744
- return item.$schema ? (_a = extractDefaultsFromSchema(item)) != null ? _a : {} : item;
719
+ return item.$schema ? (_a2 = extractDefaultsFromSchema(item)) != null ? _a2 : {} : item;
745
720
  });
746
721
  const [first, ...rest] = resolvedConfigs;
747
722
  const mergedConfig = JSON.parse(JSON.stringify(first));
@@ -751,7 +726,8 @@ function setConfig(configList, config) {
751
726
  if (i18nRecord) {
752
727
  const langCode = getLanguageCode();
753
728
  console.log("detect target langCode", langCode);
754
- resolveI18nRefs(mergedConfig, i18nRecord, langCode);
729
+ const runtime = Array.isArray(i18nRecord.runtime) ? mergeI18nRuntimes(i18nRecord.runtime) : (_a = i18nRecord.runtime) != null ? _a : {};
730
+ resolveI18nRefs(mergedConfig, __spreadProps(__spreadValues({}, i18nRecord), { runtime }), langCode);
755
731
  }
756
732
  resolveImagePaths(mergedConfig, assetRecordByPath);
757
733
  _cachedConfig = mergedConfig;
@@ -1568,19 +1544,6 @@ var _sdk = class _sdk {
1568
1544
  static getLanguageCode() {
1569
1545
  return getLanguageCode();
1570
1546
  }
1571
- /**
1572
- * 获取当前用户语言的业务代号。
1573
- * 多源探测(querystring → localStorage → cookie → navigator → html tag),
1574
- * 并映射到业务语言代号(区分简繁中文)。
1575
- *
1576
- * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
1577
- *
1578
- * @example
1579
- * const lang = sdk.getLanguage(); // 'CN_S'
1580
- */
1581
- static getLanguage() {
1582
- return getLanguage();
1583
- }
1584
1547
  /**
1585
1548
  * 设置主题配置,支持传入多份 JSON5 配置。
1586
1549
  * 每一份配置都可以是 JSON Schema(带 $schema 字段),会自动提取其中的 default 值。
@@ -1643,7 +1606,7 @@ var _sdk = class _sdk {
1643
1606
  }
1644
1607
  };
1645
1608
  /** Current version of the SDK */
1646
- _sdk.version = "1.0.18-beta.2";
1609
+ _sdk.version = "1.0.18-beta.4";
1647
1610
  /** Current maximum width of the playable ad container in pixels */
1648
1611
  _sdk.maxWidth = Math.floor(window.innerWidth);
1649
1612
  /** Current maximum height of the playable ad container in pixels */
@@ -1673,7 +1636,6 @@ window.PlayableSDK = sdk;
1673
1636
  0 && (module.exports = {
1674
1637
  disableCustomCursor,
1675
1638
  enableCustomCursor,
1676
- getLanguage,
1677
1639
  getLanguageCode,
1678
1640
  hideWechatGuide,
1679
1641
  removeWechatGuide,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcraft/adsdk",
3
- "version": "1.0.18-beta.2",
3
+ "version": "1.0.18-beta.4",
4
4
  "description": "统一的 Playable SDK,支持 MRAID、Google、Facebook、Vungle、BigoAds 等多广告渠道",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",