@playcraft/adsdk 1.0.18-beta.1 → 1.0.18-beta.3

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) {
@@ -443,6 +463,196 @@ function removeWechatGuide() {
443
463
  }
444
464
  }
445
465
 
466
+ // src/language.ts
467
+ function readQuerystring(key) {
468
+ try {
469
+ if (typeof window === "undefined" || !window.location) return void 0;
470
+ const search = window.location.search || "";
471
+ if (!search) return void 0;
472
+ if (typeof URLSearchParams !== "undefined") {
473
+ const params = new URLSearchParams(search);
474
+ return params.get(key) || void 0;
475
+ }
476
+ const re = new RegExp("[?&]" + key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=([^&#]*)");
477
+ const m = re.exec(search);
478
+ return m ? decodeURIComponent(m[1]) : void 0;
479
+ } catch (e) {
480
+ return void 0;
481
+ }
482
+ }
483
+ function readLocalStorage(key) {
484
+ try {
485
+ if (typeof localStorage === "undefined") return void 0;
486
+ return localStorage.getItem(key) || void 0;
487
+ } catch (e) {
488
+ return void 0;
489
+ }
490
+ }
491
+ function readCookie(name) {
492
+ try {
493
+ if (typeof document === "undefined" || !document.cookie) return void 0;
494
+ const re = new RegExp("(?:^|; )" + name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=([^;]*)");
495
+ const m = re.exec(document.cookie);
496
+ return m ? decodeURIComponent(m[1]) : void 0;
497
+ } catch (e) {
498
+ return void 0;
499
+ }
500
+ }
501
+ function readNavigatorLanguages() {
502
+ try {
503
+ if (typeof navigator === "undefined") return [];
504
+ const list = [];
505
+ const langs = navigator.languages;
506
+ if (Array.isArray(langs)) list.push(...langs);
507
+ if (navigator.language) list.push(navigator.language);
508
+ const userLang = navigator.userLanguage || navigator.browserLanguage;
509
+ if (userLang) list.push(userLang);
510
+ return list.filter(Boolean);
511
+ } catch (e) {
512
+ return [];
513
+ }
514
+ }
515
+ function readHtmlTag() {
516
+ try {
517
+ if (typeof document === "undefined" || !document.documentElement) return void 0;
518
+ return document.documentElement.lang || void 0;
519
+ } catch (e) {
520
+ return void 0;
521
+ }
522
+ }
523
+ function detectCandidates() {
524
+ return [
525
+ readQuerystring("lng"),
526
+ readLocalStorage("i18nextLng"),
527
+ readCookie("i18next"),
528
+ ...readNavigatorLanguages(),
529
+ readHtmlTag()
530
+ ];
531
+ }
532
+ var SUPPORTED_LANG_CODES = [
533
+ "en",
534
+ "zh",
535
+ "ja",
536
+ "ko",
537
+ "de",
538
+ "fr",
539
+ "es",
540
+ "pt",
541
+ "it",
542
+ "hi",
543
+ "bn",
544
+ "ur",
545
+ "ar",
546
+ "tr",
547
+ "ru",
548
+ "ms",
549
+ "id"
550
+ ];
551
+ function normalizeLangTag(tag) {
552
+ if (!tag || typeof tag !== "string") return void 0;
553
+ const primary = tag.split(/[-_]/)[0].toLowerCase();
554
+ return SUPPORTED_LANG_CODES.indexOf(primary) >= 0 ? primary : void 0;
555
+ }
556
+ function getLanguageCode() {
557
+ const candidates = detectCandidates();
558
+ for (const tag of candidates) {
559
+ const code = normalizeLangTag(tag);
560
+ if (code) return code;
561
+ }
562
+ return "en";
563
+ }
564
+ var LANGUAGE_MAP = {
565
+ // 英语
566
+ "en": "EN",
567
+ // 中文(简体)
568
+ "zh": "CN_S",
569
+ "zh-cn": "CN_S",
570
+ "zh-sg": "CN_S",
571
+ "zh-my": "CN_S",
572
+ "zh-hans": "CN_S",
573
+ "zh-hans-cn": "CN_S",
574
+ "zh-hans-sg": "CN_S",
575
+ "zh-hans-my": "CN_S",
576
+ // 中文(繁体)
577
+ "zh-tw": "CN_T",
578
+ "zh-hk": "CN_T",
579
+ "zh-mo": "CN_T",
580
+ "zh-hant": "CN_T",
581
+ "zh-hant-tw": "CN_T",
582
+ "zh-hant-hk": "CN_T",
583
+ "zh-hant-mo": "CN_T",
584
+ // 德语
585
+ "de": "DE",
586
+ // 法语
587
+ "fr": "FR",
588
+ // 西班牙语
589
+ "es": "ES",
590
+ // 日语
591
+ "ja": "JA",
592
+ // 韩语
593
+ "ko": "KO",
594
+ // 葡萄牙语
595
+ "pt": "PT",
596
+ // 意大利语
597
+ "it": "IT",
598
+ // 印地语
599
+ "hi": "HI",
600
+ // 孟加拉语
601
+ "bn": "BN",
602
+ // 乌尔都语
603
+ "ur": "UR",
604
+ // 阿拉伯语
605
+ "ar": "AR",
606
+ // 土耳其语
607
+ "tr": "TR",
608
+ // 俄语
609
+ "ru": "RU",
610
+ // 马来语
611
+ "ms": "MS",
612
+ // 印尼语
613
+ "id": "ID"
614
+ };
615
+ var SUPPORTED_PROJECT_LANGUAGES = /* @__PURE__ */ new Set([
616
+ "EN",
617
+ "CN_S",
618
+ "CN_T",
619
+ "DE",
620
+ "FR",
621
+ "ES",
622
+ "JA",
623
+ "KO",
624
+ "PT",
625
+ "IT",
626
+ "HI",
627
+ "BN",
628
+ "UR",
629
+ "AR",
630
+ "TR",
631
+ "RU",
632
+ "MS",
633
+ "IN",
634
+ "ID"
635
+ ]);
636
+ function resolveLanguageTag(tag) {
637
+ if (!tag || typeof tag !== "string") return void 0;
638
+ const normalized = tag.trim();
639
+ if (!normalized) return void 0;
640
+ const projectCode = normalized.toUpperCase().replace(/-/g, "_");
641
+ if (SUPPORTED_PROJECT_LANGUAGES.has(projectCode)) return projectCode;
642
+ const lower = normalized.toLowerCase();
643
+ if (LANGUAGE_MAP[lower]) return LANGUAGE_MAP[lower];
644
+ const primary = lower.split(/[-_]/)[0];
645
+ return LANGUAGE_MAP[primary];
646
+ }
647
+ function getLanguage() {
648
+ const candidates = detectCandidates();
649
+ for (const tag of candidates) {
650
+ const code = resolveLanguageTag(tag);
651
+ if (code) return code;
652
+ }
653
+ return "EN";
654
+ }
655
+
446
656
  // src/theme-config.ts
447
657
  function extractDefaultsFromSchema(schema) {
448
658
  if (!schema || typeof schema !== "object") return void 0;
@@ -461,18 +671,28 @@ function extractDefaultsFromSchema(schema) {
461
671
  }
462
672
  return void 0;
463
673
  }
464
- function getLanguageCode() {
465
- try {
466
- return (navigator.language || "en").split("-")[0].toLowerCase();
467
- } catch (e) {
468
- return "en";
469
- }
470
- }
471
674
  function lookupI18nRuntime(runtime, key, langCode) {
472
- var _a, _b;
473
675
  const map = runtime[key];
474
676
  if (!map || typeof map !== "object") return void 0;
475
- return (_b = (_a = map[langCode]) != null ? _a : map["en"]) != null ? _b : Object.values(map)[0];
677
+ const val = map[langCode];
678
+ if (val && val.length > 0) return val;
679
+ const enVal = map["en"];
680
+ if (enVal && enVal.length > 0) return enVal;
681
+ return Object.values(map).find((v) => typeof v === "string" && v.length > 0);
682
+ }
683
+ function mergeI18nRuntimes(runtimes) {
684
+ const merged = {};
685
+ for (const runtime of runtimes) {
686
+ if (!runtime) continue;
687
+ for (const [key, langMap] of Object.entries(runtime)) {
688
+ if (!merged[key]) {
689
+ merged[key] = __spreadValues({}, langMap);
690
+ } else {
691
+ merged[key] = __spreadValues(__spreadValues({}, merged[key]), langMap);
692
+ }
693
+ }
694
+ }
695
+ return merged;
476
696
  }
477
697
  function resolveI18nRefs(config, i18nRecord, langCode) {
478
698
  var _a;
@@ -486,6 +706,9 @@ function resolveI18nRefs(config, i18nRecord, langCode) {
486
706
  const resolved = lookupI18nRuntime(runtime, i18nKey, langCode);
487
707
  if (resolved !== void 0) {
488
708
  config[key] = resolved;
709
+ } else {
710
+ console.warn(`[i18n] Missing translation for key "${i18nKey}" (lang: ${langCode}), using key name as fallback`);
711
+ config[key] = i18nKey;
489
712
  }
490
713
  }
491
714
  } else if (value !== null && typeof value === "object" && !Array.isArray(value)) {
@@ -520,11 +743,12 @@ function deepMerge(target, source) {
520
743
  return target;
521
744
  }
522
745
  function setConfig(configList, config) {
746
+ var _a;
523
747
  const { assetRecordByPath, i18nRecord } = config;
524
748
  const resolvedConfigs = configList.map((item) => {
525
- var _a;
749
+ var _a2;
526
750
  if (!item) return {};
527
- return item.$schema ? (_a = extractDefaultsFromSchema(item)) != null ? _a : {} : item;
751
+ return item.$schema ? (_a2 = extractDefaultsFromSchema(item)) != null ? _a2 : {} : item;
528
752
  });
529
753
  const [first, ...rest] = resolvedConfigs;
530
754
  const mergedConfig = JSON.parse(JSON.stringify(first));
@@ -533,7 +757,9 @@ function setConfig(configList, config) {
533
757
  }
534
758
  if (i18nRecord) {
535
759
  const langCode = getLanguageCode();
536
- resolveI18nRefs(mergedConfig, i18nRecord, langCode);
760
+ console.log("detect target langCode", langCode);
761
+ const runtime = Array.isArray(i18nRecord.runtime) ? mergeI18nRuntimes(i18nRecord.runtime) : (_a = i18nRecord.runtime) != null ? _a : {};
762
+ resolveI18nRefs(mergedConfig, __spreadProps(__spreadValues({}, i18nRecord), { runtime }), langCode);
537
763
  }
538
764
  resolveImagePaths(mergedConfig, assetRecordByPath);
539
765
  _cachedConfig = mergedConfig;
@@ -1338,6 +1564,31 @@ var _sdk = class _sdk {
1338
1564
  static isGoogle() {
1339
1565
  return _sdk.getCurChannel() === "google";
1340
1566
  }
1567
+ /**
1568
+ * 获取当前用户语言的 i18n 简码。
1569
+ * 多源探测(querystring → localStorage → cookie → navigator → html tag)。
1570
+ *
1571
+ * @returns i18n 简码:en | zh | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
1572
+ *
1573
+ * @example
1574
+ * const langCode = sdk.getLanguageCode(); // 'zh'
1575
+ */
1576
+ static getLanguageCode() {
1577
+ return getLanguageCode();
1578
+ }
1579
+ /**
1580
+ * 获取当前用户语言的业务代号。
1581
+ * 多源探测(querystring → localStorage → cookie → navigator → html tag),
1582
+ * 并映射到业务语言代号(区分简繁中文)。
1583
+ *
1584
+ * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
1585
+ *
1586
+ * @example
1587
+ * const lang = sdk.getLanguage(); // 'CN_S'
1588
+ */
1589
+ static getLanguage() {
1590
+ return getLanguage();
1591
+ }
1341
1592
  /**
1342
1593
  * 设置主题配置,支持传入多份 JSON5 配置。
1343
1594
  * 每一份配置都可以是 JSON Schema(带 $schema 字段),会自动提取其中的 default 值。
@@ -1400,7 +1651,7 @@ var _sdk = class _sdk {
1400
1651
  }
1401
1652
  };
1402
1653
  /** Current version of the SDK */
1403
- _sdk.version = "1.0.18-beta.1";
1654
+ _sdk.version = "1.0.18-beta.3";
1404
1655
  /** Current maximum width of the playable ad container in pixels */
1405
1656
  _sdk.maxWidth = Math.floor(window.innerWidth);
1406
1657
  /** Current maximum height of the playable ad container in pixels */
@@ -1430,6 +1681,8 @@ export {
1430
1681
  sdk as default,
1431
1682
  disableCustomCursor,
1432
1683
  enableCustomCursor,
1684
+ getLanguage,
1685
+ getLanguageCode,
1433
1686
  hideWechatGuide,
1434
1687
  removeWechatGuide,
1435
1688
  sdk,
@@ -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) {
@@ -681,6 +701,196 @@
681
701
  }
682
702
  }
683
703
 
704
+ // src/language.ts
705
+ function readQuerystring(key) {
706
+ try {
707
+ if (typeof window === "undefined" || !window.location) return void 0;
708
+ const search = window.location.search || "";
709
+ if (!search) return void 0;
710
+ if (typeof URLSearchParams !== "undefined") {
711
+ const params = new URLSearchParams(search);
712
+ return params.get(key) || void 0;
713
+ }
714
+ const re = new RegExp("[?&]" + key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=([^&#]*)");
715
+ const m = re.exec(search);
716
+ return m ? decodeURIComponent(m[1]) : void 0;
717
+ } catch (e) {
718
+ return void 0;
719
+ }
720
+ }
721
+ function readLocalStorage(key) {
722
+ try {
723
+ if (typeof localStorage === "undefined") return void 0;
724
+ return localStorage.getItem(key) || void 0;
725
+ } catch (e) {
726
+ return void 0;
727
+ }
728
+ }
729
+ function readCookie(name) {
730
+ try {
731
+ if (typeof document === "undefined" || !document.cookie) return void 0;
732
+ const re = new RegExp("(?:^|; )" + name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=([^;]*)");
733
+ const m = re.exec(document.cookie);
734
+ return m ? decodeURIComponent(m[1]) : void 0;
735
+ } catch (e) {
736
+ return void 0;
737
+ }
738
+ }
739
+ function readNavigatorLanguages() {
740
+ try {
741
+ if (typeof navigator === "undefined") return [];
742
+ const list = [];
743
+ const langs = navigator.languages;
744
+ if (Array.isArray(langs)) list.push(...langs);
745
+ if (navigator.language) list.push(navigator.language);
746
+ const userLang = navigator.userLanguage || navigator.browserLanguage;
747
+ if (userLang) list.push(userLang);
748
+ return list.filter(Boolean);
749
+ } catch (e) {
750
+ return [];
751
+ }
752
+ }
753
+ function readHtmlTag() {
754
+ try {
755
+ if (typeof document === "undefined" || !document.documentElement) return void 0;
756
+ return document.documentElement.lang || void 0;
757
+ } catch (e) {
758
+ return void 0;
759
+ }
760
+ }
761
+ function detectCandidates() {
762
+ return [
763
+ readQuerystring("lng"),
764
+ readLocalStorage("i18nextLng"),
765
+ readCookie("i18next"),
766
+ ...readNavigatorLanguages(),
767
+ readHtmlTag()
768
+ ];
769
+ }
770
+ var SUPPORTED_LANG_CODES = [
771
+ "en",
772
+ "zh",
773
+ "ja",
774
+ "ko",
775
+ "de",
776
+ "fr",
777
+ "es",
778
+ "pt",
779
+ "it",
780
+ "hi",
781
+ "bn",
782
+ "ur",
783
+ "ar",
784
+ "tr",
785
+ "ru",
786
+ "ms",
787
+ "id"
788
+ ];
789
+ function normalizeLangTag(tag) {
790
+ if (!tag || typeof tag !== "string") return void 0;
791
+ const primary = tag.split(/[-_]/)[0].toLowerCase();
792
+ return SUPPORTED_LANG_CODES.indexOf(primary) >= 0 ? primary : void 0;
793
+ }
794
+ function getLanguageCode() {
795
+ const candidates = detectCandidates();
796
+ for (const tag of candidates) {
797
+ const code = normalizeLangTag(tag);
798
+ if (code) return code;
799
+ }
800
+ return "en";
801
+ }
802
+ var LANGUAGE_MAP = {
803
+ // 英语
804
+ "en": "EN",
805
+ // 中文(简体)
806
+ "zh": "CN_S",
807
+ "zh-cn": "CN_S",
808
+ "zh-sg": "CN_S",
809
+ "zh-my": "CN_S",
810
+ "zh-hans": "CN_S",
811
+ "zh-hans-cn": "CN_S",
812
+ "zh-hans-sg": "CN_S",
813
+ "zh-hans-my": "CN_S",
814
+ // 中文(繁体)
815
+ "zh-tw": "CN_T",
816
+ "zh-hk": "CN_T",
817
+ "zh-mo": "CN_T",
818
+ "zh-hant": "CN_T",
819
+ "zh-hant-tw": "CN_T",
820
+ "zh-hant-hk": "CN_T",
821
+ "zh-hant-mo": "CN_T",
822
+ // 德语
823
+ "de": "DE",
824
+ // 法语
825
+ "fr": "FR",
826
+ // 西班牙语
827
+ "es": "ES",
828
+ // 日语
829
+ "ja": "JA",
830
+ // 韩语
831
+ "ko": "KO",
832
+ // 葡萄牙语
833
+ "pt": "PT",
834
+ // 意大利语
835
+ "it": "IT",
836
+ // 印地语
837
+ "hi": "HI",
838
+ // 孟加拉语
839
+ "bn": "BN",
840
+ // 乌尔都语
841
+ "ur": "UR",
842
+ // 阿拉伯语
843
+ "ar": "AR",
844
+ // 土耳其语
845
+ "tr": "TR",
846
+ // 俄语
847
+ "ru": "RU",
848
+ // 马来语
849
+ "ms": "MS",
850
+ // 印尼语
851
+ "id": "ID"
852
+ };
853
+ var SUPPORTED_PROJECT_LANGUAGES = /* @__PURE__ */ new Set([
854
+ "EN",
855
+ "CN_S",
856
+ "CN_T",
857
+ "DE",
858
+ "FR",
859
+ "ES",
860
+ "JA",
861
+ "KO",
862
+ "PT",
863
+ "IT",
864
+ "HI",
865
+ "BN",
866
+ "UR",
867
+ "AR",
868
+ "TR",
869
+ "RU",
870
+ "MS",
871
+ "IN",
872
+ "ID"
873
+ ]);
874
+ function resolveLanguageTag(tag) {
875
+ if (!tag || typeof tag !== "string") return void 0;
876
+ const normalized = tag.trim();
877
+ if (!normalized) return void 0;
878
+ const projectCode = normalized.toUpperCase().replace(/-/g, "_");
879
+ if (SUPPORTED_PROJECT_LANGUAGES.has(projectCode)) return projectCode;
880
+ const lower = normalized.toLowerCase();
881
+ if (LANGUAGE_MAP[lower]) return LANGUAGE_MAP[lower];
882
+ const primary = lower.split(/[-_]/)[0];
883
+ return LANGUAGE_MAP[primary];
884
+ }
885
+ function getLanguage() {
886
+ const candidates = detectCandidates();
887
+ for (const tag of candidates) {
888
+ const code = resolveLanguageTag(tag);
889
+ if (code) return code;
890
+ }
891
+ return "EN";
892
+ }
893
+
684
894
  // src/theme-config.ts
685
895
  function extractDefaultsFromSchema(schema) {
686
896
  if (!schema || typeof schema !== "object") return void 0;
@@ -699,18 +909,28 @@
699
909
  }
700
910
  return void 0;
701
911
  }
702
- function getLanguageCode() {
703
- try {
704
- return (navigator.language || "en").split("-")[0].toLowerCase();
705
- } catch (e) {
706
- return "en";
707
- }
708
- }
709
912
  function lookupI18nRuntime(runtime, key, langCode) {
710
- var _a, _b;
711
913
  const map = runtime[key];
712
914
  if (!map || typeof map !== "object") return void 0;
713
- return (_b = (_a = map[langCode]) != null ? _a : map["en"]) != null ? _b : Object.values(map)[0];
915
+ const val = map[langCode];
916
+ if (val && val.length > 0) return val;
917
+ const enVal = map["en"];
918
+ if (enVal && enVal.length > 0) return enVal;
919
+ return Object.values(map).find((v) => typeof v === "string" && v.length > 0);
920
+ }
921
+ function mergeI18nRuntimes(runtimes) {
922
+ const merged = {};
923
+ for (const runtime of runtimes) {
924
+ if (!runtime) continue;
925
+ for (const [key, langMap] of Object.entries(runtime)) {
926
+ if (!merged[key]) {
927
+ merged[key] = __spreadValues({}, langMap);
928
+ } else {
929
+ merged[key] = __spreadValues(__spreadValues({}, merged[key]), langMap);
930
+ }
931
+ }
932
+ }
933
+ return merged;
714
934
  }
715
935
  function resolveI18nRefs(config, i18nRecord, langCode) {
716
936
  var _a;
@@ -724,6 +944,9 @@
724
944
  const resolved = lookupI18nRuntime(runtime, i18nKey, langCode);
725
945
  if (resolved !== void 0) {
726
946
  config[key] = resolved;
947
+ } else {
948
+ console.warn(`[i18n] Missing translation for key "${i18nKey}" (lang: ${langCode}), using key name as fallback`);
949
+ config[key] = i18nKey;
727
950
  }
728
951
  }
729
952
  } else if (value !== null && typeof value === "object" && !Array.isArray(value)) {
@@ -758,11 +981,12 @@
758
981
  return target;
759
982
  }
760
983
  function setConfig(configList, config) {
984
+ var _a;
761
985
  const { assetRecordByPath, i18nRecord } = config;
762
986
  const resolvedConfigs = configList.map((item) => {
763
- var _a;
987
+ var _a2;
764
988
  if (!item) return {};
765
- return item.$schema ? (_a = extractDefaultsFromSchema(item)) != null ? _a : {} : item;
989
+ return item.$schema ? (_a2 = extractDefaultsFromSchema(item)) != null ? _a2 : {} : item;
766
990
  });
767
991
  const [first, ...rest] = resolvedConfigs;
768
992
  const mergedConfig = JSON.parse(JSON.stringify(first));
@@ -771,7 +995,9 @@
771
995
  }
772
996
  if (i18nRecord) {
773
997
  const langCode = getLanguageCode();
774
- resolveI18nRefs(mergedConfig, i18nRecord, langCode);
998
+ console.log("detect target langCode", langCode);
999
+ const runtime = Array.isArray(i18nRecord.runtime) ? mergeI18nRuntimes(i18nRecord.runtime) : (_a = i18nRecord.runtime) != null ? _a : {};
1000
+ resolveI18nRefs(mergedConfig, __spreadProps(__spreadValues({}, i18nRecord), { runtime }), langCode);
775
1001
  }
776
1002
  resolveImagePaths(mergedConfig, assetRecordByPath);
777
1003
  _cachedConfig = mergedConfig;
@@ -1576,6 +1802,31 @@
1576
1802
  static isGoogle() {
1577
1803
  return _sdk.getCurChannel() === "google";
1578
1804
  }
1805
+ /**
1806
+ * 获取当前用户语言的 i18n 简码。
1807
+ * 多源探测(querystring → localStorage → cookie → navigator → html tag)。
1808
+ *
1809
+ * @returns i18n 简码:en | zh | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
1810
+ *
1811
+ * @example
1812
+ * const langCode = sdk.getLanguageCode(); // 'zh'
1813
+ */
1814
+ static getLanguageCode() {
1815
+ return getLanguageCode();
1816
+ }
1817
+ /**
1818
+ * 获取当前用户语言的业务代号。
1819
+ * 多源探测(querystring → localStorage → cookie → navigator → html tag),
1820
+ * 并映射到业务语言代号(区分简繁中文)。
1821
+ *
1822
+ * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
1823
+ *
1824
+ * @example
1825
+ * const lang = sdk.getLanguage(); // 'CN_S'
1826
+ */
1827
+ static getLanguage() {
1828
+ return getLanguage();
1829
+ }
1579
1830
  /**
1580
1831
  * 设置主题配置,支持传入多份 JSON5 配置。
1581
1832
  * 每一份配置都可以是 JSON Schema(带 $schema 字段),会自动提取其中的 default 值。
@@ -1638,7 +1889,7 @@
1638
1889
  }
1639
1890
  };
1640
1891
  /** Current version of the SDK */
1641
- _sdk.version = "1.0.18-beta.1";
1892
+ _sdk.version = "1.0.18-beta.3";
1642
1893
  /** Current maximum width of the playable ad container in pixels */
1643
1894
  _sdk.maxWidth = Math.floor(window.innerWidth);
1644
1895
  /** 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';
@@ -262,6 +266,27 @@ declare class sdk {
262
266
  * 判断是否是 Google
263
267
  */
264
268
  static isGoogle(): boolean;
269
+ /**
270
+ * 获取当前用户语言的 i18n 简码。
271
+ * 多源探测(querystring → localStorage → cookie → navigator → html tag)。
272
+ *
273
+ * @returns i18n 简码:en | zh | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
274
+ *
275
+ * @example
276
+ * const langCode = sdk.getLanguageCode(); // 'zh'
277
+ */
278
+ static getLanguageCode(): string;
279
+ /**
280
+ * 获取当前用户语言的业务代号。
281
+ * 多源探测(querystring → localStorage → cookie → navigator → html tag),
282
+ * 并映射到业务语言代号(区分简繁中文)。
283
+ *
284
+ * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
285
+ *
286
+ * @example
287
+ * const lang = sdk.getLanguage(); // 'CN_S'
288
+ */
289
+ static getLanguage(): string;
265
290
  /**
266
291
  * 设置主题配置,支持传入多份 JSON5 配置。
267
292
  * 每一份配置都可以是 JSON Schema(带 $schema 字段),会自动提取其中的 default 值。
@@ -336,4 +361,31 @@ declare function hideWechatGuide(): void;
336
361
  */
337
362
  declare function removeWechatGuide(): void;
338
363
 
339
- export { type CursorOptions, type I18nRecord, sdk as default, disableCustomCursor, enableCustomCursor, hideWechatGuide, removeWechatGuide, sdk, showWechatGuide };
364
+ /**
365
+ * 语言检测模块(零外部依赖)。
366
+ *
367
+ * 提供两个层级的语言获取:
368
+ * - getLanguageCode() → i18n 简码(en / zh / ja / ko …),用于 i18n.runtime 查表
369
+ * - getLanguage() → 业务语言代号(EN / CN_S / CN_T / DE …),用于游戏内资源选择
370
+ *
371
+ * 探测优先级(与 i18next-browser-languagedetector 保持一致):
372
+ * 1. URL querystring (?lng=xx)
373
+ * 2. localStorage (i18nextLng)
374
+ * 3. cookie (i18next)
375
+ * 4. navigator.languages / navigator.language
376
+ * 5. <html lang="xx">
377
+ */
378
+ /**
379
+ * 多源探测当前用户语言,并归一化为 i18n 简码。
380
+ *
381
+ * @returns i18n 简码:en | zh | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
382
+ */
383
+ declare function getLanguageCode(): string;
384
+ /**
385
+ * 多源探测当前用户语言,返回业务语言代号。
386
+ *
387
+ * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
388
+ */
389
+ declare function getLanguage(): string;
390
+
391
+ export { type CursorOptions, type I18nRecord, sdk as default, disableCustomCursor, enableCustomCursor, getLanguage, 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';
@@ -262,6 +266,27 @@ declare class sdk {
262
266
  * 判断是否是 Google
263
267
  */
264
268
  static isGoogle(): boolean;
269
+ /**
270
+ * 获取当前用户语言的 i18n 简码。
271
+ * 多源探测(querystring → localStorage → cookie → navigator → html tag)。
272
+ *
273
+ * @returns i18n 简码:en | zh | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
274
+ *
275
+ * @example
276
+ * const langCode = sdk.getLanguageCode(); // 'zh'
277
+ */
278
+ static getLanguageCode(): string;
279
+ /**
280
+ * 获取当前用户语言的业务代号。
281
+ * 多源探测(querystring → localStorage → cookie → navigator → html tag),
282
+ * 并映射到业务语言代号(区分简繁中文)。
283
+ *
284
+ * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
285
+ *
286
+ * @example
287
+ * const lang = sdk.getLanguage(); // 'CN_S'
288
+ */
289
+ static getLanguage(): string;
265
290
  /**
266
291
  * 设置主题配置,支持传入多份 JSON5 配置。
267
292
  * 每一份配置都可以是 JSON Schema(带 $schema 字段),会自动提取其中的 default 值。
@@ -336,4 +361,31 @@ declare function hideWechatGuide(): void;
336
361
  */
337
362
  declare function removeWechatGuide(): void;
338
363
 
339
- export { type CursorOptions, type I18nRecord, sdk as default, disableCustomCursor, enableCustomCursor, hideWechatGuide, removeWechatGuide, sdk, showWechatGuide };
364
+ /**
365
+ * 语言检测模块(零外部依赖)。
366
+ *
367
+ * 提供两个层级的语言获取:
368
+ * - getLanguageCode() → i18n 简码(en / zh / ja / ko …),用于 i18n.runtime 查表
369
+ * - getLanguage() → 业务语言代号(EN / CN_S / CN_T / DE …),用于游戏内资源选择
370
+ *
371
+ * 探测优先级(与 i18next-browser-languagedetector 保持一致):
372
+ * 1. URL querystring (?lng=xx)
373
+ * 2. localStorage (i18nextLng)
374
+ * 3. cookie (i18next)
375
+ * 4. navigator.languages / navigator.language
376
+ * 5. <html lang="xx">
377
+ */
378
+ /**
379
+ * 多源探测当前用户语言,并归一化为 i18n 简码。
380
+ *
381
+ * @returns i18n 简码:en | zh | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
382
+ */
383
+ declare function getLanguageCode(): string;
384
+ /**
385
+ * 多源探测当前用户语言,返回业务语言代号。
386
+ *
387
+ * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
388
+ */
389
+ declare function getLanguage(): string;
390
+
391
+ export { type CursorOptions, type I18nRecord, sdk as default, disableCustomCursor, enableCustomCursor, getLanguage, 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,6 +40,8 @@ __export(index_exports, {
23
40
  default: () => sdk,
24
41
  disableCustomCursor: () => disableCustomCursor,
25
42
  enableCustomCursor: () => enableCustomCursor,
43
+ getLanguage: () => getLanguage,
44
+ getLanguageCode: () => getLanguageCode,
26
45
  hideWechatGuide: () => hideWechatGuide,
27
46
  removeWechatGuide: () => removeWechatGuide,
28
47
  sdk: () => sdk,
@@ -475,6 +494,196 @@ function removeWechatGuide() {
475
494
  }
476
495
  }
477
496
 
497
+ // src/language.ts
498
+ function readQuerystring(key) {
499
+ try {
500
+ if (typeof window === "undefined" || !window.location) return void 0;
501
+ const search = window.location.search || "";
502
+ if (!search) return void 0;
503
+ if (typeof URLSearchParams !== "undefined") {
504
+ const params = new URLSearchParams(search);
505
+ return params.get(key) || void 0;
506
+ }
507
+ const re = new RegExp("[?&]" + key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=([^&#]*)");
508
+ const m = re.exec(search);
509
+ return m ? decodeURIComponent(m[1]) : void 0;
510
+ } catch (e) {
511
+ return void 0;
512
+ }
513
+ }
514
+ function readLocalStorage(key) {
515
+ try {
516
+ if (typeof localStorage === "undefined") return void 0;
517
+ return localStorage.getItem(key) || void 0;
518
+ } catch (e) {
519
+ return void 0;
520
+ }
521
+ }
522
+ function readCookie(name) {
523
+ try {
524
+ if (typeof document === "undefined" || !document.cookie) return void 0;
525
+ const re = new RegExp("(?:^|; )" + name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=([^;]*)");
526
+ const m = re.exec(document.cookie);
527
+ return m ? decodeURIComponent(m[1]) : void 0;
528
+ } catch (e) {
529
+ return void 0;
530
+ }
531
+ }
532
+ function readNavigatorLanguages() {
533
+ try {
534
+ if (typeof navigator === "undefined") return [];
535
+ const list = [];
536
+ const langs = navigator.languages;
537
+ if (Array.isArray(langs)) list.push(...langs);
538
+ if (navigator.language) list.push(navigator.language);
539
+ const userLang = navigator.userLanguage || navigator.browserLanguage;
540
+ if (userLang) list.push(userLang);
541
+ return list.filter(Boolean);
542
+ } catch (e) {
543
+ return [];
544
+ }
545
+ }
546
+ function readHtmlTag() {
547
+ try {
548
+ if (typeof document === "undefined" || !document.documentElement) return void 0;
549
+ return document.documentElement.lang || void 0;
550
+ } catch (e) {
551
+ return void 0;
552
+ }
553
+ }
554
+ function detectCandidates() {
555
+ return [
556
+ readQuerystring("lng"),
557
+ readLocalStorage("i18nextLng"),
558
+ readCookie("i18next"),
559
+ ...readNavigatorLanguages(),
560
+ readHtmlTag()
561
+ ];
562
+ }
563
+ var SUPPORTED_LANG_CODES = [
564
+ "en",
565
+ "zh",
566
+ "ja",
567
+ "ko",
568
+ "de",
569
+ "fr",
570
+ "es",
571
+ "pt",
572
+ "it",
573
+ "hi",
574
+ "bn",
575
+ "ur",
576
+ "ar",
577
+ "tr",
578
+ "ru",
579
+ "ms",
580
+ "id"
581
+ ];
582
+ function normalizeLangTag(tag) {
583
+ if (!tag || typeof tag !== "string") return void 0;
584
+ const primary = tag.split(/[-_]/)[0].toLowerCase();
585
+ return SUPPORTED_LANG_CODES.indexOf(primary) >= 0 ? primary : void 0;
586
+ }
587
+ function getLanguageCode() {
588
+ const candidates = detectCandidates();
589
+ for (const tag of candidates) {
590
+ const code = normalizeLangTag(tag);
591
+ if (code) return code;
592
+ }
593
+ return "en";
594
+ }
595
+ var LANGUAGE_MAP = {
596
+ // 英语
597
+ "en": "EN",
598
+ // 中文(简体)
599
+ "zh": "CN_S",
600
+ "zh-cn": "CN_S",
601
+ "zh-sg": "CN_S",
602
+ "zh-my": "CN_S",
603
+ "zh-hans": "CN_S",
604
+ "zh-hans-cn": "CN_S",
605
+ "zh-hans-sg": "CN_S",
606
+ "zh-hans-my": "CN_S",
607
+ // 中文(繁体)
608
+ "zh-tw": "CN_T",
609
+ "zh-hk": "CN_T",
610
+ "zh-mo": "CN_T",
611
+ "zh-hant": "CN_T",
612
+ "zh-hant-tw": "CN_T",
613
+ "zh-hant-hk": "CN_T",
614
+ "zh-hant-mo": "CN_T",
615
+ // 德语
616
+ "de": "DE",
617
+ // 法语
618
+ "fr": "FR",
619
+ // 西班牙语
620
+ "es": "ES",
621
+ // 日语
622
+ "ja": "JA",
623
+ // 韩语
624
+ "ko": "KO",
625
+ // 葡萄牙语
626
+ "pt": "PT",
627
+ // 意大利语
628
+ "it": "IT",
629
+ // 印地语
630
+ "hi": "HI",
631
+ // 孟加拉语
632
+ "bn": "BN",
633
+ // 乌尔都语
634
+ "ur": "UR",
635
+ // 阿拉伯语
636
+ "ar": "AR",
637
+ // 土耳其语
638
+ "tr": "TR",
639
+ // 俄语
640
+ "ru": "RU",
641
+ // 马来语
642
+ "ms": "MS",
643
+ // 印尼语
644
+ "id": "ID"
645
+ };
646
+ var SUPPORTED_PROJECT_LANGUAGES = /* @__PURE__ */ new Set([
647
+ "EN",
648
+ "CN_S",
649
+ "CN_T",
650
+ "DE",
651
+ "FR",
652
+ "ES",
653
+ "JA",
654
+ "KO",
655
+ "PT",
656
+ "IT",
657
+ "HI",
658
+ "BN",
659
+ "UR",
660
+ "AR",
661
+ "TR",
662
+ "RU",
663
+ "MS",
664
+ "IN",
665
+ "ID"
666
+ ]);
667
+ function resolveLanguageTag(tag) {
668
+ if (!tag || typeof tag !== "string") return void 0;
669
+ const normalized = tag.trim();
670
+ if (!normalized) return void 0;
671
+ const projectCode = normalized.toUpperCase().replace(/-/g, "_");
672
+ if (SUPPORTED_PROJECT_LANGUAGES.has(projectCode)) return projectCode;
673
+ const lower = normalized.toLowerCase();
674
+ if (LANGUAGE_MAP[lower]) return LANGUAGE_MAP[lower];
675
+ const primary = lower.split(/[-_]/)[0];
676
+ return LANGUAGE_MAP[primary];
677
+ }
678
+ function getLanguage() {
679
+ const candidates = detectCandidates();
680
+ for (const tag of candidates) {
681
+ const code = resolveLanguageTag(tag);
682
+ if (code) return code;
683
+ }
684
+ return "EN";
685
+ }
686
+
478
687
  // src/theme-config.ts
479
688
  function extractDefaultsFromSchema(schema) {
480
689
  if (!schema || typeof schema !== "object") return void 0;
@@ -493,18 +702,28 @@ function extractDefaultsFromSchema(schema) {
493
702
  }
494
703
  return void 0;
495
704
  }
496
- function getLanguageCode() {
497
- try {
498
- return (navigator.language || "en").split("-")[0].toLowerCase();
499
- } catch (e) {
500
- return "en";
501
- }
502
- }
503
705
  function lookupI18nRuntime(runtime, key, langCode) {
504
- var _a, _b;
505
706
  const map = runtime[key];
506
707
  if (!map || typeof map !== "object") return void 0;
507
- return (_b = (_a = map[langCode]) != null ? _a : map["en"]) != null ? _b : Object.values(map)[0];
708
+ const val = map[langCode];
709
+ if (val && val.length > 0) return val;
710
+ const enVal = map["en"];
711
+ if (enVal && enVal.length > 0) return enVal;
712
+ return Object.values(map).find((v) => typeof v === "string" && v.length > 0);
713
+ }
714
+ function mergeI18nRuntimes(runtimes) {
715
+ const merged = {};
716
+ for (const runtime of runtimes) {
717
+ if (!runtime) continue;
718
+ for (const [key, langMap] of Object.entries(runtime)) {
719
+ if (!merged[key]) {
720
+ merged[key] = __spreadValues({}, langMap);
721
+ } else {
722
+ merged[key] = __spreadValues(__spreadValues({}, merged[key]), langMap);
723
+ }
724
+ }
725
+ }
726
+ return merged;
508
727
  }
509
728
  function resolveI18nRefs(config, i18nRecord, langCode) {
510
729
  var _a;
@@ -518,6 +737,9 @@ function resolveI18nRefs(config, i18nRecord, langCode) {
518
737
  const resolved = lookupI18nRuntime(runtime, i18nKey, langCode);
519
738
  if (resolved !== void 0) {
520
739
  config[key] = resolved;
740
+ } else {
741
+ console.warn(`[i18n] Missing translation for key "${i18nKey}" (lang: ${langCode}), using key name as fallback`);
742
+ config[key] = i18nKey;
521
743
  }
522
744
  }
523
745
  } else if (value !== null && typeof value === "object" && !Array.isArray(value)) {
@@ -552,11 +774,12 @@ function deepMerge(target, source) {
552
774
  return target;
553
775
  }
554
776
  function setConfig(configList, config) {
777
+ var _a;
555
778
  const { assetRecordByPath, i18nRecord } = config;
556
779
  const resolvedConfigs = configList.map((item) => {
557
- var _a;
780
+ var _a2;
558
781
  if (!item) return {};
559
- return item.$schema ? (_a = extractDefaultsFromSchema(item)) != null ? _a : {} : item;
782
+ return item.$schema ? (_a2 = extractDefaultsFromSchema(item)) != null ? _a2 : {} : item;
560
783
  });
561
784
  const [first, ...rest] = resolvedConfigs;
562
785
  const mergedConfig = JSON.parse(JSON.stringify(first));
@@ -565,7 +788,9 @@ function setConfig(configList, config) {
565
788
  }
566
789
  if (i18nRecord) {
567
790
  const langCode = getLanguageCode();
568
- resolveI18nRefs(mergedConfig, i18nRecord, langCode);
791
+ console.log("detect target langCode", langCode);
792
+ const runtime = Array.isArray(i18nRecord.runtime) ? mergeI18nRuntimes(i18nRecord.runtime) : (_a = i18nRecord.runtime) != null ? _a : {};
793
+ resolveI18nRefs(mergedConfig, __spreadProps(__spreadValues({}, i18nRecord), { runtime }), langCode);
569
794
  }
570
795
  resolveImagePaths(mergedConfig, assetRecordByPath);
571
796
  _cachedConfig = mergedConfig;
@@ -1370,6 +1595,31 @@ var _sdk = class _sdk {
1370
1595
  static isGoogle() {
1371
1596
  return _sdk.getCurChannel() === "google";
1372
1597
  }
1598
+ /**
1599
+ * 获取当前用户语言的 i18n 简码。
1600
+ * 多源探测(querystring → localStorage → cookie → navigator → html tag)。
1601
+ *
1602
+ * @returns i18n 简码:en | zh | ja | ko | de | fr | es | pt | it | hi | bn | ur | ar | tr | ru | ms | id,默认 'en'
1603
+ *
1604
+ * @example
1605
+ * const langCode = sdk.getLanguageCode(); // 'zh'
1606
+ */
1607
+ static getLanguageCode() {
1608
+ return getLanguageCode();
1609
+ }
1610
+ /**
1611
+ * 获取当前用户语言的业务代号。
1612
+ * 多源探测(querystring → localStorage → cookie → navigator → html tag),
1613
+ * 并映射到业务语言代号(区分简繁中文)。
1614
+ *
1615
+ * @returns 业务代号:EN | CN_S | CN_T | DE | FR | ES | JA | KO | PT | IT | HI | BN | UR | AR | TR | RU | MS | IN | ID,默认 'EN'
1616
+ *
1617
+ * @example
1618
+ * const lang = sdk.getLanguage(); // 'CN_S'
1619
+ */
1620
+ static getLanguage() {
1621
+ return getLanguage();
1622
+ }
1373
1623
  /**
1374
1624
  * 设置主题配置,支持传入多份 JSON5 配置。
1375
1625
  * 每一份配置都可以是 JSON Schema(带 $schema 字段),会自动提取其中的 default 值。
@@ -1432,7 +1682,7 @@ var _sdk = class _sdk {
1432
1682
  }
1433
1683
  };
1434
1684
  /** Current version of the SDK */
1435
- _sdk.version = "1.0.18-beta.1";
1685
+ _sdk.version = "1.0.18-beta.3";
1436
1686
  /** Current maximum width of the playable ad container in pixels */
1437
1687
  _sdk.maxWidth = Math.floor(window.innerWidth);
1438
1688
  /** Current maximum height of the playable ad container in pixels */
@@ -1462,6 +1712,8 @@ window.PlayableSDK = sdk;
1462
1712
  0 && (module.exports = {
1463
1713
  disableCustomCursor,
1464
1714
  enableCustomCursor,
1715
+ getLanguage,
1716
+ getLanguageCode,
1465
1717
  hideWechatGuide,
1466
1718
  removeWechatGuide,
1467
1719
  sdk,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcraft/adsdk",
3
- "version": "1.0.18-beta.1",
3
+ "version": "1.0.18-beta.3",
4
4
  "description": "统一的 Playable SDK,支持 MRAID、Google、Facebook、Vungle、BigoAds 等多广告渠道",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",