@chipmobilesdk/rn-i18n 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/README.md +48 -17
  3. package/lib/commonjs/config/catalog.js +29 -0
  4. package/lib/commonjs/config/catalog.js.map +1 -0
  5. package/lib/commonjs/config/diagnostics.js +56 -0
  6. package/lib/commonjs/config/diagnostics.js.map +1 -0
  7. package/lib/commonjs/config/errors.js +35 -0
  8. package/lib/commonjs/config/errors.js.map +1 -0
  9. package/lib/commonjs/config/types.js +13 -0
  10. package/lib/commonjs/config/types.js.map +1 -0
  11. package/lib/commonjs/config/validateConfig.js +134 -0
  12. package/lib/commonjs/config/validateConfig.js.map +1 -0
  13. package/lib/commonjs/format/currency.js +35 -0
  14. package/lib/commonjs/format/currency.js.map +1 -0
  15. package/lib/commonjs/format/date.js +36 -0
  16. package/lib/commonjs/format/date.js.map +1 -0
  17. package/lib/commonjs/format/invalid.js +24 -0
  18. package/lib/commonjs/format/invalid.js.map +1 -0
  19. package/lib/commonjs/format/number.js +29 -0
  20. package/lib/commonjs/format/number.js.map +1 -0
  21. package/lib/commonjs/format/units.js +184 -0
  22. package/lib/commonjs/format/units.js.map +1 -0
  23. package/lib/commonjs/i18n.js +234 -0
  24. package/lib/commonjs/i18n.js.map +1 -0
  25. package/lib/commonjs/index.js +93 -0
  26. package/lib/commonjs/index.js.map +1 -0
  27. package/lib/commonjs/locale/activeLocale.js +37 -0
  28. package/lib/commonjs/locale/activeLocale.js.map +1 -0
  29. package/lib/commonjs/locale/deviceLocale.js +52 -0
  30. package/lib/commonjs/locale/deviceLocale.js.map +1 -0
  31. package/lib/commonjs/locale/keyValueStorage.js +29 -0
  32. package/lib/commonjs/locale/keyValueStorage.js.map +1 -0
  33. package/lib/commonjs/locale/persistence.js +74 -0
  34. package/lib/commonjs/locale/persistence.js.map +1 -0
  35. package/lib/commonjs/package.json +1 -0
  36. package/lib/commonjs/react/I18nProvider.js +36 -0
  37. package/lib/commonjs/react/I18nProvider.js.map +1 -0
  38. package/lib/commonjs/react/hooks.js +47 -0
  39. package/lib/commonjs/react/hooks.js.map +1 -0
  40. package/lib/commonjs/translation/interpolate.js +24 -0
  41. package/lib/commonjs/translation/interpolate.js.map +1 -0
  42. package/lib/commonjs/translation/plurals.js +122 -0
  43. package/lib/commonjs/translation/plurals.js.map +1 -0
  44. package/lib/commonjs/translation/resolver.js +124 -0
  45. package/lib/commonjs/translation/resolver.js.map +1 -0
  46. package/lib/commonjs/translation/runtimeKeys.js +55 -0
  47. package/lib/commonjs/translation/runtimeKeys.js.map +1 -0
  48. package/lib/module/config/catalog.js +25 -0
  49. package/lib/module/config/catalog.js.map +1 -0
  50. package/lib/module/config/diagnostics.js +51 -0
  51. package/lib/module/config/diagnostics.js.map +1 -0
  52. package/lib/module/config/errors.js +30 -0
  53. package/lib/module/config/errors.js.map +1 -0
  54. package/lib/module/config/types.js +26 -0
  55. package/lib/module/config/types.js.map +1 -0
  56. package/lib/module/config/validateConfig.js +131 -0
  57. package/lib/module/config/validateConfig.js.map +1 -0
  58. package/lib/module/format/currency.js +32 -0
  59. package/lib/module/format/currency.js.map +1 -0
  60. package/lib/module/format/date.js +33 -0
  61. package/lib/module/format/date.js.map +1 -0
  62. package/lib/module/format/invalid.js +21 -0
  63. package/lib/module/format/invalid.js.map +1 -0
  64. package/lib/module/format/number.js +26 -0
  65. package/lib/module/format/number.js.map +1 -0
  66. package/lib/module/format/units.js +171 -0
  67. package/lib/module/format/units.js.map +1 -0
  68. package/lib/module/i18n.js +230 -0
  69. package/lib/module/i18n.js.map +1 -0
  70. package/lib/module/index.js +23 -0
  71. package/lib/module/index.js.map +1 -0
  72. package/lib/module/locale/activeLocale.js +33 -0
  73. package/lib/module/locale/activeLocale.js.map +1 -0
  74. package/lib/module/locale/deviceLocale.js +46 -0
  75. package/lib/module/locale/deviceLocale.js.map +1 -0
  76. package/lib/module/locale/keyValueStorage.js +25 -0
  77. package/lib/module/locale/keyValueStorage.js.map +1 -0
  78. package/lib/module/locale/persistence.js +66 -0
  79. package/lib/module/locale/persistence.js.map +1 -0
  80. package/lib/module/package.json +1 -0
  81. package/lib/module/react/I18nProvider.js +29 -0
  82. package/lib/module/react/I18nProvider.js.map +1 -0
  83. package/lib/module/react/hooks.js +42 -0
  84. package/lib/module/react/hooks.js.map +1 -0
  85. package/lib/module/translation/interpolate.js +20 -0
  86. package/lib/module/translation/interpolate.js.map +1 -0
  87. package/lib/module/translation/plurals.js +114 -0
  88. package/lib/module/translation/plurals.js.map +1 -0
  89. package/lib/module/translation/resolver.js +118 -0
  90. package/lib/module/translation/resolver.js.map +1 -0
  91. package/lib/module/translation/runtimeKeys.js +50 -0
  92. package/lib/module/translation/runtimeKeys.js.map +1 -0
  93. package/lib/typescript/commonjs/config/catalog.d.ts +18 -0
  94. package/lib/typescript/commonjs/config/catalog.d.ts.map +1 -0
  95. package/lib/typescript/commonjs/config/diagnostics.d.ts +21 -0
  96. package/lib/typescript/commonjs/config/diagnostics.d.ts.map +1 -0
  97. package/lib/typescript/commonjs/config/errors.d.ts +16 -0
  98. package/lib/typescript/commonjs/config/errors.d.ts.map +1 -0
  99. package/lib/typescript/commonjs/config/types.d.ts +127 -0
  100. package/lib/typescript/commonjs/config/types.d.ts.map +1 -0
  101. package/lib/typescript/commonjs/config/validateConfig.d.ts +8 -0
  102. package/lib/typescript/commonjs/config/validateConfig.d.ts.map +1 -0
  103. package/lib/typescript/commonjs/format/currency.d.ts +12 -0
  104. package/lib/typescript/commonjs/format/currency.d.ts.map +1 -0
  105. package/lib/typescript/commonjs/format/date.d.ts +14 -0
  106. package/lib/typescript/commonjs/format/date.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/format/invalid.d.ts +12 -0
  108. package/lib/typescript/commonjs/format/invalid.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/format/number.d.ts +8 -0
  110. package/lib/typescript/commonjs/format/number.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/format/units.d.ts +23 -0
  112. package/lib/typescript/commonjs/format/units.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/i18n.d.ts +46 -0
  114. package/lib/typescript/commonjs/i18n.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/index.d.ts +27 -0
  116. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/locale/activeLocale.d.ts +17 -0
  118. package/lib/typescript/commonjs/locale/activeLocale.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/locale/deviceLocale.d.ts +19 -0
  120. package/lib/typescript/commonjs/locale/deviceLocale.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/locale/keyValueStorage.d.ts +13 -0
  122. package/lib/typescript/commonjs/locale/keyValueStorage.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/locale/persistence.d.ts +24 -0
  124. package/lib/typescript/commonjs/locale/persistence.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/package.json +1 -0
  126. package/lib/typescript/commonjs/react/I18nProvider.d.ts +16 -0
  127. package/lib/typescript/commonjs/react/I18nProvider.d.ts.map +1 -0
  128. package/lib/typescript/commonjs/react/hooks.d.ts +21 -0
  129. package/lib/typescript/commonjs/react/hooks.d.ts.map +1 -0
  130. package/lib/typescript/commonjs/translation/interpolate.d.ts +8 -0
  131. package/lib/typescript/commonjs/translation/interpolate.d.ts.map +1 -0
  132. package/lib/typescript/commonjs/translation/plurals.d.ts +13 -0
  133. package/lib/typescript/commonjs/translation/plurals.d.ts.map +1 -0
  134. package/lib/typescript/commonjs/translation/resolver.d.ts +24 -0
  135. package/lib/typescript/commonjs/translation/resolver.d.ts.map +1 -0
  136. package/lib/typescript/commonjs/translation/runtimeKeys.d.ts +16 -0
  137. package/lib/typescript/commonjs/translation/runtimeKeys.d.ts.map +1 -0
  138. package/lib/typescript/module/config/catalog.d.ts +18 -0
  139. package/lib/typescript/module/config/catalog.d.ts.map +1 -0
  140. package/lib/typescript/module/config/diagnostics.d.ts +21 -0
  141. package/lib/typescript/module/config/diagnostics.d.ts.map +1 -0
  142. package/lib/typescript/module/config/errors.d.ts +16 -0
  143. package/lib/typescript/module/config/errors.d.ts.map +1 -0
  144. package/lib/typescript/module/config/types.d.ts +127 -0
  145. package/lib/typescript/module/config/types.d.ts.map +1 -0
  146. package/lib/typescript/module/config/validateConfig.d.ts +8 -0
  147. package/lib/typescript/module/config/validateConfig.d.ts.map +1 -0
  148. package/lib/typescript/module/format/currency.d.ts +12 -0
  149. package/lib/typescript/module/format/currency.d.ts.map +1 -0
  150. package/lib/typescript/module/format/date.d.ts +14 -0
  151. package/lib/typescript/module/format/date.d.ts.map +1 -0
  152. package/lib/typescript/module/format/invalid.d.ts +12 -0
  153. package/lib/typescript/module/format/invalid.d.ts.map +1 -0
  154. package/lib/typescript/module/format/number.d.ts +8 -0
  155. package/lib/typescript/module/format/number.d.ts.map +1 -0
  156. package/lib/typescript/module/format/units.d.ts +23 -0
  157. package/lib/typescript/module/format/units.d.ts.map +1 -0
  158. package/lib/typescript/module/i18n.d.ts +46 -0
  159. package/lib/typescript/module/i18n.d.ts.map +1 -0
  160. package/lib/typescript/module/index.d.ts +27 -0
  161. package/lib/typescript/module/index.d.ts.map +1 -0
  162. package/lib/typescript/module/locale/activeLocale.d.ts +17 -0
  163. package/lib/typescript/module/locale/activeLocale.d.ts.map +1 -0
  164. package/lib/typescript/module/locale/deviceLocale.d.ts +19 -0
  165. package/lib/typescript/module/locale/deviceLocale.d.ts.map +1 -0
  166. package/lib/typescript/module/locale/keyValueStorage.d.ts +13 -0
  167. package/lib/typescript/module/locale/keyValueStorage.d.ts.map +1 -0
  168. package/lib/typescript/module/locale/persistence.d.ts +24 -0
  169. package/lib/typescript/module/locale/persistence.d.ts.map +1 -0
  170. package/lib/typescript/module/package.json +1 -0
  171. package/lib/typescript/module/react/I18nProvider.d.ts +16 -0
  172. package/lib/typescript/module/react/I18nProvider.d.ts.map +1 -0
  173. package/lib/typescript/module/react/hooks.d.ts +21 -0
  174. package/lib/typescript/module/react/hooks.d.ts.map +1 -0
  175. package/lib/typescript/module/translation/interpolate.d.ts +8 -0
  176. package/lib/typescript/module/translation/interpolate.d.ts.map +1 -0
  177. package/lib/typescript/module/translation/plurals.d.ts +13 -0
  178. package/lib/typescript/module/translation/plurals.d.ts.map +1 -0
  179. package/lib/typescript/module/translation/resolver.d.ts +24 -0
  180. package/lib/typescript/module/translation/resolver.d.ts.map +1 -0
  181. package/lib/typescript/module/translation/runtimeKeys.d.ts +16 -0
  182. package/lib/typescript/module/translation/runtimeKeys.d.ts.map +1 -0
  183. package/package.json +41 -18
  184. package/skills/sdk-rn-i18n/SKILL.md +27 -0
  185. package/src/config/diagnostics.ts +2 -0
  186. package/src/format/currency.ts +5 -0
  187. package/src/format/date.ts +10 -4
  188. package/src/i18n.ts +93 -9
  189. package/src/index.ts +5 -3
  190. package/src/locale/activeLocale.ts +10 -0
  191. package/src/locale/persistence.ts +19 -0
  192. package/src/translation/plurals.ts +74 -5
  193. package/src/translation/runtimeKeys.ts +28 -1
  194. package/src/tooling/cli.ts +0 -76
  195. package/src/tooling/generateKeys.ts +0 -62
  196. package/src/tooling/index.ts +0 -27
  197. package/src/tooling/report.ts +0 -109
  198. package/src/tooling/runner.ts +0 -111
  199. package/src/tooling/scan.ts +0 -193
  200. package/src/tooling/sync.ts +0 -193
  201. package/src/tooling/types.ts +0 -119
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createActiveLocaleStore = createActiveLocaleStore;
7
+ var _rnCore = require("@chipmobilesdk/rn-core");
8
+ var _diagnostics = require("../config/diagnostics.js");
9
+ function createActiveLocaleStore(initial, report = _diagnostics.defaultReporter) {
10
+ let preference = initial;
11
+ let version = 0;
12
+ const listeners = (0, _rnCore.createListenerSet)({
13
+ onListenerError: error => report({
14
+ code: 'listener_threw',
15
+ message: `A locale listener threw; the locale change still applied: ${(0, _diagnostics.describeError)(error)}`
16
+ })
17
+ });
18
+ return {
19
+ get: () => preference,
20
+ set(next) {
21
+ preference = next;
22
+ version += 1;
23
+ // Isolated (CORE-03). One that threw used to skip every listener after
24
+ // it — useSyncExternalStore subscribers included — and made setLocale
25
+ // reject after the switch but before the choice was persisted, so the
26
+ // app showed one locale and stored another.
27
+ listeners.notify();
28
+ },
29
+ bump() {
30
+ version += 1;
31
+ listeners.notify();
32
+ },
33
+ subscribe: listener => listeners.add(listener),
34
+ getVersion: () => version
35
+ };
36
+ }
37
+ //# sourceMappingURL=activeLocale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_rnCore","require","_diagnostics","createActiveLocaleStore","initial","report","defaultReporter","preference","version","listeners","createListenerSet","onListenerError","error","code","message","describeError","get","set","next","notify","bump","subscribe","listener","add","getVersion"],"sourceRoot":"../../../src","sources":["locale/activeLocale.ts"],"mappings":";;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;AAEA,IAAAC,YAAA,GAAAD,OAAA;AAiBO,SAASE,uBAAuBA,CACtCC,OAA+B,EAC/BC,MAA6B,GAAGC,4BAAe,EAC3B;EACpB,IAAIC,UAAU,GAAGH,OAAO;EACxB,IAAII,OAAO,GAAG,CAAC;EACf,MAAMC,SAAS,GAAG,IAAAC,yBAAiB,EAAK;IACvCC,eAAe,EAAEC,KAAK,IACrBP,MAAM,CAAC;MACNQ,IAAI,EAAE,gBAAgB;MACtBC,OAAO,EAAE,6DAA6D,IAAAC,0BAAa,EAACH,KAAK,CAAC;IAC3F,CAAC;EACH,CAAC,CAAC;EAEF,OAAO;IACNI,GAAG,EAAEA,CAAA,KAAMT,UAAU;IACrBU,GAAGA,CAACC,IAAI,EAAE;MACTX,UAAU,GAAGW,IAAI;MACjBV,OAAO,IAAI,CAAC;MACZ;MACA;MACA;MACA;MACAC,SAAS,CAACU,MAAM,CAAC,CAAC;IACnB,CAAC;IACDC,IAAIA,CAAA,EAAG;MACNZ,OAAO,IAAI,CAAC;MACZC,SAAS,CAACU,MAAM,CAAC,CAAC;IACnB,CAAC;IACDE,SAAS,EAAEC,QAAQ,IAAIb,SAAS,CAACc,GAAG,CAACD,QAAQ,CAAC;IAC9CE,UAAU,EAAEA,CAAA,KAAMhB;EACnB,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.defaultDeviceLocaleProvider = void 0;
7
+ exports.matchSupportedLocale = matchSupportedLocale;
8
+ /**
9
+ * Default device locale detection. Hermes resolves the Intl default locale
10
+ * from the device locale on both Android and iOS, so no native module is
11
+ * required. Apps may inject their own provider (e.g. react-native-localize)
12
+ * through `I18nConfig.deviceLocale`.
13
+ */
14
+ const defaultDeviceLocaleProvider = () => {
15
+ try {
16
+ return Intl.DateTimeFormat().resolvedOptions().locale;
17
+ } catch {
18
+ return undefined;
19
+ }
20
+ };
21
+ exports.defaultDeviceLocaleProvider = defaultDeviceLocaleProvider;
22
+ /**
23
+ * Matches a detected device locale against the supported locales: an exact
24
+ * (case-insensitive) match wins; otherwise a device language that matches
25
+ * exactly one supported locale selects that locale (US4 scenario 3).
26
+ */
27
+ function matchSupportedLocale(deviceLocale, locales) {
28
+ if (!deviceLocale) {
29
+ return undefined;
30
+ }
31
+ const normalized = deviceLocale.toLowerCase();
32
+ const exact = locales.find(locale => locale.code.toLowerCase() === normalized);
33
+ if (exact) {
34
+ return {
35
+ code: exact.code,
36
+ source: 'device'
37
+ };
38
+ }
39
+ const language = normalized.split('-')[0];
40
+ if (!language) {
41
+ return undefined;
42
+ }
43
+ const languageMatches = locales.filter(locale => locale.code.toLowerCase().split('-')[0] === language);
44
+ if (languageMatches.length === 1) {
45
+ return {
46
+ code: languageMatches[0].code,
47
+ source: 'languageMatch'
48
+ };
49
+ }
50
+ return undefined;
51
+ }
52
+ //# sourceMappingURL=deviceLocale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["defaultDeviceLocaleProvider","Intl","DateTimeFormat","resolvedOptions","locale","undefined","exports","matchSupportedLocale","deviceLocale","locales","normalized","toLowerCase","exact","find","code","source","language","split","languageMatches","filter","length"],"sourceRoot":"../../../src","sources":["locale/deviceLocale.ts"],"mappings":";;;;;;;AAEA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMA,2BAAiD,GAAGA,CAAA,KAAM;EACtE,IAAI;IACH,OAAOC,IAAI,CAACC,cAAc,CAAC,CAAC,CAACC,eAAe,CAAC,CAAC,CAACC,MAAM;EACtD,CAAC,CAAC,MAAM;IACP,OAAOC,SAAS;EACjB;AACD,CAAC;AAACC,OAAA,CAAAN,2BAAA,GAAAA,2BAAA;AAOF;AACA;AACA;AACA;AACA;AACO,SAASO,oBAAoBA,CACnCC,YAAgC,EAChCC,OAAgC,EACA;EAChC,IAAI,CAACD,YAAY,EAAE;IAClB,OAAOH,SAAS;EACjB;EACA,MAAMK,UAAU,GAAGF,YAAY,CAACG,WAAW,CAAC,CAAC;EAC7C,MAAMC,KAAK,GAAGH,OAAO,CAACI,IAAI,CAACT,MAAM,IAAIA,MAAM,CAACU,IAAI,CAACH,WAAW,CAAC,CAAC,KAAKD,UAAU,CAAC;EAC9E,IAAIE,KAAK,EAAE;IACV,OAAO;MAAEE,IAAI,EAAEF,KAAK,CAACE,IAAI;MAAEC,MAAM,EAAE;IAAS,CAAC;EAC9C;EACA,MAAMC,QAAQ,GAAGN,UAAU,CAACO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;EACzC,IAAI,CAACD,QAAQ,EAAE;IACd,OAAOX,SAAS;EACjB;EACA,MAAMa,eAAe,GAAGT,OAAO,CAACU,MAAM,CACrCf,MAAM,IAAIA,MAAM,CAACU,IAAI,CAACH,WAAW,CAAC,CAAC,CAACM,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAKD,QACvD,CAAC;EACD,IAAIE,eAAe,CAACE,MAAM,KAAK,CAAC,EAAE;IACjC,OAAO;MAAEN,IAAI,EAAEI,eAAe,CAAC,CAAC,CAAC,CAACJ,IAAI;MAAEC,MAAM,EAAE;IAAgB,CAAC;EAClE;EACA,OAAOV,SAAS;AACjB","ignoreList":[]}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.localeStorageFromKeyValue = localeStorageFromKeyValue;
7
+ /**
8
+ * A `LocaleStorageAdapter` over rn-core's synchronous `KeyValuePort` (PERF-08).
9
+ *
10
+ * The adapter carries `getItemSync`, so `i18n.initSync()` resolves the persisted
11
+ * locale before the first render. Open the port the way the app opens its other
12
+ * durable state, for example `openDurable(() => createMMKV({ id: 'app' }))`.
13
+ */
14
+
15
+ function localeStorageFromKeyValue(port) {
16
+ return {
17
+ getItemSync: key => port.getString(key) ?? null,
18
+ async getItem(key) {
19
+ return port.getString(key) ?? null;
20
+ },
21
+ async setItem(key, value) {
22
+ port.set(key, value);
23
+ },
24
+ async removeItem(key) {
25
+ port.remove(key);
26
+ }
27
+ };
28
+ }
29
+ //# sourceMappingURL=keyValueStorage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["localeStorageFromKeyValue","port","getItemSync","key","getString","getItem","setItem","value","set","removeItem","remove"],"sourceRoot":"../../../src","sources":["locale/keyValueStorage.ts"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAKO,SAASA,yBAAyBA,CACxCC,IAAkB,EACmD;EACrE,OAAO;IACNC,WAAW,EAAEC,GAAG,IAAIF,IAAI,CAACG,SAAS,CAACD,GAAG,CAAC,IAAI,IAAI;IAC/C,MAAME,OAAOA,CAACF,GAAG,EAAE;MAClB,OAAOF,IAAI,CAACG,SAAS,CAACD,GAAG,CAAC,IAAI,IAAI;IACnC,CAAC;IACD,MAAMG,OAAOA,CAACH,GAAG,EAAEI,KAAK,EAAE;MACzBN,IAAI,CAACO,GAAG,CAACL,GAAG,EAAEI,KAAK,CAAC;IACrB,CAAC;IACD,MAAME,UAAUA,CAACN,GAAG,EAAE;MACrBF,IAAI,CAACS,MAAM,CAACP,GAAG,CAAC;IACjB;EACD,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.LOCALE_STORAGE_KEY = void 0;
7
+ exports.clearPersistedLocale = clearPersistedLocale;
8
+ exports.readPersistedLocale = readPersistedLocale;
9
+ exports.readPersistedLocaleSync = readPersistedLocaleSync;
10
+ exports.writePersistedLocale = writePersistedLocale;
11
+ var _diagnostics = require("../config/diagnostics.js");
12
+ const LOCALE_STORAGE_KEY = exports.LOCALE_STORAGE_KEY = '@chipmobilesdk/rn-i18n:locale';
13
+
14
+ /**
15
+ * Reads the persisted locale preference. Adapter failures are reported and
16
+ * treated as "no persisted value" so locale selection never crashes (FR-015).
17
+ */
18
+ async function readPersistedLocale(storage, report = _diagnostics.defaultReporter) {
19
+ try {
20
+ return await storage.getItem(LOCALE_STORAGE_KEY);
21
+ } catch (error) {
22
+ report({
23
+ code: 'locale_read_failed',
24
+ message: `Failed to read the persisted locale preference: ${(0, _diagnostics.describeError)(error)}`
25
+ });
26
+ return null;
27
+ }
28
+ }
29
+
30
+ /** `readPersistedLocale` for a store with a synchronous read; same failure handling. */
31
+ function readPersistedLocaleSync(storage, report = _diagnostics.defaultReporter) {
32
+ try {
33
+ return storage.getItemSync(LOCALE_STORAGE_KEY);
34
+ } catch (error) {
35
+ report({
36
+ code: 'locale_read_failed',
37
+ message: `Failed to read the persisted locale preference: ${(0, _diagnostics.describeError)(error)}`
38
+ });
39
+ return null;
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Persists the selected locale. Persistence is best-effort: a write failure
45
+ * is reported but the in-memory locale switch stays authoritative.
46
+ */
47
+ async function writePersistedLocale(storage, code, report = _diagnostics.defaultReporter) {
48
+ try {
49
+ await storage.setItem(LOCALE_STORAGE_KEY, code);
50
+ } catch (error) {
51
+ report({
52
+ code: 'locale_write_failed',
53
+ locale: code,
54
+ message: `Failed to persist locale "${code}": ${(0, _diagnostics.describeError)(error)}`
55
+ });
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Forgets the stored choice, so the next launch follows the device again. The
61
+ * adapter's `removeItem` was required by the contract and called by nothing
62
+ * until `useDeviceLocale()` (I18N-17). Best-effort, like the write.
63
+ */
64
+ async function clearPersistedLocale(storage, report = _diagnostics.defaultReporter) {
65
+ try {
66
+ await storage.removeItem(LOCALE_STORAGE_KEY);
67
+ } catch (error) {
68
+ report({
69
+ code: 'locale_write_failed',
70
+ message: `Failed to forget the persisted locale preference: ${(0, _diagnostics.describeError)(error)}`
71
+ });
72
+ }
73
+ }
74
+ //# sourceMappingURL=persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_diagnostics","require","LOCALE_STORAGE_KEY","exports","readPersistedLocale","storage","report","defaultReporter","getItem","error","code","message","describeError","readPersistedLocaleSync","getItemSync","writePersistedLocale","setItem","locale","clearPersistedLocale","removeItem"],"sourceRoot":"../../../src","sources":["locale/persistence.ts"],"mappings":";;;;;;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAGO,MAAMC,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,GAAG,+BAA+B;;AAEjE;AACA;AACA;AACA;AACO,eAAeE,mBAAmBA,CACxCC,OAA6B,EAC7BC,MAA6B,GAAGC,4BAAe,EACtB;EACzB,IAAI;IACH,OAAO,MAAMF,OAAO,CAACG,OAAO,CAACN,kBAAkB,CAAC;EACjD,CAAC,CAAC,OAAOO,KAAK,EAAE;IACfH,MAAM,CAAC;MACNI,IAAI,EAAE,oBAAoB;MAC1BC,OAAO,EAAE,mDAAmD,IAAAC,0BAAa,EAACH,KAAK,CAAC;IACjF,CAAC,CAAC;IACF,OAAO,IAAI;EACZ;AACD;;AAEA;AACO,SAASI,uBAAuBA,CACtCR,OAA2E,EAC3EC,MAA6B,GAAGC,4BAAe,EAC/B;EAChB,IAAI;IACH,OAAOF,OAAO,CAACS,WAAW,CAACZ,kBAAkB,CAAC;EAC/C,CAAC,CAAC,OAAOO,KAAK,EAAE;IACfH,MAAM,CAAC;MACNI,IAAI,EAAE,oBAAoB;MAC1BC,OAAO,EAAE,mDAAmD,IAAAC,0BAAa,EAACH,KAAK,CAAC;IACjF,CAAC,CAAC;IACF,OAAO,IAAI;EACZ;AACD;;AAEA;AACA;AACA;AACA;AACO,eAAeM,oBAAoBA,CACzCV,OAA6B,EAC7BK,IAAY,EACZJ,MAA6B,GAAGC,4BAAe,EAC/B;EAChB,IAAI;IACH,MAAMF,OAAO,CAACW,OAAO,CAACd,kBAAkB,EAAEQ,IAAI,CAAC;EAChD,CAAC,CAAC,OAAOD,KAAK,EAAE;IACfH,MAAM,CAAC;MACNI,IAAI,EAAE,qBAAqB;MAC3BO,MAAM,EAAEP,IAAI;MACZC,OAAO,EAAE,6BAA6BD,IAAI,MAAM,IAAAE,0BAAa,EAACH,KAAK,CAAC;IACrE,CAAC,CAAC;EACH;AACD;;AAEA;AACA;AACA;AACA;AACA;AACO,eAAeS,oBAAoBA,CACzCb,OAA6B,EAC7BC,MAA6B,GAAGC,4BAAe,EAC/B;EAChB,IAAI;IACH,MAAMF,OAAO,CAACc,UAAU,CAACjB,kBAAkB,CAAC;EAC7C,CAAC,CAAC,OAAOO,KAAK,EAAE;IACfH,MAAM,CAAC;MACNI,IAAI,EAAE,qBAAqB;MAC3BC,OAAO,EAAE,qDAAqD,IAAAC,0BAAa,EAACH,KAAK,CAAC;IACnF,CAAC,CAAC;EACH;AACD","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.I18nContext = void 0;
7
+ exports.I18nProvider = I18nProvider;
8
+ exports.useI18nContext = useI18nContext;
9
+ var _react = _interopRequireWildcard(require("react"));
10
+ var _jsxRuntime = require("react/jsx-runtime");
11
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
12
+ // The context intentionally erases the app-specific key type; the typed
13
+ // surface is restored by the hooks' generic parameters.
14
+ const I18nContext = exports.I18nContext = /*#__PURE__*/(0, _react.createContext)(null);
15
+ /**
16
+ * Provides the I18n instance to the React tree. Locale changes re-render
17
+ * consumers through the hooks' useSyncExternalStore subscription, so a
18
+ * runtime switch updates UI within one interaction cycle (PERF-002).
19
+ */
20
+ function I18nProvider({
21
+ i18n,
22
+ children
23
+ }) {
24
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(I18nContext.Provider, {
25
+ value: i18n,
26
+ children: children
27
+ });
28
+ }
29
+ function useI18nContext() {
30
+ const i18n = (0, _react.useContext)(I18nContext);
31
+ if (!i18n) {
32
+ throw new Error('[rn-i18n] No I18n instance found. Wrap your app in <I18nProvider>.');
33
+ }
34
+ return i18n;
35
+ }
36
+ //# sourceMappingURL=I18nProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","I18nContext","exports","createContext","I18nProvider","i18n","children","jsx","Provider","value","useI18nContext","useContext","Error"],"sourceRoot":"../../../src","sources":["react/I18nProvider.tsx"],"mappings":";;;;;;;;AAAA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AAAyD,IAAAC,WAAA,GAAAD,OAAA;AAAA,SAAAD,wBAAAG,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAL,uBAAA,YAAAA,CAAAG,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAIzD;AACA;AACO,MAAMkB,WAAW,GAAAC,OAAA,CAAAD,WAAA,gBAAG,IAAAE,oBAAa,EAAsB,IAAI,CAAC;AAOnE;AACA;AACA;AACA;AACA;AACO,SAASC,YAAYA,CAAC;EAAEC,IAAI;EAAEC;AAA4B,CAAC,EAAE;EACnE,oBACC,IAAAzB,WAAA,CAAA0B,GAAA,EAACN,WAAW,CAACO,QAAQ;IAACC,KAAK,EAAEJ,IAAgC;IAAAC,QAAA,EAAEA;EAAQ,CAAuB,CAAC;AAEjG;AAEO,SAASI,cAAcA,CAAA,EAAiB;EAC9C,MAAML,IAAI,GAAG,IAAAM,iBAAU,EAACV,WAAW,CAAC;EACpC,IAAI,CAACI,IAAI,EAAE;IACV,MAAM,IAAIO,KAAK,CAAC,oEAAoE,CAAC;EACtF;EACA,OAAOP,IAAI;AACZ","ignoreList":[]}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useLocale = useLocale;
7
+ exports.useTranslation = useTranslation;
8
+ var _react = require("react");
9
+ var _I18nProvider = require("./I18nProvider.js");
10
+ function useLocaleVersion(i18n) {
11
+ return (0, _react.useSyncExternalStore)(i18n.subscribe, i18n.getVersion, i18n.getVersion);
12
+ }
13
+ /**
14
+ * Returns the translation function bound to the active locale. Pass the
15
+ * app's generated key type for compile-time key validation (FR-041):
16
+ * `const { t } = useTranslation<AppI18nKey>();`
17
+ */
18
+ function useTranslation() {
19
+ const i18n = (0, _I18nProvider.useI18nContext)();
20
+ const version = useLocaleVersion(i18n);
21
+ // One `t` and one result per locale version (I18N-05): a memoized child that
22
+ // takes `t` re-renders when the locale changes, not on every parent render.
23
+ return (0, _react.useMemo)(() => ({
24
+ t: (key, vars, options) => i18n.t(key, vars, options),
25
+ locale: i18n.getLocale().code
26
+ }),
27
+ // `version` is the dependency that matters: it changes with the locale.
28
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- `version` is read to invalidate, not used
29
+ [i18n, version]);
30
+ }
31
+ /** Returns active locale state, direction metadata, and the locale switcher. */
32
+ function useLocale() {
33
+ const i18n = (0, _I18nProvider.useI18nContext)();
34
+ useLocaleVersion(i18n);
35
+ const setLocale = (0, _react.useCallback)(code => i18n.setLocale(code), [i18n]);
36
+ const preference = i18n.getLocale();
37
+ const supportedLocales = i18n.getSupportedLocales();
38
+ const active = supportedLocales.find(locale => locale.code === preference.code);
39
+ return {
40
+ locale: preference.code,
41
+ direction: active?.direction ?? 'ltr',
42
+ preference,
43
+ supportedLocales,
44
+ setLocale
45
+ };
46
+ }
47
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","require","_I18nProvider","useLocaleVersion","i18n","useSyncExternalStore","subscribe","getVersion","useTranslation","useI18nContext","version","useMemo","t","key","vars","options","locale","getLocale","code","useLocale","setLocale","useCallback","preference","supportedLocales","getSupportedLocales","active","find","direction"],"sourceRoot":"../../../src","sources":["react/hooks.ts"],"mappings":";;;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AASA,IAAAC,aAAA,GAAAD,OAAA;AAEA,SAASE,gBAAgBA,CAACC,IAAkB,EAAU;EACrD,OAAO,IAAAC,2BAAoB,EAACD,IAAI,CAACE,SAAS,EAAEF,IAAI,CAACG,UAAU,EAAEH,IAAI,CAACG,UAAU,CAAC;AAC9E;AAOA;AACA;AACA;AACA;AACA;AACO,SAASC,cAAcA,CAAA,EAA6D;EAC1F,MAAMJ,IAAI,GAAG,IAAAK,4BAAc,EAAC,CAAC;EAC7B,MAAMC,OAAO,GAAGP,gBAAgB,CAACC,IAAI,CAAC;EACtC;EACA;EACA,OAAO,IAAAO,cAAO,EACb,OAAO;IACNC,CAAC,EAAEA,CAACC,GAAS,EAAEC,IAAoB,EAAEC,OAA0B,KAC9DX,IAAI,CAACQ,CAAC,CAACC,GAAG,EAAEC,IAAI,EAAEC,OAAO,CAAC;IAC3BC,MAAM,EAAEZ,IAAI,CAACa,SAAS,CAAC,CAAC,CAACC;EAC1B,CAAC,CAAC;EACF;EACA;EACA,CAACd,IAAI,EAAEM,OAAO,CACf,CAAC;AACF;AAUA;AACO,SAASS,SAASA,CAAA,EAAoB;EAC5C,MAAMf,IAAI,GAAG,IAAAK,4BAAc,EAAC,CAAC;EAC7BN,gBAAgB,CAACC,IAAI,CAAC;EACtB,MAAMgB,SAAS,GAAG,IAAAC,kBAAW,EAAEH,IAAY,IAAKd,IAAI,CAACgB,SAAS,CAACF,IAAI,CAAC,EAAE,CAACd,IAAI,CAAC,CAAC;EAC7E,MAAMkB,UAAU,GAAGlB,IAAI,CAACa,SAAS,CAAC,CAAC;EACnC,MAAMM,gBAAgB,GAAGnB,IAAI,CAACoB,mBAAmB,CAAC,CAAC;EACnD,MAAMC,MAAM,GAAGF,gBAAgB,CAACG,IAAI,CAACV,MAAM,IAAIA,MAAM,CAACE,IAAI,KAAKI,UAAU,CAACJ,IAAI,CAAC;EAC/E,OAAO;IACNF,MAAM,EAAEM,UAAU,CAACJ,IAAI;IACvBS,SAAS,EAAEF,MAAM,EAAEE,SAAS,IAAI,KAAK;IACrCL,UAAU;IACVC,gBAAgB;IAChBH;EACD,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.interpolate = interpolate;
7
+ const VARIABLE_PATTERN = /\{\{\s*([\w.]+)\s*\}\}/g;
8
+
9
+ /**
10
+ * Replaces `{{name}}` placeholders with named values. Missing variables keep
11
+ * their placeholder text so the result stays deterministic, and each missing
12
+ * name is reported through `onMissingVariable`.
13
+ */
14
+ function interpolate(text, vars, onMissingVariable) {
15
+ return text.replace(VARIABLE_PATTERN, (placeholder, name) => {
16
+ const value = vars?.[name];
17
+ if (value === undefined || value === null) {
18
+ onMissingVariable?.(name);
19
+ return placeholder;
20
+ }
21
+ return String(value);
22
+ });
23
+ }
24
+ //# sourceMappingURL=interpolate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["VARIABLE_PATTERN","interpolate","text","vars","onMissingVariable","replace","placeholder","name","value","undefined","String"],"sourceRoot":"../../../src","sources":["translation/interpolate.ts"],"mappings":";;;;;;AAEA,MAAMA,gBAAgB,GAAG,yBAAyB;;AAElD;AACA;AACA;AACA;AACA;AACO,SAASC,WAAWA,CAC1BC,IAAY,EACZC,IAAoB,EACpBC,iBAA0C,EACjC;EACT,OAAOF,IAAI,CAACG,OAAO,CAACL,gBAAgB,EAAE,CAACM,WAAW,EAAEC,IAAY,KAAK;IACpE,MAAMC,KAAK,GAAGL,IAAI,GAAGI,IAAI,CAAC;IAC1B,IAAIC,KAAK,KAAKC,SAAS,IAAID,KAAK,KAAK,IAAI,EAAE;MAC1CJ,iBAAiB,GAAGG,IAAI,CAAC;MACzB,OAAOD,WAAW;IACnB;IACA,OAAOI,MAAM,CAACF,KAAK,CAAC;EACrB,CAAC,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.PLURAL_CATEGORIES = exports.DEFAULT_PLURAL_RULE = void 0;
7
+ exports.hasPluralRule = hasPluralRule;
8
+ exports.isPluralGroup = isPluralGroup;
9
+ exports.resolvePluralRule = resolvePluralRule;
10
+ exports.selectPluralVariant = selectPluralVariant;
11
+ const PLURAL_CATEGORIES = exports.PLURAL_CATEGORIES = ['zero', 'one', 'two', 'few', 'many', 'other'];
12
+ const oneOtherRule = count => count === 1 ? 'one' : 'other';
13
+ const otherOnlyRule = () => 'other';
14
+ /** French and Brazilian Portuguese: 0 and 1 are both singular. */
15
+ const zeroOneRule = count => count === 0 || count === 1 ? 'one' : 'other';
16
+
17
+ /** Russian, Ukrainian, Polish, Czech and their neighbours (CLDR). */
18
+ const slavicRule = count => {
19
+ if (!Number.isInteger(count)) {
20
+ return 'many';
21
+ }
22
+ const mod10 = Math.abs(count) % 10;
23
+ const mod100 = Math.abs(count) % 100;
24
+ if (mod10 === 1 && mod100 !== 11) {
25
+ return 'one';
26
+ }
27
+ if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) {
28
+ return 'few';
29
+ }
30
+ return 'many';
31
+ };
32
+
33
+ /** Arabic (CLDR), which uses every category. */
34
+ const arabicRule = count => {
35
+ if (count === 0) return 'zero';
36
+ if (count === 1) return 'one';
37
+ if (count === 2) return 'two';
38
+ const mod100 = Math.abs(count) % 100;
39
+ if (mod100 >= 3 && mod100 <= 10) return 'few';
40
+ if (mod100 >= 11 && mod100 <= 99) return 'many';
41
+ return 'other';
42
+ };
43
+
44
+ /**
45
+ * Package-owned plural rules, a compact subset of CLDR. Intl.PluralRules is not
46
+ * implemented by Hermes, so rules are resolved from configuration to keep
47
+ * behavior identical across devices and test environments.
48
+ *
49
+ * A language that is not here falls back to `count === 1 ? one : other`, which
50
+ * is wrong for most of the world — Korean and Thai have no singular, French
51
+ * calls 0 singular, Russian has `few` and `many` — so the fallback now reports
52
+ * a diagnostic once per locale rather than being silently applied (I18N-12).
53
+ */
54
+ const BUILT_IN_RULES = {
55
+ // one/other
56
+ en: oneOtherRule,
57
+ de: oneOtherRule,
58
+ es: oneOtherRule,
59
+ it: oneOtherRule,
60
+ nl: oneOtherRule,
61
+ sv: oneOtherRule,
62
+ da: oneOtherRule,
63
+ nb: oneOtherRule,
64
+ fi: oneOtherRule,
65
+ el: oneOtherRule,
66
+ he: oneOtherRule,
67
+ // other only
68
+ ja: otherOnlyRule,
69
+ vi: otherOnlyRule,
70
+ ko: otherOnlyRule,
71
+ zh: otherOnlyRule,
72
+ th: otherOnlyRule,
73
+ id: otherOnlyRule,
74
+ ms: otherOnlyRule,
75
+ // 0 and 1 are singular
76
+ fr: zeroOneRule,
77
+ pt: zeroOneRule,
78
+ // Slavic
79
+ ru: slavicRule,
80
+ uk: slavicRule,
81
+ pl: slavicRule,
82
+ cs: slavicRule,
83
+ sk: slavicRule,
84
+ // Every category
85
+ ar: arabicRule
86
+ };
87
+ const DEFAULT_PLURAL_RULE = exports.DEFAULT_PLURAL_RULE = oneOtherRule;
88
+
89
+ /** True when this package has a rule for the language, or the locale brought one. */
90
+ function hasPluralRule(locale) {
91
+ if (locale.pluralRule) {
92
+ return true;
93
+ }
94
+ const language = locale.code.split('-')[0]?.toLowerCase() ?? '';
95
+ return language in BUILT_IN_RULES;
96
+ }
97
+ function resolvePluralRule(locale) {
98
+ if (locale.pluralRule) {
99
+ return locale.pluralRule;
100
+ }
101
+ const language = locale.code.split('-')[0]?.toLowerCase() ?? '';
102
+ return BUILT_IN_RULES[language] ?? DEFAULT_PLURAL_RULE;
103
+ }
104
+
105
+ /**
106
+ * A plural group is an object whose keys are all plural categories, whose
107
+ * values are all strings, and which provides the required `other` variant.
108
+ */
109
+ function isPluralGroup(node) {
110
+ if (typeof node !== 'object' || node === null) {
111
+ return false;
112
+ }
113
+ const keys = Object.keys(node);
114
+ if (keys.length === 0 || !('other' in node)) {
115
+ return false;
116
+ }
117
+ return keys.every(key => PLURAL_CATEGORIES.includes(key) && typeof node[key] === 'string');
118
+ }
119
+ function selectPluralVariant(group, category) {
120
+ return group[category] ?? group.other;
121
+ }
122
+ //# sourceMappingURL=plurals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["PLURAL_CATEGORIES","exports","oneOtherRule","count","otherOnlyRule","zeroOneRule","slavicRule","Number","isInteger","mod10","Math","abs","mod100","arabicRule","BUILT_IN_RULES","en","de","es","it","nl","sv","da","nb","fi","el","he","ja","vi","ko","zh","th","id","ms","fr","pt","ru","uk","pl","cs","sk","ar","DEFAULT_PLURAL_RULE","hasPluralRule","locale","pluralRule","language","code","split","toLowerCase","resolvePluralRule","isPluralGroup","node","keys","Object","length","every","key","includes","selectPluralVariant","group","category","other"],"sourceRoot":"../../../src","sources":["translation/plurals.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getTranslationNode = getTranslationNode;
7
+ exports.translate = translate;
8
+ exports.warnOnce = warnOnce;
9
+ var _interpolate = require("./interpolate.js");
10
+ var _plurals = require("./plurals.js");
11
+ /**
12
+ * How many lookup paths are remembered. An app that misses many distinct keys
13
+ * forgets the oldest first, so memory stays bounded (I18N-11).
14
+ */
15
+ const WARNED_CAPACITY = 500;
16
+ function warnOnce(context, dedupeKey, diagnostic) {
17
+ const {
18
+ warned
19
+ } = context;
20
+ if (warned.has(dedupeKey)) {
21
+ return;
22
+ }
23
+ warned.add(dedupeKey);
24
+ if (warned.size > WARNED_CAPACITY) {
25
+ const oldest = warned.values().next().value;
26
+ if (oldest !== undefined) warned.delete(oldest);
27
+ }
28
+ context.report(diagnostic);
29
+ }
30
+
31
+ /** Walks a dot-path key through a nested translation namespace. */
32
+ function getTranslationNode(namespace, key) {
33
+ if (!namespace) {
34
+ return undefined;
35
+ }
36
+ let node = namespace;
37
+ for (const segment of key.split('.')) {
38
+ if (typeof node !== 'object' || node === null) {
39
+ return undefined;
40
+ }
41
+ const next = node[segment];
42
+ if (next === undefined) {
43
+ return undefined;
44
+ }
45
+ node = next;
46
+ }
47
+ return node;
48
+ }
49
+ function pickValue(node, locale, options, warnings, key) {
50
+ if (typeof node === 'string') {
51
+ return node;
52
+ }
53
+ if ((0, _plurals.isPluralGroup)(node)) {
54
+ const count = options?.count;
55
+ if (count === undefined) {
56
+ return node.other;
57
+ }
58
+ return (0, _plurals.selectPluralVariant)(node, (0, _plurals.resolvePluralRule)(locale)(count));
59
+ }
60
+ warnOnce(warnings, `invalid-value|${locale.code}|${key}`, {
61
+ code: 'invalid_value',
62
+ key,
63
+ locale: locale.code,
64
+ message: `Translation value for "${key}" in locale "${locale.code}" is not text or a plural group; treating it as missing.`
65
+ });
66
+ return undefined;
67
+ }
68
+
69
+ /**
70
+ * Resolves a key through the active locale, its ordered fallback chain, and
71
+ * declared runtime-only default text, applying plural selection and named
72
+ * variable interpolation. Misses are reported with one console warning per
73
+ * lookup path; a full-chain miss applies the configured missing-translation
74
+ * policy (FR-008…FR-011, FR-033).
75
+ */
76
+ function translate(context, activeCode, key, vars, options) {
77
+ const active = context.localesByCode.get(activeCode);
78
+ const chain = [activeCode, ...(active?.fallbackChain ?? [])];
79
+ const mergedVars = options?.count === undefined ? vars : {
80
+ count: options.count,
81
+ ...vars
82
+ };
83
+ const interpolateWith = (text, sourceLocale) => (0, _interpolate.interpolate)(text, mergedVars, name => warnOnce(context, `missing-var|${sourceLocale}|${key}|${name}`, {
84
+ code: 'missing_variable',
85
+ key,
86
+ locale: sourceLocale,
87
+ message: `Missing interpolation variable "${name}" for key "${key}" in locale "${sourceLocale}".`
88
+ }));
89
+ for (const code of chain) {
90
+ const locale = context.localesByCode.get(code);
91
+ if (!locale) {
92
+ continue;
93
+ }
94
+ const node = getTranslationNode(context.resources[code], key);
95
+ if (node === undefined) {
96
+ continue;
97
+ }
98
+ const value = pickValue(node, locale, options, context, key);
99
+ if (value === undefined) {
100
+ continue;
101
+ }
102
+ if (code !== activeCode) {
103
+ warnOnce(context, `fallback|${activeCode}|${key}`, {
104
+ code: 'fallback_used',
105
+ key,
106
+ locale: activeCode,
107
+ message: `Key "${key}" is missing in locale "${activeCode}"; served from fallback locale "${code}".`
108
+ });
109
+ }
110
+ return interpolateWith(value, code);
111
+ }
112
+ const runtimeEntry = context.runtimeEntries.get(key);
113
+ if (runtimeEntry) {
114
+ return interpolateWith(runtimeEntry.defaultText, activeCode);
115
+ }
116
+ warnOnce(context, `missing|${activeCode}|${key}`, {
117
+ code: 'missing_translation',
118
+ key,
119
+ locale: activeCode,
120
+ message: `Missing translation for key "${key}" in locale "${activeCode}" and its entire fallback chain.`
121
+ });
122
+ return context.missingTranslation.mode === 'placeholder' ? context.missingTranslation.text : key;
123
+ }
124
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_interpolate","require","_plurals","WARNED_CAPACITY","warnOnce","context","dedupeKey","diagnostic","warned","has","add","size","oldest","values","next","value","undefined","delete","report","getTranslationNode","namespace","key","node","segment","split","pickValue","locale","options","warnings","isPluralGroup","count","other","selectPluralVariant","resolvePluralRule","code","message","translate","activeCode","vars","active","localesByCode","get","chain","fallbackChain","mergedVars","interpolateWith","text","sourceLocale","interpolate","name","resources","runtimeEntry","runtimeEntries","defaultText","missingTranslation","mode"],"sourceRoot":"../../../src","sources":["translation/resolver.ts"],"mappings":"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","ignoreList":[]}