@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,230 @@
1
+ "use strict";
2
+
3
+ import { createReporter } from "./config/diagnostics.js";
4
+ import { validateConfig } from "./config/validateConfig.js";
5
+ import { createActiveLocaleStore } from "./locale/activeLocale.js";
6
+ import { defaultDeviceLocaleProvider, matchSupportedLocale } from "./locale/deviceLocale.js";
7
+ import { clearPersistedLocale, readPersistedLocale, readPersistedLocaleSync, writePersistedLocale } from "./locale/persistence.js";
8
+ import { hasPluralRule } from "./translation/plurals.js";
9
+ import { translate } from "./translation/resolver.js";
10
+ import { createRuntimeRegistry, registerRuntimeEntries } from "./translation/runtimeKeys.js";
11
+ import { formatCurrencyValue } from "./format/currency.js";
12
+ import { formatDateValue } from "./format/date.js";
13
+ import { formatNumberValue } from "./format/number.js";
14
+ import { KNOWN_UNIT_IDS, convertUnitValue, formatUnitValue } from "./format/units.js";
15
+ const DEFAULT_MISSING = {
16
+ mode: 'key'
17
+ };
18
+ const DEFAULT_INVALID = {
19
+ mode: 'placeholder',
20
+ text: '—'
21
+ };
22
+
23
+ /**
24
+ * Creates an I18n instance from an app-owned configuration. Validation runs
25
+ * eagerly and throws an I18nConfigError before any localized content can be
26
+ * served (FR-003). Pass the app's generated key type for typed lookups:
27
+ * `createI18n<AppI18nKey>(config)`.
28
+ */
29
+ export function createI18n(config) {
30
+ validateConfig(config, KNOWN_UNIT_IDS);
31
+ const locales = [...config.locales];
32
+ const localesByCode = new Map(locales.map(locale => [locale.code, locale]));
33
+ const missingTranslation = config.missingTranslation ?? DEFAULT_MISSING;
34
+ const report = createReporter(config.onDiagnostic);
35
+ const invalidFormat = {
36
+ ...(config.invalidFormat ?? DEFAULT_INVALID),
37
+ report
38
+ };
39
+ const persistenceEnabled = config.persistLocale !== false && !!config.storage;
40
+ const runtimeEntries = createRuntimeRegistry(config.runtimeEntries);
41
+ const store = createActiveLocaleStore({
42
+ code: config.primaryLocale,
43
+ source: 'primaryFallback',
44
+ recovered: false
45
+ }, report);
46
+
47
+ // A language this package has no plural rule for falls back to
48
+ // `count === 1 ? one : other`, which is wrong for most of the world. Said
49
+ // once per locale, at creation, rather than never (I18N-12).
50
+ for (const locale of locales) {
51
+ if (!hasPluralRule(locale)) {
52
+ report({
53
+ code: 'plural_rule_default',
54
+ locale: locale.code,
55
+ message: `No plural rule for "${locale.code}"; falling back to "count === 1 selects one". ` + 'Declare `pluralRule` on the locale if that is not how the language works.'
56
+ });
57
+ }
58
+ }
59
+ const resolverContext = {
60
+ localesByCode,
61
+ resources: config.resources,
62
+ runtimeEntries,
63
+ missingTranslation,
64
+ warned: new Set(),
65
+ report
66
+ };
67
+ const activeLocale = () => {
68
+ const locale = localesByCode.get(store.get().code);
69
+ if (!locale) {
70
+ // Unreachable after validation; guards against external mutation.
71
+ throw new Error(`[rn-i18n] Active locale "${store.get().code}" is not configured.`);
72
+ }
73
+ return locale;
74
+ };
75
+
76
+ /** persisted → device → primary fallback; shared by `init` and `initSync`. */
77
+ const resolveInitialLocale = persisted => {
78
+ if (persisted) {
79
+ if (localesByCode.has(persisted)) {
80
+ store.set({
81
+ code: persisted,
82
+ source: 'persisted',
83
+ recovered: false
84
+ });
85
+ return;
86
+ }
87
+ report({
88
+ code: 'locale_unsupported',
89
+ locale: persisted,
90
+ message: `Persisted locale "${persisted}" is no longer supported; recovering to "${config.primaryLocale}".`
91
+ });
92
+ store.set({
93
+ code: config.primaryLocale,
94
+ source: 'primaryFallback',
95
+ recovered: true
96
+ });
97
+ return;
98
+ }
99
+ const provider = config.deviceLocale ?? defaultDeviceLocaleProvider;
100
+ const match = matchSupportedLocale(provider(), locales);
101
+ store.set(match ? {
102
+ code: match.code,
103
+ source: match.source,
104
+ recovered: false
105
+ } : {
106
+ code: config.primaryLocale,
107
+ source: 'primaryFallback',
108
+ recovered: false
109
+ });
110
+ };
111
+
112
+ /**
113
+ * `init()` runs once, and loses to the user.
114
+ *
115
+ * It used to be re-run by every caller (StrictMode mounts an effect twice),
116
+ * and the persisted value it had awaited was written in unconditionally — so
117
+ * a locale the user picked, or a deep link set, while the read was in flight
118
+ * was overwritten by the old one (I18N-07).
119
+ */
120
+ let initialized;
121
+ let switched = false;
122
+ const runInit = async () => {
123
+ const persisted = persistenceEnabled && config.storage ? await readPersistedLocale(config.storage, report) : null;
124
+ if (switched) {
125
+ // The user chose while the read was in flight; their choice stands.
126
+ return;
127
+ }
128
+ resolveInitialLocale(persisted);
129
+ };
130
+ return {
131
+ init() {
132
+ initialized ??= runInit();
133
+ return initialized;
134
+ },
135
+ initSync() {
136
+ if (!persistenceEnabled || !config.storage) {
137
+ resolveInitialLocale(null);
138
+ return true;
139
+ }
140
+ const {
141
+ storage
142
+ } = config;
143
+ if (typeof storage.getItemSync !== 'function') {
144
+ return false;
145
+ }
146
+ resolveInitialLocale(readPersistedLocaleSync(storage, report));
147
+ return true;
148
+ },
149
+ t(key, vars, options) {
150
+ return translate(resolverContext, store.get().code, key, vars, options);
151
+ },
152
+ getLocale() {
153
+ return store.get();
154
+ },
155
+ async setLocale(code) {
156
+ if (!localesByCode.has(code)) {
157
+ throw new Error(`[rn-i18n] Cannot switch to unsupported locale "${code}".`);
158
+ }
159
+ switched = true;
160
+ const current = store.get();
161
+ if (current.code === code && current.source === 'runtimeSwitch') {
162
+ // Already this locale, by this route: re-rendering the whole tree and
163
+ // rewriting storage would change nothing (I18N-07).
164
+ return;
165
+ }
166
+ store.set({
167
+ code,
168
+ source: 'runtimeSwitch',
169
+ recovered: false
170
+ });
171
+ if (persistenceEnabled && config.storage) {
172
+ await writePersistedLocale(config.storage, code, report);
173
+ }
174
+ },
175
+ async useDeviceLocale() {
176
+ switched = true;
177
+ if (persistenceEnabled && config.storage) {
178
+ await clearPersistedLocale(config.storage, report);
179
+ }
180
+ const provider = config.deviceLocale ?? defaultDeviceLocaleProvider;
181
+ const match = matchSupportedLocale(provider(), locales);
182
+ store.set(match ? {
183
+ code: match.code,
184
+ source: match.source,
185
+ recovered: false
186
+ } : {
187
+ code: config.primaryLocale,
188
+ source: 'primaryFallback',
189
+ recovered: false
190
+ });
191
+ return store.get();
192
+ },
193
+ getSupportedLocales() {
194
+ return locales;
195
+ },
196
+ formatNumber(value, options) {
197
+ const locale = activeLocale();
198
+ return formatNumberValue(value, locale.code, locale.defaultNumberFormat, options, invalidFormat);
199
+ },
200
+ formatDate(value, options, formatting) {
201
+ const locale = activeLocale();
202
+ return formatDateValue(value, locale.code, locale.defaultDateFormat, options, invalidFormat, formatting?.replaceDefaults === true);
203
+ },
204
+ formatCurrency(value, currency, options) {
205
+ const locale = activeLocale();
206
+ return formatCurrencyValue(value, locale.code, locale.defaultCurrency, currency, options, invalidFormat);
207
+ },
208
+ formatUnit(value, options) {
209
+ const locale = activeLocale();
210
+ return formatUnitValue(value, locale.code, locale.defaultUnit, locale.defaultNumberFormat, options, invalidFormat);
211
+ },
212
+ convertUnit(value, from, to) {
213
+ return convertUnitValue(value, from, to);
214
+ },
215
+ registerRuntimeEntries(entries) {
216
+ registerRuntimeEntries(runtimeEntries, entries);
217
+ // What `t()` answers has changed, so every subscriber has to read again:
218
+ // a feature that registered its entries after mounting used to leave the
219
+ // screen showing the key (I18N-06).
220
+ store.bump();
221
+ },
222
+ subscribe(listener) {
223
+ return store.subscribe(listener);
224
+ },
225
+ getVersion() {
226
+ return store.getVersion();
227
+ }
228
+ };
229
+ }
230
+ //# sourceMappingURL=i18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createReporter","validateConfig","createActiveLocaleStore","defaultDeviceLocaleProvider","matchSupportedLocale","clearPersistedLocale","readPersistedLocale","readPersistedLocaleSync","writePersistedLocale","hasPluralRule","translate","createRuntimeRegistry","registerRuntimeEntries","formatCurrencyValue","formatDateValue","formatNumberValue","KNOWN_UNIT_IDS","convertUnitValue","formatUnitValue","DEFAULT_MISSING","mode","DEFAULT_INVALID","text","createI18n","config","locales","localesByCode","Map","map","locale","code","missingTranslation","report","onDiagnostic","invalidFormat","persistenceEnabled","persistLocale","storage","runtimeEntries","store","primaryLocale","source","recovered","message","resolverContext","resources","warned","Set","activeLocale","get","Error","resolveInitialLocale","persisted","has","set","provider","deviceLocale","match","initialized","switched","runInit","init","initSync","getItemSync","t","key","vars","options","getLocale","setLocale","current","useDeviceLocale","getSupportedLocales","formatNumber","value","defaultNumberFormat","formatDate","formatting","defaultDateFormat","replaceDefaults","formatCurrency","currency","defaultCurrency","formatUnit","defaultUnit","convertUnit","from","to","entries","bump","subscribe","listener","getVersion"],"sourceRoot":"../../src","sources":["i18n.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * @chipmobilesdk/rn-i18n — reusable localization for ChipMobileSdk-family
5
+ * React Native apps.
6
+ *
7
+ * This is the single entrypoint, and the package is React Native code only. The
8
+ * Node-only extraction and synchronization tooling is a package of its own,
9
+ * `@chipmobilesdk/rn-i18n-tooling` (the `chip-i18n` CLI): it used to ship inside
10
+ * this tarball as TypeScript source under `./tooling`, which no consumer could
11
+ * execute.
12
+ */
13
+
14
+ export { createI18n } from "./i18n.js";
15
+ export { I18nConfigError } from "./config/types.js";
16
+ export { runtimeEntriesFromCatalog } from "./config/catalog.js";
17
+ export { localeStorageFromKeyValue } from "./locale/keyValueStorage.js";
18
+ export { LOCALE_STORAGE_KEY } from "./locale/persistence.js";
19
+ export { defaultDeviceLocaleProvider } from "./locale/deviceLocale.js";
20
+ export { SUPPORTED_UNITS, UnitConversionError, convertUnitValue as convertUnit, getUnitSymbol } from "./format/units.js";
21
+ export { I18nProvider } from "./react/I18nProvider.js";
22
+ export { useLocale, useTranslation } from "./react/hooks.js";
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createI18n","I18nConfigError","runtimeEntriesFromCatalog","localeStorageFromKeyValue","LOCALE_STORAGE_KEY","defaultDeviceLocaleProvider","SUPPORTED_UNITS","UnitConversionError","convertUnitValue","convertUnit","getUnitSymbol","I18nProvider","useLocale","useTranslation"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,UAAU,QAAQ,WAAQ;AAGnC,SAASC,eAAe,QAAQ,mBAAgB;AAChD,SAASC,yBAAyB,QAAQ,qBAAkB;AAC5D,SAASC,yBAAyB,QAAQ,6BAA0B;AA6BpE,SAASC,kBAAkB,QAAQ,yBAAsB;AACzD,SAASC,2BAA2B,QAAQ,0BAAuB;AAEnE,SACCC,eAAe,EACfC,mBAAmB,EACnBC,gBAAgB,IAAIC,WAAW,EAC/BC,aAAa,QACP,mBAAgB;AAGvB,SAASC,YAAY,QAAQ,yBAAsB;AAEnD,SAASC,SAAS,EAAEC,cAAc,QAAQ,kBAAe","ignoreList":[]}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ import { createListenerSet } from '@chipmobilesdk/rn-core';
4
+ import { defaultReporter, describeError } from "../config/diagnostics.js";
5
+ export function createActiveLocaleStore(initial, report = defaultReporter) {
6
+ let preference = initial;
7
+ let version = 0;
8
+ const listeners = createListenerSet({
9
+ onListenerError: error => report({
10
+ code: 'listener_threw',
11
+ message: `A locale listener threw; the locale change still applied: ${describeError(error)}`
12
+ })
13
+ });
14
+ return {
15
+ get: () => preference,
16
+ set(next) {
17
+ preference = next;
18
+ version += 1;
19
+ // Isolated (CORE-03). One that threw used to skip every listener after
20
+ // it — useSyncExternalStore subscribers included — and made setLocale
21
+ // reject after the switch but before the choice was persisted, so the
22
+ // app showed one locale and stored another.
23
+ listeners.notify();
24
+ },
25
+ bump() {
26
+ version += 1;
27
+ listeners.notify();
28
+ },
29
+ subscribe: listener => listeners.add(listener),
30
+ getVersion: () => version
31
+ };
32
+ }
33
+ //# sourceMappingURL=activeLocale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createListenerSet","defaultReporter","describeError","createActiveLocaleStore","initial","report","preference","version","listeners","onListenerError","error","code","message","get","set","next","notify","bump","subscribe","listener","add","getVersion"],"sourceRoot":"../../../src","sources":["locale/activeLocale.ts"],"mappings":";;AAAA,SAASA,iBAAiB,QAAQ,wBAAwB;AAE1D,SAASC,eAAe,EAAEC,aAAa,QAAoC,0BAAuB;AAiBlG,OAAO,SAASC,uBAAuBA,CACtCC,OAA+B,EAC/BC,MAA6B,GAAGJ,eAAe,EAC3B;EACpB,IAAIK,UAAU,GAAGF,OAAO;EACxB,IAAIG,OAAO,GAAG,CAAC;EACf,MAAMC,SAAS,GAAGR,iBAAiB,CAAK;IACvCS,eAAe,EAAEC,KAAK,IACrBL,MAAM,CAAC;MACNM,IAAI,EAAE,gBAAgB;MACtBC,OAAO,EAAE,6DAA6DV,aAAa,CAACQ,KAAK,CAAC;IAC3F,CAAC;EACH,CAAC,CAAC;EAEF,OAAO;IACNG,GAAG,EAAEA,CAAA,KAAMP,UAAU;IACrBQ,GAAGA,CAACC,IAAI,EAAE;MACTT,UAAU,GAAGS,IAAI;MACjBR,OAAO,IAAI,CAAC;MACZ;MACA;MACA;MACA;MACAC,SAAS,CAACQ,MAAM,CAAC,CAAC;IACnB,CAAC;IACDC,IAAIA,CAAA,EAAG;MACNV,OAAO,IAAI,CAAC;MACZC,SAAS,CAACQ,MAAM,CAAC,CAAC;IACnB,CAAC;IACDE,SAAS,EAAEC,QAAQ,IAAIX,SAAS,CAACY,GAAG,CAACD,QAAQ,CAAC;IAC9CE,UAAU,EAAEA,CAAA,KAAMd;EACnB,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Default device locale detection. Hermes resolves the Intl default locale
5
+ * from the device locale on both Android and iOS, so no native module is
6
+ * required. Apps may inject their own provider (e.g. react-native-localize)
7
+ * through `I18nConfig.deviceLocale`.
8
+ */
9
+ export const defaultDeviceLocaleProvider = () => {
10
+ try {
11
+ return Intl.DateTimeFormat().resolvedOptions().locale;
12
+ } catch {
13
+ return undefined;
14
+ }
15
+ };
16
+ /**
17
+ * Matches a detected device locale against the supported locales: an exact
18
+ * (case-insensitive) match wins; otherwise a device language that matches
19
+ * exactly one supported locale selects that locale (US4 scenario 3).
20
+ */
21
+ export function matchSupportedLocale(deviceLocale, locales) {
22
+ if (!deviceLocale) {
23
+ return undefined;
24
+ }
25
+ const normalized = deviceLocale.toLowerCase();
26
+ const exact = locales.find(locale => locale.code.toLowerCase() === normalized);
27
+ if (exact) {
28
+ return {
29
+ code: exact.code,
30
+ source: 'device'
31
+ };
32
+ }
33
+ const language = normalized.split('-')[0];
34
+ if (!language) {
35
+ return undefined;
36
+ }
37
+ const languageMatches = locales.filter(locale => locale.code.toLowerCase().split('-')[0] === language);
38
+ if (languageMatches.length === 1) {
39
+ return {
40
+ code: languageMatches[0].code,
41
+ source: 'languageMatch'
42
+ };
43
+ }
44
+ return undefined;
45
+ }
46
+ //# sourceMappingURL=deviceLocale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["defaultDeviceLocaleProvider","Intl","DateTimeFormat","resolvedOptions","locale","undefined","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;AACA,OAAO,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;AAOD;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CACnCC,YAAgC,EAChCC,OAAgC,EACA;EAChC,IAAI,CAACD,YAAY,EAAE;IAClB,OAAOF,SAAS;EACjB;EACA,MAAMI,UAAU,GAAGF,YAAY,CAACG,WAAW,CAAC,CAAC;EAC7C,MAAMC,KAAK,GAAGH,OAAO,CAACI,IAAI,CAACR,MAAM,IAAIA,MAAM,CAACS,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,OAAOV,SAAS;EACjB;EACA,MAAMY,eAAe,GAAGT,OAAO,CAACU,MAAM,CACrCd,MAAM,IAAIA,MAAM,CAACS,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,OAAOT,SAAS;AACjB","ignoreList":[]}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * A `LocaleStorageAdapter` over rn-core's synchronous `KeyValuePort` (PERF-08).
5
+ *
6
+ * The adapter carries `getItemSync`, so `i18n.initSync()` resolves the persisted
7
+ * locale before the first render. Open the port the way the app opens its other
8
+ * durable state, for example `openDurable(() => createMMKV({ id: 'app' }))`.
9
+ */
10
+
11
+ export function localeStorageFromKeyValue(port) {
12
+ return {
13
+ getItemSync: key => port.getString(key) ?? null,
14
+ async getItem(key) {
15
+ return port.getString(key) ?? null;
16
+ },
17
+ async setItem(key, value) {
18
+ port.set(key, value);
19
+ },
20
+ async removeItem(key) {
21
+ port.remove(key);
22
+ }
23
+ };
24
+ }
25
+ //# 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;;AAKA,OAAO,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,66 @@
1
+ "use strict";
2
+
3
+ import { defaultReporter, describeError } from "../config/diagnostics.js";
4
+ export const LOCALE_STORAGE_KEY = '@chipmobilesdk/rn-i18n:locale';
5
+
6
+ /**
7
+ * Reads the persisted locale preference. Adapter failures are reported and
8
+ * treated as "no persisted value" so locale selection never crashes (FR-015).
9
+ */
10
+ export async function readPersistedLocale(storage, report = defaultReporter) {
11
+ try {
12
+ return await storage.getItem(LOCALE_STORAGE_KEY);
13
+ } catch (error) {
14
+ report({
15
+ code: 'locale_read_failed',
16
+ message: `Failed to read the persisted locale preference: ${describeError(error)}`
17
+ });
18
+ return null;
19
+ }
20
+ }
21
+
22
+ /** `readPersistedLocale` for a store with a synchronous read; same failure handling. */
23
+ export function readPersistedLocaleSync(storage, report = defaultReporter) {
24
+ try {
25
+ return storage.getItemSync(LOCALE_STORAGE_KEY);
26
+ } catch (error) {
27
+ report({
28
+ code: 'locale_read_failed',
29
+ message: `Failed to read the persisted locale preference: ${describeError(error)}`
30
+ });
31
+ return null;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Persists the selected locale. Persistence is best-effort: a write failure
37
+ * is reported but the in-memory locale switch stays authoritative.
38
+ */
39
+ export async function writePersistedLocale(storage, code, report = defaultReporter) {
40
+ try {
41
+ await storage.setItem(LOCALE_STORAGE_KEY, code);
42
+ } catch (error) {
43
+ report({
44
+ code: 'locale_write_failed',
45
+ locale: code,
46
+ message: `Failed to persist locale "${code}": ${describeError(error)}`
47
+ });
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Forgets the stored choice, so the next launch follows the device again. The
53
+ * adapter's `removeItem` was required by the contract and called by nothing
54
+ * until `useDeviceLocale()` (I18N-17). Best-effort, like the write.
55
+ */
56
+ export async function clearPersistedLocale(storage, report = defaultReporter) {
57
+ try {
58
+ await storage.removeItem(LOCALE_STORAGE_KEY);
59
+ } catch (error) {
60
+ report({
61
+ code: 'locale_write_failed',
62
+ message: `Failed to forget the persisted locale preference: ${describeError(error)}`
63
+ });
64
+ }
65
+ }
66
+ //# sourceMappingURL=persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["defaultReporter","describeError","LOCALE_STORAGE_KEY","readPersistedLocale","storage","report","getItem","error","code","message","readPersistedLocaleSync","getItemSync","writePersistedLocale","setItem","locale","clearPersistedLocale","removeItem"],"sourceRoot":"../../../src","sources":["locale/persistence.ts"],"mappings":";;AAAA,SAASA,eAAe,EAAEC,aAAa,QAAoC,0BAAuB;AAGlG,OAAO,MAAMC,kBAAkB,GAAG,+BAA+B;;AAEjE;AACA;AACA;AACA;AACA,OAAO,eAAeC,mBAAmBA,CACxCC,OAA6B,EAC7BC,MAA6B,GAAGL,eAAe,EACtB;EACzB,IAAI;IACH,OAAO,MAAMI,OAAO,CAACE,OAAO,CAACJ,kBAAkB,CAAC;EACjD,CAAC,CAAC,OAAOK,KAAK,EAAE;IACfF,MAAM,CAAC;MACNG,IAAI,EAAE,oBAAoB;MAC1BC,OAAO,EAAE,mDAAmDR,aAAa,CAACM,KAAK,CAAC;IACjF,CAAC,CAAC;IACF,OAAO,IAAI;EACZ;AACD;;AAEA;AACA,OAAO,SAASG,uBAAuBA,CACtCN,OAA2E,EAC3EC,MAA6B,GAAGL,eAAe,EAC/B;EAChB,IAAI;IACH,OAAOI,OAAO,CAACO,WAAW,CAACT,kBAAkB,CAAC;EAC/C,CAAC,CAAC,OAAOK,KAAK,EAAE;IACfF,MAAM,CAAC;MACNG,IAAI,EAAE,oBAAoB;MAC1BC,OAAO,EAAE,mDAAmDR,aAAa,CAACM,KAAK,CAAC;IACjF,CAAC,CAAC;IACF,OAAO,IAAI;EACZ;AACD;;AAEA;AACA;AACA;AACA;AACA,OAAO,eAAeK,oBAAoBA,CACzCR,OAA6B,EAC7BI,IAAY,EACZH,MAA6B,GAAGL,eAAe,EAC/B;EAChB,IAAI;IACH,MAAMI,OAAO,CAACS,OAAO,CAACX,kBAAkB,EAAEM,IAAI,CAAC;EAChD,CAAC,CAAC,OAAOD,KAAK,EAAE;IACfF,MAAM,CAAC;MACNG,IAAI,EAAE,qBAAqB;MAC3BM,MAAM,EAAEN,IAAI;MACZC,OAAO,EAAE,6BAA6BD,IAAI,MAAMP,aAAa,CAACM,KAAK,CAAC;IACrE,CAAC,CAAC;EACH;AACD;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeQ,oBAAoBA,CACzCX,OAA6B,EAC7BC,MAA6B,GAAGL,eAAe,EAC/B;EAChB,IAAI;IACH,MAAMI,OAAO,CAACY,UAAU,CAACd,kBAAkB,CAAC;EAC7C,CAAC,CAAC,OAAOK,KAAK,EAAE;IACfF,MAAM,CAAC;MACNG,IAAI,EAAE,qBAAqB;MAC3BC,OAAO,EAAE,qDAAqDR,aAAa,CAACM,KAAK,CAAC;IACnF,CAAC,CAAC;EACH;AACD","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ import React, { createContext, useContext } from 'react';
4
+ import { jsx as _jsx } from "react/jsx-runtime";
5
+ // The context intentionally erases the app-specific key type; the typed
6
+ // surface is restored by the hooks' generic parameters.
7
+ export const I18nContext = /*#__PURE__*/createContext(null);
8
+ /**
9
+ * Provides the I18n instance to the React tree. Locale changes re-render
10
+ * consumers through the hooks' useSyncExternalStore subscription, so a
11
+ * runtime switch updates UI within one interaction cycle (PERF-002).
12
+ */
13
+ export function I18nProvider({
14
+ i18n,
15
+ children
16
+ }) {
17
+ return /*#__PURE__*/_jsx(I18nContext.Provider, {
18
+ value: i18n,
19
+ children: children
20
+ });
21
+ }
22
+ export function useI18nContext() {
23
+ const i18n = useContext(I18nContext);
24
+ if (!i18n) {
25
+ throw new Error('[rn-i18n] No I18n instance found. Wrap your app in <I18nProvider>.');
26
+ }
27
+ return i18n;
28
+ }
29
+ //# sourceMappingURL=I18nProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","createContext","useContext","jsx","_jsx","I18nContext","I18nProvider","i18n","children","Provider","value","useI18nContext","Error"],"sourceRoot":"../../../src","sources":["react/I18nProvider.tsx"],"mappings":";;AAAA,OAAOA,KAAK,IAAIC,aAAa,EAAEC,UAAU,QAAQ,OAAO;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAIzD;AACA;AACA,OAAO,MAAMC,WAAW,gBAAGJ,aAAa,CAAsB,IAAI,CAAC;AAOnE;AACA;AACA;AACA;AACA;AACA,OAAO,SAASK,YAAYA,CAAC;EAAEC,IAAI;EAAEC;AAA4B,CAAC,EAAE;EACnE,oBACCJ,IAAA,CAACC,WAAW,CAACI,QAAQ;IAACC,KAAK,EAAEH,IAAgC;IAAAC,QAAA,EAAEA;EAAQ,CAAuB,CAAC;AAEjG;AAEA,OAAO,SAASG,cAAcA,CAAA,EAAiB;EAC9C,MAAMJ,IAAI,GAAGL,UAAU,CAACG,WAAW,CAAC;EACpC,IAAI,CAACE,IAAI,EAAE;IACV,MAAM,IAAIK,KAAK,CAAC,oEAAoE,CAAC;EACtF;EACA,OAAOL,IAAI;AACZ","ignoreList":[]}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ import { useCallback, useMemo, useSyncExternalStore } from 'react';
4
+ import { useI18nContext } from "./I18nProvider.js";
5
+ function useLocaleVersion(i18n) {
6
+ return useSyncExternalStore(i18n.subscribe, i18n.getVersion, i18n.getVersion);
7
+ }
8
+ /**
9
+ * Returns the translation function bound to the active locale. Pass the
10
+ * app's generated key type for compile-time key validation (FR-041):
11
+ * `const { t } = useTranslation<AppI18nKey>();`
12
+ */
13
+ export function useTranslation() {
14
+ const i18n = useI18nContext();
15
+ const version = useLocaleVersion(i18n);
16
+ // One `t` and one result per locale version (I18N-05): a memoized child that
17
+ // takes `t` re-renders when the locale changes, not on every parent render.
18
+ return useMemo(() => ({
19
+ t: (key, vars, options) => i18n.t(key, vars, options),
20
+ locale: i18n.getLocale().code
21
+ }),
22
+ // `version` is the dependency that matters: it changes with the locale.
23
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- `version` is read to invalidate, not used
24
+ [i18n, version]);
25
+ }
26
+ /** Returns active locale state, direction metadata, and the locale switcher. */
27
+ export function useLocale() {
28
+ const i18n = useI18nContext();
29
+ useLocaleVersion(i18n);
30
+ const setLocale = useCallback(code => i18n.setLocale(code), [i18n]);
31
+ const preference = i18n.getLocale();
32
+ const supportedLocales = i18n.getSupportedLocales();
33
+ const active = supportedLocales.find(locale => locale.code === preference.code);
34
+ return {
35
+ locale: preference.code,
36
+ direction: active?.direction ?? 'ltr',
37
+ preference,
38
+ supportedLocales,
39
+ setLocale
40
+ };
41
+ }
42
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useCallback","useMemo","useSyncExternalStore","useI18nContext","useLocaleVersion","i18n","subscribe","getVersion","useTranslation","version","t","key","vars","options","locale","getLocale","code","useLocale","setLocale","preference","supportedLocales","getSupportedLocales","active","find","direction"],"sourceRoot":"../../../src","sources":["react/hooks.ts"],"mappings":";;AAAA,SAASA,WAAW,EAAEC,OAAO,EAAEC,oBAAoB,QAAQ,OAAO;AASlE,SAASC,cAAc,QAAQ,mBAAgB;AAE/C,SAASC,gBAAgBA,CAACC,IAAkB,EAAU;EACrD,OAAOH,oBAAoB,CAACG,IAAI,CAACC,SAAS,EAAED,IAAI,CAACE,UAAU,EAAEF,IAAI,CAACE,UAAU,CAAC;AAC9E;AAOA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAAA,EAA6D;EAC1F,MAAMH,IAAI,GAAGF,cAAc,CAAC,CAAC;EAC7B,MAAMM,OAAO,GAAGL,gBAAgB,CAACC,IAAI,CAAC;EACtC;EACA;EACA,OAAOJ,OAAO,CACb,OAAO;IACNS,CAAC,EAAEA,CAACC,GAAS,EAAEC,IAAoB,EAAEC,OAA0B,KAC9DR,IAAI,CAACK,CAAC,CAACC,GAAG,EAAEC,IAAI,EAAEC,OAAO,CAAC;IAC3BC,MAAM,EAAET,IAAI,CAACU,SAAS,CAAC,CAAC,CAACC;EAC1B,CAAC,CAAC;EACF;EACA;EACA,CAACX,IAAI,EAAEI,OAAO,CACf,CAAC;AACF;AAUA;AACA,OAAO,SAASQ,SAASA,CAAA,EAAoB;EAC5C,MAAMZ,IAAI,GAAGF,cAAc,CAAC,CAAC;EAC7BC,gBAAgB,CAACC,IAAI,CAAC;EACtB,MAAMa,SAAS,GAAGlB,WAAW,CAAEgB,IAAY,IAAKX,IAAI,CAACa,SAAS,CAACF,IAAI,CAAC,EAAE,CAACX,IAAI,CAAC,CAAC;EAC7E,MAAMc,UAAU,GAAGd,IAAI,CAACU,SAAS,CAAC,CAAC;EACnC,MAAMK,gBAAgB,GAAGf,IAAI,CAACgB,mBAAmB,CAAC,CAAC;EACnD,MAAMC,MAAM,GAAGF,gBAAgB,CAACG,IAAI,CAACT,MAAM,IAAIA,MAAM,CAACE,IAAI,KAAKG,UAAU,CAACH,IAAI,CAAC;EAC/E,OAAO;IACNF,MAAM,EAAEK,UAAU,CAACH,IAAI;IACvBQ,SAAS,EAAEF,MAAM,EAAEE,SAAS,IAAI,KAAK;IACrCL,UAAU;IACVC,gBAAgB;IAChBF;EACD,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ const VARIABLE_PATTERN = /\{\{\s*([\w.]+)\s*\}\}/g;
4
+
5
+ /**
6
+ * Replaces `{{name}}` placeholders with named values. Missing variables keep
7
+ * their placeholder text so the result stays deterministic, and each missing
8
+ * name is reported through `onMissingVariable`.
9
+ */
10
+ export function interpolate(text, vars, onMissingVariable) {
11
+ return text.replace(VARIABLE_PATTERN, (placeholder, name) => {
12
+ const value = vars?.[name];
13
+ if (value === undefined || value === null) {
14
+ onMissingVariable?.(name);
15
+ return placeholder;
16
+ }
17
+ return String(value);
18
+ });
19
+ }
20
+ //# 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;AACA,OAAO,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":[]}