@chipmobilesdk/rn-i18n 0.3.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 (192) hide show
  1. package/CHANGELOG.md +157 -0
  2. package/README.md +28 -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/src/index.ts +5 -3
  185. package/src/tooling/cli.ts +0 -76
  186. package/src/tooling/generateKeys.ts +0 -65
  187. package/src/tooling/index.ts +0 -27
  188. package/src/tooling/report.ts +0 -109
  189. package/src/tooling/runner.ts +0 -111
  190. package/src/tooling/scan.ts +0 -193
  191. package/src/tooling/sync.ts +0 -193
  192. package/src/tooling/types.ts +0 -119
@@ -0,0 +1 @@
1
+ {"version":3,"names":["runtimeEntriesFromCatalog","catalog","options","Object","entries","map","key","text","defaultText","replace","policy","description","undefined"],"sourceRoot":"../../../src","sources":["config/catalog.ts"],"mappings":";;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,yBAAyBA,CACxCC,OAAyC,EACzCC,OAA8E,GAAG,CAAC,CAAC,EACvD;EAC5B,OAAOC,MAAM,CAACC,OAAO,CAACH,OAAO,CAAC,CAACI,GAAG,CAAC,CAAC,CAACC,GAAG,EAAEC,IAAI,CAAC,MAAM;IACpDD,GAAG;IACHE,WAAW,EAAED,IAAI,CAACE,OAAO,CAAC,yBAAyB,EAAE,QAAQ,CAAC;IAC9DC,MAAM,EAAER,OAAO,CAACQ,MAAM,IAAI,QAAQ;IAClC,IAAIR,OAAO,CAACS,WAAW,KAAKC,SAAS,GAAG,CAAC,CAAC,GAAG;MAAED,WAAW,EAAET,OAAO,CAACS;IAAY,CAAC;EAClF,CAAC,CAAC,CAAC;AACJ","ignoreList":[]}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ import { createDiagnosticChannel, redactPatterns } from '@chipmobilesdk/rn-core';
4
+
5
+ /** What rn-i18n reports. Stable: an app may branch on these. */
6
+
7
+ const SEVERITY = {
8
+ missing_translation: 'warn',
9
+ fallback_used: 'info',
10
+ missing_variable: 'warn',
11
+ invalid_value: 'warn',
12
+ invalid_format: 'warn',
13
+ locale_unsupported: 'warn',
14
+ plural_rule_default: 'warn',
15
+ locale_read_failed: 'warn',
16
+ locale_write_failed: 'warn',
17
+ listener_threw: 'error'
18
+ };
19
+ const channel = createDiagnosticChannel('rn-i18n');
20
+
21
+ /**
22
+ * One place every diagnostic goes through (I18N-11): the app's SDK sinks always
23
+ * (`installSdkSink` from rn-core), then `onDiagnostic` when the app gave one,
24
+ * otherwise `console.warn` in development builds and tests only.
25
+ */
26
+ export function createReporter(onDiagnostic) {
27
+ return diagnostic => {
28
+ channel.emit(diagnostic.code, SEVERITY[diagnostic.code], {
29
+ ...(diagnostic.key === undefined ? {} : {
30
+ key: diagnostic.key
31
+ }),
32
+ ...(diagnostic.locale === undefined ? {} : {
33
+ locale: diagnostic.locale
34
+ })
35
+ });
36
+ if (onDiagnostic) {
37
+ onDiagnostic(diagnostic);
38
+ } else if (typeof __DEV__ === 'undefined' || __DEV__) {
39
+ console.warn(`[rn-i18n] ${diagnostic.message}`);
40
+ }
41
+ };
42
+ }
43
+
44
+ /** For the few call sites that run before or outside an i18n instance. */
45
+ export const defaultReporter = createReporter();
46
+
47
+ /** Foreign error text, shaped before it reaches a message. */
48
+ export function describeError(error) {
49
+ return redactPatterns(error instanceof Error ? error.message : String(error));
50
+ }
51
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createDiagnosticChannel","redactPatterns","SEVERITY","missing_translation","fallback_used","missing_variable","invalid_value","invalid_format","locale_unsupported","plural_rule_default","locale_read_failed","locale_write_failed","listener_threw","channel","createReporter","onDiagnostic","diagnostic","emit","code","key","undefined","locale","__DEV__","console","warn","message","defaultReporter","describeError","error","Error","String"],"sourceRoot":"../../../src","sources":["config/diagnostics.ts"],"mappings":";;AAAA,SACCA,uBAAuB,EACvBC,cAAc,QAER,wBAAwB;;AAE/B;;AAuBA,MAAMC,QAAwD,GAAG;EAChEC,mBAAmB,EAAE,MAAM;EAC3BC,aAAa,EAAE,MAAM;EACrBC,gBAAgB,EAAE,MAAM;EACxBC,aAAa,EAAE,MAAM;EACrBC,cAAc,EAAE,MAAM;EACtBC,kBAAkB,EAAE,MAAM;EAC1BC,mBAAmB,EAAE,MAAM;EAC3BC,kBAAkB,EAAE,MAAM;EAC1BC,mBAAmB,EAAE,MAAM;EAC3BC,cAAc,EAAE;AACjB,CAAC;AAED,MAAMC,OAAO,GAAGb,uBAAuB,CAAqB,SAAS,CAAC;;AAEtE;AACA;AACA;AACA;AACA;AACA,OAAO,SAASc,cAAcA,CAACC,YAAoC,EAAyB;EAC3F,OAAOC,UAAU,IAAI;IACpBH,OAAO,CAACI,IAAI,CAACD,UAAU,CAACE,IAAI,EAAEhB,QAAQ,CAACc,UAAU,CAACE,IAAI,CAAC,EAAE;MACxD,IAAIF,UAAU,CAACG,GAAG,KAAKC,SAAS,GAAG,CAAC,CAAC,GAAG;QAAED,GAAG,EAAEH,UAAU,CAACG;MAAI,CAAC,CAAC;MAChE,IAAIH,UAAU,CAACK,MAAM,KAAKD,SAAS,GAAG,CAAC,CAAC,GAAG;QAAEC,MAAM,EAAEL,UAAU,CAACK;MAAO,CAAC;IACzE,CAAC,CAAC;IACF,IAAIN,YAAY,EAAE;MACjBA,YAAY,CAACC,UAAU,CAAC;IACzB,CAAC,MAAM,IAAI,OAAOM,OAAO,KAAK,WAAW,IAAIA,OAAO,EAAE;MACrDC,OAAO,CAACC,IAAI,CAAC,aAAaR,UAAU,CAACS,OAAO,EAAE,CAAC;IAChD;EACD,CAAC;AACF;;AAEA;AACA,OAAO,MAAMC,eAAe,GAAGZ,cAAc,CAAC,CAAC;;AAE/C;AACA,OAAO,SAASa,aAAaA,CAACC,KAAc,EAAU;EACrD,OAAO3B,cAAc,CAAC2B,KAAK,YAAYC,KAAK,GAAGD,KAAK,CAACH,OAAO,GAAGK,MAAM,CAACF,KAAK,CAAC,CAAC;AAC9E","ignoreList":[]}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ import { SdkError } from '@chipmobilesdk/rn-core';
4
+
5
+ /** The package's error codes. */
6
+
7
+ /**
8
+ * Configuration error listing every detected violation. An `SdkError`
9
+ * (`@chipmobilesdk/rn-core`) with `pkg: 'rn-i18n'`.
10
+ */
11
+ export class I18nConfigError extends SdkError {
12
+ constructor(issues) {
13
+ super('rn-i18n', 'invalid_config', {
14
+ message: `Invalid i18n configuration:\n- ${issues.join('\n- ')}`
15
+ });
16
+ this.name = 'I18nConfigError';
17
+ this.issues = issues;
18
+ }
19
+ }
20
+
21
+ /** A unit conversion the package cannot perform, such as across dimensions. */
22
+ export class UnitConversionError extends SdkError {
23
+ constructor(message) {
24
+ super('rn-i18n', 'unit_conversion', {
25
+ message
26
+ });
27
+ this.name = 'UnitConversionError';
28
+ }
29
+ }
30
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["SdkError","I18nConfigError","constructor","issues","message","join","name","UnitConversionError"],"sourceRoot":"../../../src","sources":["config/errors.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,wBAAwB;;AAEjD;;AAGA;AACA;AACA;AACA;AACA,OAAO,MAAMC,eAAe,SAASD,QAAQ,CAAgB;EAG5DE,WAAWA,CAACC,MAAyB,EAAE;IACtC,KAAK,CAAC,SAAS,EAAE,gBAAgB,EAAE;MAClCC,OAAO,EAAE,kCAAkCD,MAAM,CAACE,IAAI,CAAC,MAAM,CAAC;IAC/D,CAAC,CAAC;IACF,IAAI,CAACC,IAAI,GAAG,iBAAiB;IAC7B,IAAI,CAACH,MAAM,GAAGA,MAAM;EACrB;AACD;;AAEA;AACA,OAAO,MAAMI,mBAAmB,SAASP,QAAQ,CAAgB;EAChEE,WAAWA,CAACE,OAAe,EAAE;IAC5B,KAAK,CAAC,SAAS,EAAE,iBAAiB,EAAE;MAAEA;IAAQ,CAAC,CAAC;IAChD,IAAI,CAACE,IAAI,GAAG,qBAAqB;EAClC;AACD","ignoreList":[]}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Public configuration and contract types for @chipmobilesdk/rn-i18n.
5
+ *
6
+ * The package has one runtime dependency, rn-core; formatting uses the Intl APIs
7
+ * built into Hermes (Intl.NumberFormat, Intl.DateTimeFormat), while plural
8
+ * rules and unit conversion are package-owned because Intl.PluralRules and
9
+ * Intl unit-style formatting are not reliably available in Hermes.
10
+ */
11
+
12
+ /** App-owned translation resources keyed by locale code. */
13
+
14
+ /**
15
+ * A translation key intentionally resolved at runtime and therefore not
16
+ * discoverable by static source scanning. Declared entries are protected
17
+ * from removal during locale JSON synchronization.
18
+ */
19
+
20
+ /** App-injected persistence contract. The package never bundles a backend. */
21
+
22
+ /** Returns the device locale, or undefined when detection is unavailable. */
23
+
24
+ // Kept importable from here for compatibility; the errors live in config/errors.ts (I18N-14).
25
+ export { I18nConfigError } from "./errors.js";
26
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["I18nConfigError"],"sourceRoot":"../../../src","sources":["config/types.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AA4DA;;AAGA;AACA;AACA;AACA;AACA;;AAkBA;;AAaA;;AA2CA;AACA,SAASA,eAAe,QAAQ,aAAU","ignoreList":[]}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+
3
+ import { I18nConfigError } from "./types.js";
4
+
5
+ /**
6
+ * Validates an I18nConfig before any localized content is served (FR-003,
7
+ * FR-046). Collects every violation and throws a single I18nConfigError so
8
+ * apps see the complete picture instead of fixing issues one at a time.
9
+ */
10
+ export function validateConfig(config, knownUnits) {
11
+ const issues = [];
12
+ const locales = Array.isArray(config.locales) ? config.locales : [];
13
+ if (locales.length === 0) {
14
+ issues.push('At least one supported locale must be declared.');
15
+ }
16
+ const codes = new Set();
17
+ for (const locale of locales) {
18
+ if (codes.has(locale.code)) {
19
+ issues.push(`Duplicate locale code "${locale.code}".`);
20
+ }
21
+ codes.add(locale.code);
22
+ }
23
+ for (const locale of locales) {
24
+ validateLocale(locale, codes, knownUnits, issues);
25
+ }
26
+ detectFallbackCycles(locales, codes, issues);
27
+ if (locales.length > 0 && !codes.has(config.primaryLocale)) {
28
+ issues.push(`Primary locale "${config.primaryLocale}" is not a supported locale.`);
29
+ }
30
+ for (const code of codes) {
31
+ const resource = config.resources?.[code];
32
+ if (resource === undefined || resource === null) {
33
+ issues.push(`Locale "${code}" has no translation resource.`);
34
+ }
35
+ }
36
+ if (config.persistLocale !== false && !config.storage) {
37
+ issues.push('Locale persistence is enabled but no storage adapter was injected. ' + 'Provide `storage` or set `persistLocale: false`.');
38
+ }
39
+ const runtimeKeys = new Set();
40
+ for (const entry of config.runtimeEntries ?? []) {
41
+ if (!entry.key) {
42
+ issues.push('Runtime-only entries must declare a non-empty key.');
43
+ continue;
44
+ }
45
+ if (runtimeKeys.has(entry.key)) {
46
+ issues.push(`Duplicate runtime-only entry "${entry.key}".`);
47
+ }
48
+ runtimeKeys.add(entry.key);
49
+ if (typeof entry.defaultText !== 'string') {
50
+ issues.push(`Runtime-only entry "${entry.key}" must declare default text.`);
51
+ }
52
+ }
53
+ if (issues.length > 0) {
54
+ throw new I18nConfigError(issues);
55
+ }
56
+ }
57
+ function validateLocale(locale, codes, knownUnits, issues) {
58
+ const code = locale.code;
59
+ if (!code) {
60
+ issues.push('Every locale must declare a non-empty code.');
61
+ return;
62
+ }
63
+ if (!locale.displayName) {
64
+ issues.push(`Locale "${code}" must declare a display name.`);
65
+ }
66
+ if (locale.direction !== 'ltr' && locale.direction !== 'rtl') {
67
+ issues.push(`Locale "${code}" must declare direction "ltr" or "rtl".`);
68
+ }
69
+ if (!locale.defaultCurrency) {
70
+ issues.push(`Locale "${code}" must declare a default currency.`);
71
+ } else if (!/^[A-Z]{3}$/.test(locale.defaultCurrency)) {
72
+ // An ISO 4217 code; anything else would fail every currency format (I18N-08).
73
+ issues.push(`Locale "${code}" default currency "${locale.defaultCurrency}" is not a three-letter ISO 4217 code.`);
74
+ }
75
+ if (!knownUnits.has(locale.defaultUnit)) {
76
+ issues.push(`Locale "${code}" declares unknown default unit "${locale.defaultUnit}".`);
77
+ }
78
+ if (typeof locale.defaultDateFormat !== 'object' || !locale.defaultDateFormat) {
79
+ issues.push(`Locale "${code}" must declare a default date format.`);
80
+ }
81
+ if (typeof locale.defaultNumberFormat !== 'object' || !locale.defaultNumberFormat) {
82
+ issues.push(`Locale "${code}" must declare a default number format.`);
83
+ }
84
+ if (!Array.isArray(locale.fallbackChain)) {
85
+ issues.push(`Locale "${code}" must declare a fallback chain array.`);
86
+ return;
87
+ }
88
+ const seen = new Set();
89
+ for (const entry of locale.fallbackChain) {
90
+ if (entry === code) {
91
+ issues.push(`Locale "${code}" must not include itself in its fallback chain.`);
92
+ }
93
+ if (seen.has(entry)) {
94
+ issues.push(`Locale "${code}" lists duplicate fallback-chain entry "${entry}".`);
95
+ }
96
+ seen.add(entry);
97
+ if (!codes.has(entry)) {
98
+ issues.push(`Locale "${code}" references unsupported fallback locale "${entry}".`);
99
+ }
100
+ }
101
+ }
102
+ function detectFallbackCycles(locales, codes, issues) {
103
+ const chains = new Map(locales.map(locale => [locale.code, (locale.fallbackChain ?? []).filter(entry => codes.has(entry))]));
104
+ const states = new Map();
105
+ const visit = (code, path) => {
106
+ const state = states.get(code);
107
+ if (state === 'done') {
108
+ return false;
109
+ }
110
+ if (state === 'visiting') {
111
+ issues.push(`Fallback cycle detected: ${[...path, code].join(' -> ')}.`);
112
+ return true;
113
+ }
114
+ states.set(code, 'visiting');
115
+ for (const next of chains.get(code) ?? []) {
116
+ if (visit(next, [...path, code])) {
117
+ states.set(code, 'done');
118
+ return true;
119
+ }
120
+ }
121
+ states.set(code, 'done');
122
+ return false;
123
+ };
124
+ for (const locale of locales) {
125
+ if (visit(locale.code, [])) {
126
+ // Report the first cycle only; one clear cycle message is actionable.
127
+ return;
128
+ }
129
+ }
130
+ }
131
+ //# sourceMappingURL=validateConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["I18nConfigError","validateConfig","config","knownUnits","issues","locales","Array","isArray","length","push","codes","Set","locale","has","code","add","validateLocale","detectFallbackCycles","primaryLocale","resource","resources","undefined","persistLocale","storage","runtimeKeys","entry","runtimeEntries","key","defaultText","displayName","direction","defaultCurrency","test","defaultUnit","defaultDateFormat","defaultNumberFormat","fallbackChain","seen","chains","Map","map","filter","states","visit","path","state","get","join","set","next"],"sourceRoot":"../../../src","sources":["config/validateConfig.ts"],"mappings":";;AACA,SAASA,eAAe,QAAQ,YAAS;;AAEzC;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAACC,MAAkB,EAAEC,UAA+B,EAAQ;EACzF,MAAMC,MAAgB,GAAG,EAAE;EAC3B,MAAMC,OAAO,GAAGC,KAAK,CAACC,OAAO,CAACL,MAAM,CAACG,OAAO,CAAC,GAAGH,MAAM,CAACG,OAAO,GAAG,EAAE;EAEnE,IAAIA,OAAO,CAACG,MAAM,KAAK,CAAC,EAAE;IACzBJ,MAAM,CAACK,IAAI,CAAC,iDAAiD,CAAC;EAC/D;EAEA,MAAMC,KAAK,GAAG,IAAIC,GAAG,CAAS,CAAC;EAC/B,KAAK,MAAMC,MAAM,IAAIP,OAAO,EAAE;IAC7B,IAAIK,KAAK,CAACG,GAAG,CAACD,MAAM,CAACE,IAAI,CAAC,EAAE;MAC3BV,MAAM,CAACK,IAAI,CAAC,0BAA0BG,MAAM,CAACE,IAAI,IAAI,CAAC;IACvD;IACAJ,KAAK,CAACK,GAAG,CAACH,MAAM,CAACE,IAAI,CAAC;EACvB;EAEA,KAAK,MAAMF,MAAM,IAAIP,OAAO,EAAE;IAC7BW,cAAc,CAACJ,MAAM,EAAEF,KAAK,EAAEP,UAAU,EAAEC,MAAM,CAAC;EAClD;EAEAa,oBAAoB,CAACZ,OAAO,EAAEK,KAAK,EAAEN,MAAM,CAAC;EAE5C,IAAIC,OAAO,CAACG,MAAM,GAAG,CAAC,IAAI,CAACE,KAAK,CAACG,GAAG,CAACX,MAAM,CAACgB,aAAa,CAAC,EAAE;IAC3Dd,MAAM,CAACK,IAAI,CAAC,mBAAmBP,MAAM,CAACgB,aAAa,8BAA8B,CAAC;EACnF;EAEA,KAAK,MAAMJ,IAAI,IAAIJ,KAAK,EAAE;IACzB,MAAMS,QAAQ,GAAGjB,MAAM,CAACkB,SAAS,GAAGN,IAAI,CAAC;IACzC,IAAIK,QAAQ,KAAKE,SAAS,IAAIF,QAAQ,KAAK,IAAI,EAAE;MAChDf,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,gCAAgC,CAAC;IAC7D;EACD;EAEA,IAAIZ,MAAM,CAACoB,aAAa,KAAK,KAAK,IAAI,CAACpB,MAAM,CAACqB,OAAO,EAAE;IACtDnB,MAAM,CAACK,IAAI,CACV,qEAAqE,GACpE,kDACF,CAAC;EACF;EAEA,MAAMe,WAAW,GAAG,IAAIb,GAAG,CAAS,CAAC;EACrC,KAAK,MAAMc,KAAK,IAAIvB,MAAM,CAACwB,cAAc,IAAI,EAAE,EAAE;IAChD,IAAI,CAACD,KAAK,CAACE,GAAG,EAAE;MACfvB,MAAM,CAACK,IAAI,CAAC,oDAAoD,CAAC;MACjE;IACD;IACA,IAAIe,WAAW,CAACX,GAAG,CAACY,KAAK,CAACE,GAAG,CAAC,EAAE;MAC/BvB,MAAM,CAACK,IAAI,CAAC,iCAAiCgB,KAAK,CAACE,GAAG,IAAI,CAAC;IAC5D;IACAH,WAAW,CAACT,GAAG,CAACU,KAAK,CAACE,GAAG,CAAC;IAC1B,IAAI,OAAOF,KAAK,CAACG,WAAW,KAAK,QAAQ,EAAE;MAC1CxB,MAAM,CAACK,IAAI,CAAC,uBAAuBgB,KAAK,CAACE,GAAG,8BAA8B,CAAC;IAC5E;EACD;EAEA,IAAIvB,MAAM,CAACI,MAAM,GAAG,CAAC,EAAE;IACtB,MAAM,IAAIR,eAAe,CAACI,MAAM,CAAC;EAClC;AACD;AAEA,SAASY,cAAcA,CACtBJ,MAAoB,EACpBF,KAA0B,EAC1BP,UAA+B,EAC/BC,MAAgB,EACT;EACP,MAAMU,IAAI,GAAGF,MAAM,CAACE,IAAI;EACxB,IAAI,CAACA,IAAI,EAAE;IACVV,MAAM,CAACK,IAAI,CAAC,6CAA6C,CAAC;IAC1D;EACD;EACA,IAAI,CAACG,MAAM,CAACiB,WAAW,EAAE;IACxBzB,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,gCAAgC,CAAC;EAC7D;EACA,IAAIF,MAAM,CAACkB,SAAS,KAAK,KAAK,IAAIlB,MAAM,CAACkB,SAAS,KAAK,KAAK,EAAE;IAC7D1B,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,0CAA0C,CAAC;EACvE;EACA,IAAI,CAACF,MAAM,CAACmB,eAAe,EAAE;IAC5B3B,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,oCAAoC,CAAC;EACjE,CAAC,MAAM,IAAI,CAAC,YAAY,CAACkB,IAAI,CAACpB,MAAM,CAACmB,eAAe,CAAC,EAAE;IACtD;IACA3B,MAAM,CAACK,IAAI,CACV,WAAWK,IAAI,uBAAuBF,MAAM,CAACmB,eAAe,wCAC7D,CAAC;EACF;EACA,IAAI,CAAC5B,UAAU,CAACU,GAAG,CAACD,MAAM,CAACqB,WAAW,CAAC,EAAE;IACxC7B,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,oCAAoCF,MAAM,CAACqB,WAAW,IAAI,CAAC;EACvF;EACA,IAAI,OAAOrB,MAAM,CAACsB,iBAAiB,KAAK,QAAQ,IAAI,CAACtB,MAAM,CAACsB,iBAAiB,EAAE;IAC9E9B,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,uCAAuC,CAAC;EACpE;EACA,IAAI,OAAOF,MAAM,CAACuB,mBAAmB,KAAK,QAAQ,IAAI,CAACvB,MAAM,CAACuB,mBAAmB,EAAE;IAClF/B,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,yCAAyC,CAAC;EACtE;EACA,IAAI,CAACR,KAAK,CAACC,OAAO,CAACK,MAAM,CAACwB,aAAa,CAAC,EAAE;IACzChC,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,wCAAwC,CAAC;IACpE;EACD;EACA,MAAMuB,IAAI,GAAG,IAAI1B,GAAG,CAAS,CAAC;EAC9B,KAAK,MAAMc,KAAK,IAAIb,MAAM,CAACwB,aAAa,EAAE;IACzC,IAAIX,KAAK,KAAKX,IAAI,EAAE;MACnBV,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,kDAAkD,CAAC;IAC/E;IACA,IAAIuB,IAAI,CAACxB,GAAG,CAACY,KAAK,CAAC,EAAE;MACpBrB,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,2CAA2CW,KAAK,IAAI,CAAC;IACjF;IACAY,IAAI,CAACtB,GAAG,CAACU,KAAK,CAAC;IACf,IAAI,CAACf,KAAK,CAACG,GAAG,CAACY,KAAK,CAAC,EAAE;MACtBrB,MAAM,CAACK,IAAI,CAAC,WAAWK,IAAI,6CAA6CW,KAAK,IAAI,CAAC;IACnF;EACD;AACD;AAEA,SAASR,oBAAoBA,CAC5BZ,OAAgC,EAChCK,KAA0B,EAC1BN,MAAgB,EACT;EACP,MAAMkC,MAAM,GAAG,IAAIC,GAAG,CACrBlC,OAAO,CAACmC,GAAG,CAAC5B,MAAM,IAAI,CACrBA,MAAM,CAACE,IAAI,EACX,CAACF,MAAM,CAACwB,aAAa,IAAI,EAAE,EAAEK,MAAM,CAAChB,KAAK,IAAIf,KAAK,CAACG,GAAG,CAACY,KAAK,CAAC,CAAC,CAC9D,CACF,CAAC;EACD,MAAMiB,MAAM,GAAG,IAAIH,GAAG,CAA8B,CAAC;EAErD,MAAMI,KAAK,GAAGA,CAAC7B,IAAY,EAAE8B,IAAc,KAAc;IACxD,MAAMC,KAAK,GAAGH,MAAM,CAACI,GAAG,CAAChC,IAAI,CAAC;IAC9B,IAAI+B,KAAK,KAAK,MAAM,EAAE;MACrB,OAAO,KAAK;IACb;IACA,IAAIA,KAAK,KAAK,UAAU,EAAE;MACzBzC,MAAM,CAACK,IAAI,CAAC,4BAA4B,CAAC,GAAGmC,IAAI,EAAE9B,IAAI,CAAC,CAACiC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;MACxE,OAAO,IAAI;IACZ;IACAL,MAAM,CAACM,GAAG,CAAClC,IAAI,EAAE,UAAU,CAAC;IAC5B,KAAK,MAAMmC,IAAI,IAAIX,MAAM,CAACQ,GAAG,CAAChC,IAAI,CAAC,IAAI,EAAE,EAAE;MAC1C,IAAI6B,KAAK,CAACM,IAAI,EAAE,CAAC,GAAGL,IAAI,EAAE9B,IAAI,CAAC,CAAC,EAAE;QACjC4B,MAAM,CAACM,GAAG,CAAClC,IAAI,EAAE,MAAM,CAAC;QACxB,OAAO,IAAI;MACZ;IACD;IACA4B,MAAM,CAACM,GAAG,CAAClC,IAAI,EAAE,MAAM,CAAC;IACxB,OAAO,KAAK;EACb,CAAC;EAED,KAAK,MAAMF,MAAM,IAAIP,OAAO,EAAE;IAC7B,IAAIsC,KAAK,CAAC/B,MAAM,CAACE,IAAI,EAAE,EAAE,CAAC,EAAE;MAC3B;MACA;IACD;EACD;AACD","ignoreList":[]}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ import { getNumberFormat } from '@chipmobilesdk/rn-core';
4
+ import { applyInvalidFormatPolicy } from "./invalid.js";
5
+
6
+ /**
7
+ * Locale-aware currency formatting. The locale's configured default currency
8
+ * applies unless the caller passes an explicit currency override (FR-021).
9
+ *
10
+ * `locale.defaultNumberFormat` is deliberately **not** applied here: a currency
11
+ * carries its own minor units (yen has none, dinar has three), and the locale's
12
+ * generic number options would override them — ¥1,234.56 instead of ¥1,235.
13
+ * Pass the options you want for a currency explicitly (I18N-09).
14
+ */
15
+ export function formatCurrencyValue(value, localeCode, defaultCurrency, currencyOverride, options, invalidFormat) {
16
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
17
+ return applyInvalidFormatPolicy(invalidFormat, `Cannot format invalid currency value "${String(value)}" for locale "${localeCode}".`);
18
+ }
19
+ const currency = currencyOverride ?? defaultCurrency;
20
+ // rn-core's cached formatter (I18N-03). An unknown currency code (`usd1`) used
21
+ // to throw out of render; it is a format problem now (I18N-08).
22
+ try {
23
+ return getNumberFormat(localeCode, {
24
+ ...options,
25
+ style: 'currency',
26
+ currency
27
+ }).format(value);
28
+ } catch (error) {
29
+ return applyInvalidFormatPolicy(invalidFormat, `Cannot format currency "${currency}" for locale "${localeCode}": ${String(error)}`);
30
+ }
31
+ }
32
+ //# sourceMappingURL=currency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getNumberFormat","applyInvalidFormatPolicy","formatCurrencyValue","value","localeCode","defaultCurrency","currencyOverride","options","invalidFormat","Number","isFinite","String","currency","style","format","error"],"sourceRoot":"../../../src","sources":["format/currency.ts"],"mappings":";;AAAA,SAASA,eAAe,QAAQ,wBAAwB;AAExD,SAASC,wBAAwB,QAAQ,cAAW;;AAEpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,mBAAmBA,CAClCC,KAAa,EACbC,UAAkB,EAClBC,eAAuB,EACvBC,gBAAoC,EACpCC,OAA6C,EAC7CC,aAAkC,EACzB;EACT,IAAI,OAAOL,KAAK,KAAK,QAAQ,IAAI,CAACM,MAAM,CAACC,QAAQ,CAACP,KAAK,CAAC,EAAE;IACzD,OAAOF,wBAAwB,CAC9BO,aAAa,EACb,yCAAyCG,MAAM,CAACR,KAAK,CAAC,iBAAiBC,UAAU,IAClF,CAAC;EACF;EACA,MAAMQ,QAAQ,GAAGN,gBAAgB,IAAID,eAAe;EACpD;EACA;EACA,IAAI;IACH,OAAOL,eAAe,CAACI,UAAU,EAAE;MAAE,GAAGG,OAAO;MAAEM,KAAK,EAAE,UAAU;MAAED;IAAS,CAAC,CAAC,CAACE,MAAM,CAACX,KAAK,CAAC;EAC9F,CAAC,CAAC,OAAOY,KAAK,EAAE;IACf,OAAOd,wBAAwB,CAC9BO,aAAa,EACb,2BAA2BI,QAAQ,iBAAiBR,UAAU,MAAMO,MAAM,CAACI,KAAK,CAAC,EAClF,CAAC;EACF;AACD","ignoreList":[]}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ import { getDateTimeFormat } from '@chipmobilesdk/rn-core';
4
+ import { applyInvalidFormatPolicy } from "./invalid.js";
5
+
6
+ /**
7
+ * Locale-aware date formatting through the Hermes built-in
8
+ * Intl.DateTimeFormat.
9
+ *
10
+ * Options are **merged** over the locale's configured default, the way
11
+ * `formatNumber` has always worked: `{ month: 'long' }` changes the month and
12
+ * keeps the year and day. Replacing the default wholesale, which this used to
13
+ * do, meant one option silently dropped every other component — and the two
14
+ * formatters disagreed about what an option meant (I18N-09). Pass
15
+ * `{ replaceDefaults: true }` for the old behaviour.
16
+ */
17
+ export function formatDateValue(value, localeCode, defaults, override, invalidFormat, replaceDefaults = false) {
18
+ const date = value instanceof Date ? value : new Date(value);
19
+ if (Number.isNaN(date.getTime())) {
20
+ return applyInvalidFormatPolicy(invalidFormat, `Cannot format invalid date value "${String(value)}" for locale "${localeCode}".`);
21
+ }
22
+ const options = replaceDefaults ? override ?? defaults : {
23
+ ...defaults,
24
+ ...override
25
+ };
26
+ // rn-core's cached formatter (I18N-03); a bad option is a format problem (I18N-08).
27
+ try {
28
+ return getDateTimeFormat(localeCode, options).format(date);
29
+ } catch (error) {
30
+ return applyInvalidFormatPolicy(invalidFormat, `Cannot format a date: ${String(error)}`);
31
+ }
32
+ }
33
+ //# sourceMappingURL=date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getDateTimeFormat","applyInvalidFormatPolicy","formatDateValue","value","localeCode","defaults","override","invalidFormat","replaceDefaults","date","Date","Number","isNaN","getTime","String","options","format","error"],"sourceRoot":"../../../src","sources":["format/date.ts"],"mappings":";;AAAA,SAASA,iBAAiB,QAAQ,wBAAwB;AAE1D,SAASC,wBAAwB,QAAQ,cAAW;;AAEpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAeA,CAC9BC,KAAoB,EACpBC,UAAkB,EAClBC,QAAoC,EACpCC,QAAgD,EAChDC,aAAkC,EAClCC,eAAe,GAAG,KAAK,EACd;EACT,MAAMC,IAAI,GAAGN,KAAK,YAAYO,IAAI,GAAGP,KAAK,GAAG,IAAIO,IAAI,CAACP,KAAK,CAAC;EAC5D,IAAIQ,MAAM,CAACC,KAAK,CAACH,IAAI,CAACI,OAAO,CAAC,CAAC,CAAC,EAAE;IACjC,OAAOZ,wBAAwB,CAC9BM,aAAa,EACb,qCAAqCO,MAAM,CAACX,KAAK,CAAC,iBAAiBC,UAAU,IAC9E,CAAC;EACF;EACA,MAAMW,OAAO,GAAGP,eAAe,GAAIF,QAAQ,IAAID,QAAQ,GAAI;IAAE,GAAGA,QAAQ;IAAE,GAAGC;EAAS,CAAC;EACvF;EACA,IAAI;IACH,OAAON,iBAAiB,CAACI,UAAU,EAAEW,OAAO,CAAC,CAACC,MAAM,CAACP,IAAI,CAAC;EAC3D,CAAC,CAAC,OAAOQ,KAAK,EAAE;IACf,OAAOhB,wBAAwB,CAACM,aAAa,EAAE,yBAAyBO,MAAM,CAACG,KAAK,CAAC,EAAE,CAAC;EACzF;AACD","ignoreList":[]}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ import { defaultReporter } from "../config/diagnostics.js";
4
+
5
+ /** The policy as an i18n instance resolves it: with the instance's reporter. */
6
+
7
+ /**
8
+ * Applies the configured invalid-format behavior: return the placeholder, or
9
+ * throw a clear formatting error in `error` mode (FR-037, FR-045).
10
+ */
11
+ export function applyInvalidFormatPolicy(policy, message) {
12
+ (policy.report ?? defaultReporter)({
13
+ code: 'invalid_format',
14
+ message
15
+ });
16
+ if (policy.mode === 'error') {
17
+ throw new RangeError(`[rn-i18n] ${message}`);
18
+ }
19
+ return policy.text;
20
+ }
21
+ //# sourceMappingURL=invalid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["defaultReporter","applyInvalidFormatPolicy","policy","message","report","code","mode","RangeError","text"],"sourceRoot":"../../../src","sources":["format/invalid.ts"],"mappings":";;AAAA,SAASA,eAAe,QAAoC,0BAAuB;;AAGnF;;AAKA;AACA;AACA;AACA;AACA,OAAO,SAASC,wBAAwBA,CACvCC,MAAmC,EACnCC,OAAe,EACN;EACT,CAACD,MAAM,CAACE,MAAM,IAAIJ,eAAe,EAAE;IAAEK,IAAI,EAAE,gBAAgB;IAAEF;EAAQ,CAAC,CAAC;EACvE,IAAID,MAAM,CAACI,IAAI,KAAK,OAAO,EAAE;IAC5B,MAAM,IAAIC,UAAU,CAAC,aAAaJ,OAAO,EAAE,CAAC;EAC7C;EACA,OAAOD,MAAM,CAACM,IAAI;AACnB","ignoreList":[]}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ import { getNumberFormat } from '@chipmobilesdk/rn-core';
4
+ import { applyInvalidFormatPolicy } from "./invalid.js";
5
+
6
+ /**
7
+ * Locale-aware number formatting through the Hermes built-in
8
+ * Intl.NumberFormat. The locale default options apply unless the caller
9
+ * passes explicit overrides (FR-019).
10
+ */
11
+ export function formatNumberValue(value, localeCode, defaults, override, invalidFormat) {
12
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
13
+ return applyInvalidFormatPolicy(invalidFormat, `Cannot format invalid number value "${String(value)}" for locale "${localeCode}".`);
14
+ }
15
+ // rn-core's cached formatter (I18N-03); a bad option is a format problem, not a
16
+ // crash in render (I18N-08).
17
+ try {
18
+ return getNumberFormat(localeCode, {
19
+ ...defaults,
20
+ ...override
21
+ }).format(value);
22
+ } catch (error) {
23
+ return applyInvalidFormatPolicy(invalidFormat, `Cannot format a number: ${String(error)}`);
24
+ }
25
+ }
26
+ //# sourceMappingURL=number.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getNumberFormat","applyInvalidFormatPolicy","formatNumberValue","value","localeCode","defaults","override","invalidFormat","Number","isFinite","String","format","error"],"sourceRoot":"../../../src","sources":["format/number.ts"],"mappings":";;AAAA,SAASA,eAAe,QAAQ,wBAAwB;AAExD,SAASC,wBAAwB,QAAQ,cAAW;;AAEpD;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,iBAAiBA,CAChCC,KAAa,EACbC,UAAkB,EAClBC,QAAkC,EAClCC,QAA8C,EAC9CC,aAAkC,EACzB;EACT,IAAI,OAAOJ,KAAK,KAAK,QAAQ,IAAI,CAACK,MAAM,CAACC,QAAQ,CAACN,KAAK,CAAC,EAAE;IACzD,OAAOF,wBAAwB,CAC9BM,aAAa,EACb,uCAAuCG,MAAM,CAACP,KAAK,CAAC,iBAAiBC,UAAU,IAChF,CAAC;EACF;EACA;EACA;EACA,IAAI;IACH,OAAOJ,eAAe,CAACI,UAAU,EAAE;MAAE,GAAGC,QAAQ;MAAE,GAAGC;IAAS,CAAC,CAAC,CAACK,MAAM,CAACR,KAAK,CAAC;EAC/E,CAAC,CAAC,OAAOS,KAAK,EAAE;IACf,OAAOX,wBAAwB,CAACM,aAAa,EAAE,2BAA2BG,MAAM,CAACE,KAAK,CAAC,EAAE,CAAC;EAC3F;AACD","ignoreList":[]}
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+
3
+ import { applyInvalidFormatPolicy } from "./invalid.js";
4
+ import { formatNumberValue } from "./number.js";
5
+ /**
6
+ * Package-owned unit registry and conversion tables. Intl.NumberFormat unit
7
+ * style is not consistently available under Hermes, so the numeric part is
8
+ * formatted through Intl and the unit symbol is appended from this registry
9
+ * (research R4). Base units: meter, kilogram, liter, celsius.
10
+ */
11
+ const UNIT_REGISTRY = {
12
+ millimeter: {
13
+ dimension: 'length',
14
+ factor: 0.001,
15
+ symbol: 'mm'
16
+ },
17
+ centimeter: {
18
+ dimension: 'length',
19
+ factor: 0.01,
20
+ symbol: 'cm'
21
+ },
22
+ meter: {
23
+ dimension: 'length',
24
+ factor: 1,
25
+ symbol: 'm'
26
+ },
27
+ kilometer: {
28
+ dimension: 'length',
29
+ factor: 1000,
30
+ symbol: 'km'
31
+ },
32
+ inch: {
33
+ dimension: 'length',
34
+ factor: 0.0254,
35
+ symbol: 'in'
36
+ },
37
+ foot: {
38
+ dimension: 'length',
39
+ factor: 0.3048,
40
+ symbol: 'ft'
41
+ },
42
+ mile: {
43
+ dimension: 'length',
44
+ factor: 1609.344,
45
+ symbol: 'mi'
46
+ },
47
+ gram: {
48
+ dimension: 'mass',
49
+ factor: 0.001,
50
+ symbol: 'g'
51
+ },
52
+ kilogram: {
53
+ dimension: 'mass',
54
+ factor: 1,
55
+ symbol: 'kg'
56
+ },
57
+ ounce: {
58
+ dimension: 'mass',
59
+ factor: 0.028349523125,
60
+ symbol: 'oz'
61
+ },
62
+ pound: {
63
+ dimension: 'mass',
64
+ factor: 0.45359237,
65
+ symbol: 'lb'
66
+ },
67
+ milliliter: {
68
+ dimension: 'volume',
69
+ factor: 0.001,
70
+ symbol: 'ml'
71
+ },
72
+ liter: {
73
+ dimension: 'volume',
74
+ factor: 1,
75
+ symbol: 'l'
76
+ },
77
+ gallon: {
78
+ dimension: 'volume',
79
+ factor: 3.785411784,
80
+ symbol: 'gal'
81
+ },
82
+ celsius: {
83
+ dimension: 'temperature',
84
+ factor: 1,
85
+ symbol: '°C'
86
+ },
87
+ fahrenheit: {
88
+ dimension: 'temperature',
89
+ factor: 1,
90
+ symbol: '°F'
91
+ },
92
+ kelvin: {
93
+ dimension: 'temperature',
94
+ factor: 1,
95
+ symbol: 'K'
96
+ }
97
+ };
98
+ export const SUPPORTED_UNITS = Object.keys(UNIT_REGISTRY);
99
+ export const KNOWN_UNIT_IDS = new Set(SUPPORTED_UNITS);
100
+
101
+ // Kept importable from here for compatibility; the errors live in config/errors.ts.
102
+ import { UnitConversionError } from "../config/errors.js";
103
+ export { UnitConversionError };
104
+ export function getUnitSymbol(unit) {
105
+ return UNIT_REGISTRY[unit].symbol;
106
+ }
107
+ function toCelsius(value, from) {
108
+ switch (from) {
109
+ case 'fahrenheit':
110
+ return (value - 32) * 5 / 9;
111
+ case 'kelvin':
112
+ return value - 273.15;
113
+ default:
114
+ return value;
115
+ }
116
+ }
117
+ function fromCelsius(value, to) {
118
+ switch (to) {
119
+ case 'fahrenheit':
120
+ return value * 9 / 5 + 32;
121
+ case 'kelvin':
122
+ return value + 273.15;
123
+ default:
124
+ return value;
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Converts between compatible supported units. Unknown units or conversions
130
+ * across dimensions throw a UnitConversionError (FR-044/FR-045).
131
+ */
132
+ export function convertUnitValue(value, from, to) {
133
+ const fromDef = UNIT_REGISTRY[from];
134
+ const toDef = UNIT_REGISTRY[to];
135
+ if (!fromDef || !toDef) {
136
+ throw new UnitConversionError(`Unknown unit in conversion "${from}" -> "${to}".`);
137
+ }
138
+ if (fromDef.dimension !== toDef.dimension) {
139
+ throw new UnitConversionError(`Cannot convert between incompatible dimensions "${fromDef.dimension}" (${from}) and "${toDef.dimension}" (${to}).`);
140
+ }
141
+ if (!Number.isFinite(value)) {
142
+ throw new UnitConversionError(`Cannot convert invalid value "${String(value)}" from "${from}" to "${to}".`);
143
+ }
144
+ if (from === to) {
145
+ return value;
146
+ }
147
+ if (fromDef.dimension === 'temperature') {
148
+ return fromCelsius(toCelsius(value, from), to);
149
+ }
150
+ return value * fromDef.factor / toDef.factor;
151
+ }
152
+ /**
153
+ * Converts (when requested) and formats a measurement value: locale-aware
154
+ * numeric part via Intl.NumberFormat plus the package-owned unit symbol.
155
+ */
156
+ export function formatUnitValue(value, localeCode, localeDefaultUnit, numberDefaults, options, invalidFormat) {
157
+ const {
158
+ from = localeDefaultUnit,
159
+ to = from,
160
+ ...numberOptions
161
+ } = options ?? {};
162
+ let converted;
163
+ try {
164
+ converted = convertUnitValue(value, from, to);
165
+ } catch (error) {
166
+ return applyInvalidFormatPolicy(invalidFormat, error instanceof Error ? error.message : String(error));
167
+ }
168
+ const formatted = formatNumberValue(converted, localeCode, numberDefaults, numberOptions, invalidFormat);
169
+ return `${formatted} ${getUnitSymbol(to)}`;
170
+ }
171
+ //# sourceMappingURL=units.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["applyInvalidFormatPolicy","formatNumberValue","UNIT_REGISTRY","millimeter","dimension","factor","symbol","centimeter","meter","kilometer","inch","foot","mile","gram","kilogram","ounce","pound","milliliter","liter","gallon","celsius","fahrenheit","kelvin","SUPPORTED_UNITS","Object","keys","KNOWN_UNIT_IDS","Set","UnitConversionError","getUnitSymbol","unit","toCelsius","value","from","fromCelsius","to","convertUnitValue","fromDef","toDef","Number","isFinite","String","formatUnitValue","localeCode","localeDefaultUnit","numberDefaults","options","invalidFormat","numberOptions","converted","error","Error","message","formatted"],"sourceRoot":"../../../src","sources":["format/units.ts"],"mappings":"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","ignoreList":[]}