inline-i18n-multi 0.2.0 → 0.3.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.
package/README.md CHANGED
@@ -53,8 +53,10 @@ See "Hello" in your app? Just search for "Hello" in your codebase. **Done.**
53
53
  - **Type-safe** - Full TypeScript support with variable type checking
54
54
  - **Multiple languages** - Support for any number of locales
55
55
  - **i18n compatible** - Support for traditional key-based translations with JSON dictionaries
56
- - **ICU Message Format** - Plural and select syntax for complex translations
56
+ - **ICU Message Format** - Plural, select, date, number, and time formatting
57
57
  - **Variable interpolation** - `{name}` syntax for dynamic values
58
+ - **Locale Fallback Chain** - BCP 47 parent locale support (`zh-TW` → `zh` → `en`)
59
+ - **Missing Translation Warning** - Development-time diagnostics with customizable handlers
58
60
 
59
61
  ---
60
62
 
@@ -184,6 +186,56 @@ it({
184
186
  ko: '{name}님이 {count, plural, =0 {메시지가 없습니다} other {# 개의 메시지가 있습니다}}',
185
187
  en: '{name} has {count, plural, =0 {no messages} one {# message} other {# messages}}'
186
188
  }, { name: 'John', count: 3 }) // → "John has 3 messages"
189
+
190
+ // Date formatting
191
+ it({
192
+ en: 'Created: {date, date, long}',
193
+ ko: '생성일: {date, date, long}'
194
+ }, { date: new Date() }) // → "Created: January 15, 2024"
195
+
196
+ // Number formatting
197
+ it({
198
+ en: 'Price: {price, number}',
199
+ ko: '가격: {price, number}'
200
+ }, { price: 1234.56 }) // → "Price: 1,234.56"
201
+ ```
202
+
203
+ **Supported ICU styles:**
204
+ - `number`: `decimal`, `percent`, `integer`, `currency`
205
+ - `date`: `short`, `medium`, `long`, `full`
206
+ - `time`: `short`, `medium`, `long`, `full`
207
+
208
+ ---
209
+
210
+ ## Configuration
211
+
212
+ Configure global settings for fallback behavior and warnings:
213
+
214
+ ```typescript
215
+ import { configure, getConfig, resetConfig } from 'inline-i18n-multi'
216
+
217
+ configure({
218
+ fallbackLocale: 'en', // Final fallback (default: 'en')
219
+ autoParentLocale: true, // BCP 47 parent (zh-TW → zh)
220
+ fallbackChain: { // Custom chains
221
+ 'pt-BR': ['pt', 'es', 'en']
222
+ },
223
+ warnOnMissing: true, // Enable warnings
224
+ onMissingTranslation: (w) => { // Custom handler
225
+ console.warn(`Missing: ${w.requestedLocale}`)
226
+ }
227
+ })
228
+ ```
229
+
230
+ ### Locale Fallback Chain
231
+
232
+ Automatic locale fallback with BCP 47 support:
233
+
234
+ ```typescript
235
+ setLocale('zh-TW')
236
+ it({ en: 'Hello', zh: '你好' }) // → '你好' (falls back to zh)
237
+
238
+ t('greeting') // Also works with dictionaries
187
239
  ```
188
240
 
189
241
  ---
@@ -234,12 +286,39 @@ Available helpers:
234
286
  | `getLoadedLocales()` | Get array of loaded locale codes |
235
287
  | `getDictionary(locale)` | Get dictionary for a specific locale |
236
288
 
289
+ ### Configuration
290
+
291
+ | Function | Description |
292
+ |----------|-------------|
293
+ | `configure(options)` | Configure global settings (fallback, warnings) |
294
+ | `getConfig()` | Get current configuration |
295
+ | `resetConfig()` | Reset configuration to defaults |
296
+
237
297
  ### Types
238
298
 
239
299
  ```typescript
240
300
  type Locale = string
241
301
  type Translations = Record<Locale, string>
242
- type TranslationVars = Record<string, string | number>
302
+ type TranslationVars = Record<string, string | number | Date>
303
+
304
+ interface Config {
305
+ defaultLocale: Locale
306
+ fallbackLocale?: Locale
307
+ autoParentLocale?: boolean
308
+ fallbackChain?: Record<Locale, Locale[]>
309
+ warnOnMissing?: boolean
310
+ onMissingTranslation?: WarningHandler
311
+ }
312
+
313
+ interface TranslationWarning {
314
+ type: 'missing_translation'
315
+ key?: string
316
+ requestedLocale: string
317
+ availableLocales: string[]
318
+ fallbackUsed?: string
319
+ }
320
+
321
+ type WarningHandler = (warning: TranslationWarning) => void
243
322
  ```
244
323
 
245
324
  ---
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Locale code type (e.g., 'ko', 'en', 'ja')
2
+ * Locale code type (e.g., 'ko', 'en', 'ja', 'zh-TW')
3
3
  */
4
4
  type Locale = string;
5
5
  /**
@@ -8,14 +8,43 @@ type Locale = string;
8
8
  type Translations = Record<Locale, string>;
9
9
  /**
10
10
  * Variables for interpolation
11
+ * Supports string, number, and Date values for ICU formatting
12
+ */
13
+ type TranslationVars = Record<string, string | number | Date>;
14
+ /**
15
+ * Warning information for missing translations
16
+ */
17
+ interface TranslationWarning {
18
+ type: 'missing_translation';
19
+ /** Dictionary key (for t() function) */
20
+ key?: string;
21
+ /** The locale that was requested */
22
+ requestedLocale: string;
23
+ /** Available locales that have translations */
24
+ availableLocales: string[];
25
+ /** The locale that was used as fallback */
26
+ fallbackUsed?: string;
27
+ }
28
+ /**
29
+ * Warning handler function type
11
30
  */
12
- type TranslationVars = Record<string, string | number>;
31
+ type WarningHandler = (warning: TranslationWarning) => void;
13
32
  /**
14
33
  * Configuration options
15
34
  */
16
35
  interface Config {
36
+ /** Default locale to use when none is set */
17
37
  defaultLocale: Locale;
38
+ /** Fallback locale when translation is missing (default: 'en') */
18
39
  fallbackLocale?: Locale;
40
+ /** Enable automatic BCP 47 parent locale derivation (default: true) */
41
+ autoParentLocale?: boolean;
42
+ /** Custom fallback chain for specific locales */
43
+ fallbackChain?: Record<Locale, Locale[]>;
44
+ /** Enable warnings when translation is missing (default: true in dev mode) */
45
+ warnOnMissing?: boolean;
46
+ /** Custom warning handler */
47
+ onMissingTranslation?: WarningHandler;
19
48
  }
20
49
 
21
50
  /**
@@ -126,4 +155,24 @@ declare function getLoadedLocales(): Locale[];
126
155
  */
127
156
  declare function getDictionary(locale: Locale): Dictionary | undefined;
128
157
 
129
- export { type Config, type Dictionaries, type Dictionary, type Locale, type PluralRules, type TranslationVars, type Translations, __i18n_lookup, clearDictionaries, en_de, en_es, en_fr, en_ja, en_zh, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, setLocale, t, zh_es };
158
+ /**
159
+ * Configure inline-i18n-multi settings
160
+ *
161
+ * @example
162
+ * configure({
163
+ * fallbackLocale: 'en',
164
+ * fallbackChain: { 'pt-BR': ['pt', 'es', 'en'] },
165
+ * warnOnMissing: true,
166
+ * })
167
+ */
168
+ declare function configure(options: Partial<Config>): void;
169
+ /**
170
+ * Get current configuration
171
+ */
172
+ declare function getConfig(): Required<Config>;
173
+ /**
174
+ * Reset configuration to defaults
175
+ */
176
+ declare function resetConfig(): void;
177
+
178
+ export { type Config, type Dictionaries, type Dictionary, type Locale, type PluralRules, type TranslationVars, type TranslationWarning, type Translations, type WarningHandler, __i18n_lookup, clearDictionaries, configure, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, resetConfig, setLocale, t, zh_es };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Locale code type (e.g., 'ko', 'en', 'ja')
2
+ * Locale code type (e.g., 'ko', 'en', 'ja', 'zh-TW')
3
3
  */
4
4
  type Locale = string;
5
5
  /**
@@ -8,14 +8,43 @@ type Locale = string;
8
8
  type Translations = Record<Locale, string>;
9
9
  /**
10
10
  * Variables for interpolation
11
+ * Supports string, number, and Date values for ICU formatting
12
+ */
13
+ type TranslationVars = Record<string, string | number | Date>;
14
+ /**
15
+ * Warning information for missing translations
16
+ */
17
+ interface TranslationWarning {
18
+ type: 'missing_translation';
19
+ /** Dictionary key (for t() function) */
20
+ key?: string;
21
+ /** The locale that was requested */
22
+ requestedLocale: string;
23
+ /** Available locales that have translations */
24
+ availableLocales: string[];
25
+ /** The locale that was used as fallback */
26
+ fallbackUsed?: string;
27
+ }
28
+ /**
29
+ * Warning handler function type
11
30
  */
12
- type TranslationVars = Record<string, string | number>;
31
+ type WarningHandler = (warning: TranslationWarning) => void;
13
32
  /**
14
33
  * Configuration options
15
34
  */
16
35
  interface Config {
36
+ /** Default locale to use when none is set */
17
37
  defaultLocale: Locale;
38
+ /** Fallback locale when translation is missing (default: 'en') */
18
39
  fallbackLocale?: Locale;
40
+ /** Enable automatic BCP 47 parent locale derivation (default: true) */
41
+ autoParentLocale?: boolean;
42
+ /** Custom fallback chain for specific locales */
43
+ fallbackChain?: Record<Locale, Locale[]>;
44
+ /** Enable warnings when translation is missing (default: true in dev mode) */
45
+ warnOnMissing?: boolean;
46
+ /** Custom warning handler */
47
+ onMissingTranslation?: WarningHandler;
19
48
  }
20
49
 
21
50
  /**
@@ -126,4 +155,24 @@ declare function getLoadedLocales(): Locale[];
126
155
  */
127
156
  declare function getDictionary(locale: Locale): Dictionary | undefined;
128
157
 
129
- export { type Config, type Dictionaries, type Dictionary, type Locale, type PluralRules, type TranslationVars, type Translations, __i18n_lookup, clearDictionaries, en_de, en_es, en_fr, en_ja, en_zh, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, setLocale, t, zh_es };
158
+ /**
159
+ * Configure inline-i18n-multi settings
160
+ *
161
+ * @example
162
+ * configure({
163
+ * fallbackLocale: 'en',
164
+ * fallbackChain: { 'pt-BR': ['pt', 'es', 'en'] },
165
+ * warnOnMissing: true,
166
+ * })
167
+ */
168
+ declare function configure(options: Partial<Config>): void;
169
+ /**
170
+ * Get current configuration
171
+ */
172
+ declare function getConfig(): Required<Config>;
173
+ /**
174
+ * Reset configuration to defaults
175
+ */
176
+ declare function resetConfig(): void;
177
+
178
+ export { type Config, type Dictionaries, type Dictionary, type Locale, type PluralRules, type TranslationVars, type TranslationWarning, type Translations, type WarningHandler, __i18n_lookup, clearDictionaries, configure, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, resetConfig, setLocale, t, zh_es };
package/dist/index.js CHANGED
@@ -10,6 +10,96 @@ function setLocale(locale) {
10
10
  function getLocale() {
11
11
  return currentLocale;
12
12
  }
13
+ var DATE_STYLES = {
14
+ short: { dateStyle: "short" },
15
+ medium: { dateStyle: "medium" },
16
+ long: { dateStyle: "long" },
17
+ full: { dateStyle: "full" }
18
+ };
19
+ var TIME_STYLES = {
20
+ short: { timeStyle: "short" },
21
+ medium: { timeStyle: "medium" },
22
+ long: { timeStyle: "long" },
23
+ full: { timeStyle: "full" }
24
+ };
25
+ var NUMBER_STYLES = {
26
+ decimal: { style: "decimal" },
27
+ percent: { style: "percent" },
28
+ integer: { style: "decimal", maximumFractionDigits: 0 }
29
+ };
30
+ function toDate(value) {
31
+ if (value instanceof Date) {
32
+ return value;
33
+ }
34
+ return new Date(value);
35
+ }
36
+ function formatNumberElement(el, vars, locale) {
37
+ const value = vars[el.value];
38
+ if (value === void 0) {
39
+ return `{${el.value}}`;
40
+ }
41
+ const num = typeof value === "number" ? value : Number(value);
42
+ if (isNaN(num)) {
43
+ return `{${el.value}}`;
44
+ }
45
+ let options = {};
46
+ if (el.style) {
47
+ if (typeof el.style === "string") {
48
+ if (el.style === "currency") {
49
+ options = { style: "currency", currency: "USD" };
50
+ } else if (NUMBER_STYLES[el.style]) {
51
+ options = NUMBER_STYLES[el.style];
52
+ }
53
+ } else if ("parsedOptions" in el.style) {
54
+ options = el.style.parsedOptions;
55
+ }
56
+ }
57
+ try {
58
+ return new Intl.NumberFormat(locale, options).format(num);
59
+ } catch {
60
+ return String(num);
61
+ }
62
+ }
63
+ function formatDateElement(el, vars, locale) {
64
+ const value = vars[el.value];
65
+ if (value === void 0) {
66
+ return `{${el.value}}`;
67
+ }
68
+ let options = {};
69
+ if (el.style) {
70
+ if (typeof el.style === "string") {
71
+ options = DATE_STYLES[el.style] || {};
72
+ } else if ("parsedOptions" in el.style) {
73
+ options = el.style.parsedOptions;
74
+ }
75
+ }
76
+ try {
77
+ const date = toDate(value);
78
+ return new Intl.DateTimeFormat(locale, options).format(date);
79
+ } catch {
80
+ return `{${el.value}}`;
81
+ }
82
+ }
83
+ function formatTimeElement(el, vars, locale) {
84
+ const value = vars[el.value];
85
+ if (value === void 0) {
86
+ return `{${el.value}}`;
87
+ }
88
+ let options = {};
89
+ if (el.style) {
90
+ if (typeof el.style === "string") {
91
+ options = TIME_STYLES[el.style] || {};
92
+ } else if ("parsedOptions" in el.style) {
93
+ options = el.style.parsedOptions;
94
+ }
95
+ }
96
+ try {
97
+ const date = toDate(value);
98
+ return new Intl.DateTimeFormat(locale, options).format(date);
99
+ } catch {
100
+ return `{${el.value}}`;
101
+ }
102
+ }
13
103
  function interpolateICU(template, vars, locale) {
14
104
  const ast = icuMessageformatParser.parse(template);
15
105
  return formatElements(ast, vars, locale, null);
@@ -34,6 +124,15 @@ function formatElement(el, vars, locale, currentPluralValue) {
34
124
  if (icuMessageformatParser.isSelectElement(el)) {
35
125
  return formatSelect(el, vars, locale);
36
126
  }
127
+ if (icuMessageformatParser.isNumberElement(el)) {
128
+ return formatNumberElement(el, vars, locale);
129
+ }
130
+ if (icuMessageformatParser.isDateElement(el)) {
131
+ return formatDateElement(el, vars, locale);
132
+ }
133
+ if (icuMessageformatParser.isTimeElement(el)) {
134
+ return formatTimeElement(el, vars, locale);
135
+ }
37
136
  return "";
38
137
  }
39
138
  function formatPlural(el, vars, locale) {
@@ -67,7 +166,7 @@ function formatSelect(el, vars, locale) {
67
166
  }
68
167
  return `{${el.value}}`;
69
168
  }
70
- var ICU_PATTERN = /\{[^}]+,\s*(plural|select|selectordinal)\s*,/;
169
+ var ICU_PATTERN = /\{[^}]+,\s*(plural|select|selectordinal|number|date|time)\s*[,}]/;
71
170
  function hasICUPattern(template) {
72
171
  return ICU_PATTERN.test(template);
73
172
  }
@@ -85,15 +184,119 @@ function interpolate(template, vars, locale) {
85
184
  });
86
185
  }
87
186
 
187
+ // src/config.ts
188
+ function defaultWarningHandler(warning) {
189
+ const parts = [`[inline-i18n] Missing translation for locale "${warning.requestedLocale}"`];
190
+ if (warning.key) {
191
+ parts.push(`key: "${warning.key}"`);
192
+ }
193
+ parts.push(`Available: [${warning.availableLocales.join(", ")}]`);
194
+ if (warning.fallbackUsed) {
195
+ parts.push(`Using fallback: "${warning.fallbackUsed}"`);
196
+ }
197
+ console.warn(parts.join(" | "));
198
+ }
199
+ function isDevMode() {
200
+ try {
201
+ if (typeof globalThis !== "undefined" && "process" in globalThis) {
202
+ const proc = globalThis.process;
203
+ return proc?.env?.NODE_ENV !== "production";
204
+ }
205
+ return false;
206
+ } catch {
207
+ return false;
208
+ }
209
+ }
210
+ var defaultConfig = {
211
+ defaultLocale: "en",
212
+ fallbackLocale: "en",
213
+ autoParentLocale: true,
214
+ fallbackChain: {},
215
+ warnOnMissing: isDevMode(),
216
+ onMissingTranslation: defaultWarningHandler
217
+ };
218
+ var config = { ...defaultConfig };
219
+ function configure(options) {
220
+ config = { ...config, ...options };
221
+ }
222
+ function getConfig() {
223
+ return {
224
+ ...defaultConfig,
225
+ ...config
226
+ };
227
+ }
228
+ function resetConfig() {
229
+ config = { ...defaultConfig };
230
+ }
231
+ function getParentLocale(locale) {
232
+ const dashIndex = locale.indexOf("-");
233
+ if (dashIndex > 0) {
234
+ return locale.substring(0, dashIndex);
235
+ }
236
+ return void 0;
237
+ }
238
+ function buildFallbackChain(locale) {
239
+ const cfg = getConfig();
240
+ if (cfg.fallbackChain[locale]) {
241
+ return [locale, ...cfg.fallbackChain[locale]];
242
+ }
243
+ const chain = [locale];
244
+ if (cfg.autoParentLocale) {
245
+ let current = locale;
246
+ while (true) {
247
+ const parent = getParentLocale(current);
248
+ if (parent && !chain.includes(parent)) {
249
+ chain.push(parent);
250
+ current = parent;
251
+ } else {
252
+ break;
253
+ }
254
+ }
255
+ }
256
+ const finalFallback = cfg.fallbackLocale;
257
+ if (finalFallback && !chain.includes(finalFallback)) {
258
+ chain.push(finalFallback);
259
+ }
260
+ return chain;
261
+ }
262
+ function emitWarning(warning) {
263
+ const cfg = getConfig();
264
+ if (cfg.warnOnMissing && cfg.onMissingTranslation) {
265
+ cfg.onMissingTranslation(warning);
266
+ }
267
+ }
268
+
88
269
  // src/translate.ts
89
270
  function resolveTemplate(translations) {
90
271
  const locale = getLocale();
91
- const template = translations[locale];
92
- if (template) return { template, locale };
93
- const fallback = translations.en ?? Object.values(translations)[0];
94
- if (fallback) return { template: fallback, locale: "en" };
272
+ const availableLocales = Object.keys(translations);
273
+ const fallbackChain = buildFallbackChain(locale);
274
+ for (const tryLocale of fallbackChain) {
275
+ const template = translations[tryLocale];
276
+ if (template) {
277
+ if (tryLocale !== locale) {
278
+ emitWarning({
279
+ type: "missing_translation",
280
+ requestedLocale: locale,
281
+ availableLocales,
282
+ fallbackUsed: tryLocale
283
+ });
284
+ }
285
+ return { template, locale: tryLocale };
286
+ }
287
+ }
288
+ const firstAvailable = Object.entries(translations)[0];
289
+ if (firstAvailable) {
290
+ emitWarning({
291
+ type: "missing_translation",
292
+ requestedLocale: locale,
293
+ availableLocales,
294
+ fallbackUsed: firstAvailable[0]
295
+ });
296
+ return { template: firstAvailable[1], locale: firstAvailable[0] };
297
+ }
95
298
  throw new Error(
96
- `No translation found for locale "${locale}". Available: ${Object.keys(translations).join(", ")}`
299
+ `No translation found for locale "${locale}". Available: ${availableLocales.join(", ")}`
97
300
  );
98
301
  }
99
302
  function it(first, second, third) {
@@ -114,16 +317,34 @@ function it(first, second, third) {
114
317
  // src/runtime.ts
115
318
  function __i18n_lookup(_hash, translations, vars) {
116
319
  const locale = getLocale();
117
- const template = translations[locale];
118
- if (template) {
119
- return interpolate(template, vars);
320
+ const availableLocales = Object.keys(translations);
321
+ const fallbackChain = buildFallbackChain(locale);
322
+ for (const tryLocale of fallbackChain) {
323
+ const template = translations[tryLocale];
324
+ if (template) {
325
+ if (tryLocale !== locale) {
326
+ emitWarning({
327
+ type: "missing_translation",
328
+ requestedLocale: locale,
329
+ availableLocales,
330
+ fallbackUsed: tryLocale
331
+ });
332
+ }
333
+ return interpolate(template, vars, tryLocale);
334
+ }
120
335
  }
121
- const fallback = translations.en ?? Object.values(translations)[0];
122
- if (fallback) {
123
- return interpolate(fallback, vars);
336
+ const firstAvailable = Object.entries(translations)[0];
337
+ if (firstAvailable) {
338
+ emitWarning({
339
+ type: "missing_translation",
340
+ requestedLocale: locale,
341
+ availableLocales,
342
+ fallbackUsed: firstAvailable[0]
343
+ });
344
+ return interpolate(firstAvailable[1], vars, firstAvailable[0]);
124
345
  }
125
346
  throw new Error(
126
- `No translation found for locale "${locale}". Available: ${Object.keys(translations).join(", ")}`
347
+ `No translation found for locale "${locale}". Available: ${availableLocales.join(", ")}`
127
348
  );
128
349
  }
129
350
  if (typeof globalThis !== "undefined") {
@@ -183,32 +404,52 @@ function getPluralCategory(count, locale) {
183
404
  const rules = new Intl.PluralRules(locale);
184
405
  return rules.select(count);
185
406
  }
186
- function t(key, vars, locale) {
187
- const currentLocale2 = locale ?? getLocale();
188
- const dict = dictionaries[currentLocale2];
189
- if (!dict) {
190
- console.warn(`[inline-i18n] No dictionary loaded for locale: ${currentLocale2}`);
191
- return key;
192
- }
407
+ function findInDictionary(dict, key, vars, locale) {
193
408
  let template = getNestedValue(dict, key);
194
409
  if (vars && typeof vars.count === "number") {
195
- const pluralKey = `${key}_${getPluralCategory(vars.count, currentLocale2)}`;
410
+ const pluralKey = `${key}_${getPluralCategory(vars.count, locale)}`;
196
411
  const pluralTemplate = getNestedValue(dict, pluralKey);
197
412
  if (pluralTemplate) {
198
413
  template = pluralTemplate;
199
414
  }
200
415
  }
201
- if (!template) {
202
- const fallbackDict = dictionaries["en"];
203
- if (fallbackDict && currentLocale2 !== "en") {
204
- template = getNestedValue(fallbackDict, key);
416
+ return template;
417
+ }
418
+ function t(key, vars, locale) {
419
+ const currentLocale2 = locale ?? getLocale();
420
+ const fallbackChain = buildFallbackChain(currentLocale2);
421
+ const availableLocales = Object.keys(dictionaries);
422
+ let template;
423
+ let usedLocale;
424
+ for (const tryLocale of fallbackChain) {
425
+ const dict = dictionaries[tryLocale];
426
+ if (!dict) continue;
427
+ const found = findInDictionary(dict, key, vars, tryLocale);
428
+ if (found) {
429
+ template = found;
430
+ usedLocale = tryLocale;
431
+ break;
205
432
  }
206
433
  }
207
434
  if (!template) {
208
- console.warn(`[inline-i18n] Missing translation: ${key} (${currentLocale2})`);
435
+ emitWarning({
436
+ type: "missing_translation",
437
+ key,
438
+ requestedLocale: currentLocale2,
439
+ availableLocales
440
+ });
209
441
  return key;
210
442
  }
211
- return interpolate(template, vars, currentLocale2);
443
+ if (usedLocale && usedLocale !== currentLocale2) {
444
+ emitWarning({
445
+ type: "missing_translation",
446
+ key,
447
+ requestedLocale: currentLocale2,
448
+ availableLocales,
449
+ fallbackUsed: usedLocale
450
+ });
451
+ }
452
+ return interpolate(template, vars, usedLocale || currentLocale2);
212
453
  }
213
454
  function hasTranslation(key, locale) {
214
455
  const currentLocale2 = locale ?? getLocale();
@@ -224,11 +465,13 @@ function getDictionary(locale) {
224
465
 
225
466
  exports.__i18n_lookup = __i18n_lookup;
226
467
  exports.clearDictionaries = clearDictionaries;
468
+ exports.configure = configure;
227
469
  exports.en_de = en_de;
228
470
  exports.en_es = en_es;
229
471
  exports.en_fr = en_fr;
230
472
  exports.en_ja = en_ja;
231
473
  exports.en_zh = en_zh;
474
+ exports.getConfig = getConfig;
232
475
  exports.getDictionary = getDictionary;
233
476
  exports.getLoadedLocales = getLoadedLocales;
234
477
  exports.getLocale = getLocale;
@@ -243,6 +486,7 @@ exports.ja_es = ja_es;
243
486
  exports.ja_zh = ja_zh;
244
487
  exports.loadDictionaries = loadDictionaries;
245
488
  exports.loadDictionary = loadDictionary;
489
+ exports.resetConfig = resetConfig;
246
490
  exports.setLocale = setLocale;
247
491
  exports.t = t;
248
492
  exports.zh_es = zh_es;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context.ts","../src/icu.ts","../src/interpolation.ts","../src/translate.ts","../src/runtime.ts","../src/pairs.ts","../src/dictionary.ts"],"names":["parse","isLiteralElement","isArgumentElement","isPoundElement","isPluralElement","isSelectElement","translations","vars","template","locale","currentLocale"],"mappings":"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","file":"index.js","sourcesContent":["import type { Locale } from './types'\n\nlet currentLocale: Locale = 'en'\n\nexport function setLocale(locale: Locale): void {\n currentLocale = locale\n}\n\nexport function getLocale(): Locale {\n return currentLocale\n}\n","import {\n parse,\n TYPE,\n type MessageFormatElement,\n type PluralElement,\n type SelectElement,\n isLiteralElement,\n isArgumentElement,\n isPluralElement,\n isSelectElement,\n isPoundElement,\n} from '@formatjs/icu-messageformat-parser'\n\nexport type ICUVars = Record<string, string | number>\n\n/**\n * Parse and format an ICU Message Format string\n */\nexport function interpolateICU(\n template: string,\n vars: ICUVars,\n locale: string\n): string {\n const ast = parse(template)\n return formatElements(ast, vars, locale, null)\n}\n\nfunction formatElements(\n elements: MessageFormatElement[],\n vars: ICUVars,\n locale: string,\n currentPluralValue: number | null\n): string {\n return elements\n .map((el) => formatElement(el, vars, locale, currentPluralValue))\n .join('')\n}\n\nfunction formatElement(\n el: MessageFormatElement,\n vars: ICUVars,\n locale: string,\n currentPluralValue: number | null\n): string {\n if (isLiteralElement(el)) {\n return el.value\n }\n\n if (isArgumentElement(el)) {\n const value = vars[el.value]\n return value !== undefined ? String(value) : `{${el.value}}`\n }\n\n if (isPoundElement(el)) {\n // # is replaced with the current plural value\n return currentPluralValue !== null ? String(currentPluralValue) : '#'\n }\n\n if (isPluralElement(el)) {\n return formatPlural(el, vars, locale)\n }\n\n if (isSelectElement(el)) {\n return formatSelect(el, vars, locale)\n }\n\n // Unsupported types (number, date, time, tag) - return as-is for now\n return ''\n}\n\nfunction formatPlural(\n el: PluralElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n if (typeof value !== 'number') {\n return `{${el.value}}`\n }\n\n const adjustedValue = value - el.offset\n const pluralRules = new Intl.PluralRules(locale, { type: el.pluralType })\n const category = pluralRules.select(adjustedValue)\n\n // Try exact match first (=0, =1, =2, etc.)\n const exactKey = `=${value}`\n if (el.options[exactKey]) {\n return formatElements(el.options[exactKey].value, vars, locale, adjustedValue)\n }\n\n // Then try plural category (zero, one, two, few, many, other)\n if (el.options[category]) {\n return formatElements(el.options[category].value, vars, locale, adjustedValue)\n }\n\n // Fallback to 'other'\n if (el.options.other) {\n return formatElements(el.options.other.value, vars, locale, adjustedValue)\n }\n\n return `{${el.value}}`\n}\n\nfunction formatSelect(\n el: SelectElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n const key = String(value)\n\n // Try exact match\n if (el.options[key]) {\n return formatElements(el.options[key].value, vars, locale, null)\n }\n\n // Fallback to 'other'\n if (el.options.other) {\n return formatElements(el.options.other.value, vars, locale, null)\n }\n\n return `{${el.value}}`\n}\n\n// Pattern to detect ICU format (plural, select, selectordinal)\nexport const ICU_PATTERN = /\\{[^}]+,\\s*(plural|select|selectordinal)\\s*,/\n\n/**\n * Check if a template contains ICU Message Format patterns\n */\nexport function hasICUPattern(template: string): boolean {\n return ICU_PATTERN.test(template)\n}\n","import type { TranslationVars } from './types'\nimport { hasICUPattern, interpolateICU } from './icu'\n\nconst VARIABLE_PATTERN = /\\{(\\w+)\\}/g\n\nexport function interpolate(\n template: string,\n vars?: TranslationVars,\n locale?: string,\n): string {\n if (!vars) return template\n\n // ICU Message Format (plural, select)\n if (hasICUPattern(template)) {\n return interpolateICU(template, vars, locale || 'en')\n }\n\n // Simple variable substitution\n return template.replace(VARIABLE_PATTERN, (_, key) => {\n const value = vars[key]\n return value !== undefined ? String(value) : `{${key}}`\n })\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\n\ninterface ResolveResult {\n template: string\n locale: string\n}\n\nfunction resolveTemplate(translations: Translations): ResolveResult {\n const locale = getLocale()\n\n const template = translations[locale]\n if (template) return { template, locale }\n\n // fallback: en -> first available\n const fallback = translations.en ?? Object.values(translations)[0]\n if (fallback) return { template: fallback, locale: 'en' }\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${Object.keys(translations).join(', ')}`\n )\n}\n\n/**\n * Translate with two languages (shorthand)\n * @param ko - Korean text\n * @param en - English text\n * @param vars - Variables for interpolation\n */\nexport function it(ko: string, en: string, vars?: TranslationVars): string\n\n/**\n * Translate with multiple languages (object syntax)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function it(translations: Translations, vars?: TranslationVars): string\n\nexport function it(\n first: string | Translations,\n second?: string | TranslationVars,\n third?: TranslationVars,\n): string {\n // object syntax: it({ ko: '...', en: '...' }, vars?)\n if (typeof first === 'object') {\n const translations = first\n const vars = second as TranslationVars | undefined\n const { template, locale } = resolveTemplate(translations)\n return interpolate(template, vars, locale)\n }\n\n // shorthand syntax: it('한글', 'English', vars?)\n const ko = first\n const en = second as string\n const vars = third\n\n const translations: Translations = { ko, en }\n const { template, locale } = resolveTemplate(translations)\n return interpolate(template, vars, locale)\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\n\n/**\n * Runtime lookup function for plugin-transformed code.\n * This is called by code that has been processed by @inline-i18n-multi/babel-plugin\n * or @inline-i18n-multi/swc-plugin.\n *\n * @param _hash - Content hash (for caching/debugging, unused at runtime)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function __i18n_lookup(\n _hash: string,\n translations: Translations,\n vars?: TranslationVars\n): string {\n const locale = getLocale()\n\n const template = translations[locale]\n if (template) {\n return interpolate(template, vars)\n }\n\n // fallback: en -> first available\n const fallback = translations.en ?? Object.values(translations)[0]\n if (fallback) {\n return interpolate(fallback, vars)\n }\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${Object.keys(translations).join(', ')}`\n )\n}\n\n// Register __i18n_lookup globally for plugin transformations\n// This makes it available without explicit import after bundle\nif (typeof globalThis !== 'undefined') {\n (globalThis as Record<string, unknown>).__i18n_lookup = __i18n_lookup\n}\n","import type { Locale, Translations, TranslationVars } from './types'\nimport { it } from './translate'\n\ntype PairFunction = (\n text1: string,\n text2: string,\n vars?: TranslationVars,\n) => string\n\nfunction createPair(lang1: Locale, lang2: Locale): PairFunction {\n return (text1, text2, vars) => {\n const translations: Translations = {\n [lang1]: text1,\n [lang2]: text2,\n }\n return it(translations, vars)\n }\n}\n\n// Korean combinations\nexport const it_ja = createPair('ko', 'ja')\nexport const it_zh = createPair('ko', 'zh')\nexport const it_es = createPair('ko', 'es')\nexport const it_fr = createPair('ko', 'fr')\nexport const it_de = createPair('ko', 'de')\n\n// English combinations\nexport const en_ja = createPair('en', 'ja')\nexport const en_zh = createPair('en', 'zh')\nexport const en_es = createPair('en', 'es')\nexport const en_fr = createPair('en', 'fr')\nexport const en_de = createPair('en', 'de')\n\n// Other combinations\nexport const ja_zh = createPair('ja', 'zh')\nexport const ja_es = createPair('ja', 'es')\nexport const zh_es = createPair('zh', 'es')\n","import { getLocale } from './context'\nimport type { Locale, TranslationVars } from './types'\nimport { interpolate } from './interpolation'\n\n/**\n * Nested dictionary structure for translations\n * @example { greeting: { hello: \"Hello\", goodbye: \"Goodbye\" } }\n */\nexport type Dictionary = {\n [key: string]: string | Dictionary\n}\n\n/**\n * All loaded dictionaries by locale\n */\nexport type Dictionaries = Record<Locale, Dictionary>\n\n/**\n * Plural rules configuration\n */\nexport interface PluralRules {\n zero?: string\n one?: string\n two?: string\n few?: string\n many?: string\n other: string\n}\n\n// Global dictionary storage\nlet dictionaries: Dictionaries = {}\n\n/**\n * Load translations from dictionary objects\n * @param dicts - Dictionary objects keyed by locale\n * @example\n * loadDictionaries({\n * en: { greeting: { hello: \"Hello\" } },\n * ko: { greeting: { hello: \"안녕하세요\" } }\n * })\n */\nexport function loadDictionaries(dicts: Dictionaries): void {\n dictionaries = { ...dictionaries, ...dicts }\n}\n\n/**\n * Load a single locale's dictionary\n * @param locale - Locale code\n * @param dict - Dictionary object\n */\nexport function loadDictionary(locale: Locale, dict: Dictionary): void {\n dictionaries[locale] = { ...dictionaries[locale], ...dict }\n}\n\n/**\n * Clear all loaded dictionaries\n */\nexport function clearDictionaries(): void {\n dictionaries = {}\n}\n\n/**\n * Get a nested value from dictionary using dot notation\n * @param dict - Dictionary object\n * @param key - Dot-separated key path\n */\nfunction getNestedValue(dict: Dictionary, key: string): string | undefined {\n const parts = key.split('.')\n let current: string | Dictionary | undefined = dict\n\n for (const part of parts) {\n if (typeof current !== 'object' || current === null) {\n return undefined\n }\n current = current[part]\n if (current === undefined) {\n return undefined\n }\n }\n\n return typeof current === 'string' ? current : undefined\n}\n\n/**\n * Get plural category using Intl.PluralRules\n */\nfunction getPluralCategory(count: number, locale: Locale): Intl.LDMLPluralRule {\n const rules = new Intl.PluralRules(locale)\n return rules.select(count)\n}\n\n/**\n * Translate using key-based lookup (i18n compatible)\n * @param key - Dot-separated translation key\n * @param vars - Variables for interpolation (including 'count' for plurals)\n * @param locale - Override locale (optional)\n * @example\n * t('greeting.hello') // \"Hello\"\n * t('items.count', { count: 5 }) // \"5 items\"\n */\nexport function t(\n key: string,\n vars?: TranslationVars,\n locale?: Locale\n): string {\n const currentLocale = locale ?? getLocale()\n const dict = dictionaries[currentLocale]\n\n if (!dict) {\n console.warn(`[inline-i18n] No dictionary loaded for locale: ${currentLocale}`)\n return key\n }\n\n let template = getNestedValue(dict, key)\n\n // Handle plurals if count is provided\n if (vars && typeof vars.count === 'number') {\n const pluralKey = `${key}_${getPluralCategory(vars.count, currentLocale)}`\n const pluralTemplate = getNestedValue(dict, pluralKey)\n if (pluralTemplate) {\n template = pluralTemplate\n }\n }\n\n if (!template) {\n // Try fallback to English\n const fallbackDict = dictionaries['en']\n if (fallbackDict && currentLocale !== 'en') {\n template = getNestedValue(fallbackDict, key)\n }\n }\n\n if (!template) {\n console.warn(`[inline-i18n] Missing translation: ${key} (${currentLocale})`)\n return key\n }\n\n return interpolate(template, vars, currentLocale)\n}\n\n/**\n * Check if a translation key exists\n */\nexport function hasTranslation(key: string, locale?: Locale): boolean {\n const currentLocale = locale ?? getLocale()\n const dict = dictionaries[currentLocale]\n return dict ? getNestedValue(dict, key) !== undefined : false\n}\n\n/**\n * Get all loaded locales\n */\nexport function getLoadedLocales(): Locale[] {\n return Object.keys(dictionaries)\n}\n\n/**\n * Get dictionary for a specific locale\n */\nexport function getDictionary(locale: Locale): Dictionary | undefined {\n return dictionaries[locale]\n}\n"]}
1
+ {"version":3,"sources":["../src/context.ts","../src/icu.ts","../src/interpolation.ts","../src/config.ts","../src/translate.ts","../src/runtime.ts","../src/pairs.ts","../src/dictionary.ts"],"names":["parse","isLiteralElement","isArgumentElement","isPoundElement","isPluralElement","isSelectElement","isNumberElement","isDateElement","isTimeElement","translations","vars","template","locale","currentLocale"],"mappings":"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","file":"index.js","sourcesContent":["import type { Locale } from './types'\n\nlet currentLocale: Locale = 'en'\n\nexport function setLocale(locale: Locale): void {\n currentLocale = locale\n}\n\nexport function getLocale(): Locale {\n return currentLocale\n}\n","import {\n parse,\n TYPE,\n type MessageFormatElement,\n type PluralElement,\n type SelectElement,\n type NumberElement,\n type DateElement,\n type TimeElement,\n isLiteralElement,\n isArgumentElement,\n isPluralElement,\n isSelectElement,\n isPoundElement,\n isNumberElement,\n isDateElement,\n isTimeElement,\n} from '@formatjs/icu-messageformat-parser'\n\nexport type ICUVars = Record<string, string | number | Date>\n\n/**\n * Map ICU date style names to Intl.DateTimeFormat options\n */\nconst DATE_STYLES: Record<string, Intl.DateTimeFormatOptions> = {\n short: { dateStyle: 'short' },\n medium: { dateStyle: 'medium' },\n long: { dateStyle: 'long' },\n full: { dateStyle: 'full' },\n}\n\n/**\n * Map ICU time style names to Intl.DateTimeFormat options\n */\nconst TIME_STYLES: Record<string, Intl.DateTimeFormatOptions> = {\n short: { timeStyle: 'short' },\n medium: { timeStyle: 'medium' },\n long: { timeStyle: 'long' },\n full: { timeStyle: 'full' },\n}\n\n/**\n * Map ICU number style names to Intl.NumberFormat options\n */\nconst NUMBER_STYLES: Record<string, Intl.NumberFormatOptions> = {\n decimal: { style: 'decimal' },\n percent: { style: 'percent' },\n integer: { style: 'decimal', maximumFractionDigits: 0 },\n}\n\n/**\n * Convert value to Date\n */\nfunction toDate(value: string | number | Date): Date {\n if (value instanceof Date) {\n return value\n }\n return new Date(value)\n}\n\n/**\n * Format a number element\n */\nfunction formatNumberElement(\n el: NumberElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n if (value === undefined) {\n return `{${el.value}}`\n }\n\n const num = typeof value === 'number' ? value : Number(value)\n if (isNaN(num)) {\n return `{${el.value}}`\n }\n\n let options: Intl.NumberFormatOptions = {}\n\n if (el.style) {\n if (typeof el.style === 'string') {\n // Check for currency format: \"currency\" or specific currency like \"USD\"\n if (el.style === 'currency') {\n options = { style: 'currency', currency: 'USD' }\n } else if (NUMBER_STYLES[el.style]) {\n options = NUMBER_STYLES[el.style]\n }\n } else if ('parsedOptions' in el.style) {\n // NumberSkeleton with parsed options\n options = el.style.parsedOptions as Intl.NumberFormatOptions\n }\n }\n\n try {\n return new Intl.NumberFormat(locale, options).format(num)\n } catch {\n return String(num)\n }\n}\n\n/**\n * Format a date element\n */\nfunction formatDateElement(\n el: DateElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n if (value === undefined) {\n return `{${el.value}}`\n }\n\n let options: Intl.DateTimeFormatOptions = {}\n\n if (el.style) {\n if (typeof el.style === 'string') {\n options = DATE_STYLES[el.style] || {}\n } else if ('parsedOptions' in el.style) {\n // DateTimeSkeleton with parsed options\n options = el.style.parsedOptions as Intl.DateTimeFormatOptions\n }\n }\n\n try {\n const date = toDate(value)\n return new Intl.DateTimeFormat(locale, options).format(date)\n } catch {\n return `{${el.value}}`\n }\n}\n\n/**\n * Format a time element\n */\nfunction formatTimeElement(\n el: TimeElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n if (value === undefined) {\n return `{${el.value}}`\n }\n\n let options: Intl.DateTimeFormatOptions = {}\n\n if (el.style) {\n if (typeof el.style === 'string') {\n options = TIME_STYLES[el.style] || {}\n } else if ('parsedOptions' in el.style) {\n // DateTimeSkeleton with parsed options\n options = el.style.parsedOptions as Intl.DateTimeFormatOptions\n }\n }\n\n try {\n const date = toDate(value)\n return new Intl.DateTimeFormat(locale, options).format(date)\n } catch {\n return `{${el.value}}`\n }\n}\n\n/**\n * Parse and format an ICU Message Format string\n */\nexport function interpolateICU(\n template: string,\n vars: ICUVars,\n locale: string\n): string {\n const ast = parse(template)\n return formatElements(ast, vars, locale, null)\n}\n\nfunction formatElements(\n elements: MessageFormatElement[],\n vars: ICUVars,\n locale: string,\n currentPluralValue: number | null\n): string {\n return elements\n .map((el) => formatElement(el, vars, locale, currentPluralValue))\n .join('')\n}\n\nfunction formatElement(\n el: MessageFormatElement,\n vars: ICUVars,\n locale: string,\n currentPluralValue: number | null\n): string {\n if (isLiteralElement(el)) {\n return el.value\n }\n\n if (isArgumentElement(el)) {\n const value = vars[el.value]\n return value !== undefined ? String(value) : `{${el.value}}`\n }\n\n if (isPoundElement(el)) {\n // # is replaced with the current plural value\n return currentPluralValue !== null ? String(currentPluralValue) : '#'\n }\n\n if (isPluralElement(el)) {\n return formatPlural(el, vars, locale)\n }\n\n if (isSelectElement(el)) {\n return formatSelect(el, vars, locale)\n }\n\n if (isNumberElement(el)) {\n return formatNumberElement(el, vars, locale)\n }\n\n if (isDateElement(el)) {\n return formatDateElement(el, vars, locale)\n }\n\n if (isTimeElement(el)) {\n return formatTimeElement(el, vars, locale)\n }\n\n // Tag elements - not supported yet\n return ''\n}\n\nfunction formatPlural(\n el: PluralElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n if (typeof value !== 'number') {\n return `{${el.value}}`\n }\n\n const adjustedValue = value - el.offset\n const pluralRules = new Intl.PluralRules(locale, { type: el.pluralType })\n const category = pluralRules.select(adjustedValue)\n\n // Try exact match first (=0, =1, =2, etc.)\n const exactKey = `=${value}`\n if (el.options[exactKey]) {\n return formatElements(el.options[exactKey].value, vars, locale, adjustedValue)\n }\n\n // Then try plural category (zero, one, two, few, many, other)\n if (el.options[category]) {\n return formatElements(el.options[category].value, vars, locale, adjustedValue)\n }\n\n // Fallback to 'other'\n if (el.options.other) {\n return formatElements(el.options.other.value, vars, locale, adjustedValue)\n }\n\n return `{${el.value}}`\n}\n\nfunction formatSelect(\n el: SelectElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n const key = String(value)\n\n // Try exact match\n if (el.options[key]) {\n return formatElements(el.options[key].value, vars, locale, null)\n }\n\n // Fallback to 'other'\n if (el.options.other) {\n return formatElements(el.options.other.value, vars, locale, null)\n }\n\n return `{${el.value}}`\n}\n\n// Pattern to detect ICU format (plural, select, selectordinal, number, date, time)\nexport const ICU_PATTERN = /\\{[^}]+,\\s*(plural|select|selectordinal|number|date|time)\\s*[,}]/\n\n/**\n * Check if a template contains ICU Message Format patterns\n */\nexport function hasICUPattern(template: string): boolean {\n return ICU_PATTERN.test(template)\n}\n","import type { TranslationVars } from './types'\nimport { hasICUPattern, interpolateICU } from './icu'\n\nconst VARIABLE_PATTERN = /\\{(\\w+)\\}/g\n\nexport function interpolate(\n template: string,\n vars?: TranslationVars,\n locale?: string,\n): string {\n if (!vars) return template\n\n // ICU Message Format (plural, select)\n if (hasICUPattern(template)) {\n return interpolateICU(template, vars, locale || 'en')\n }\n\n // Simple variable substitution\n return template.replace(VARIABLE_PATTERN, (_, key) => {\n const value = vars[key]\n return value !== undefined ? String(value) : `{${key}}`\n })\n}\n","import type { Config, Locale, TranslationWarning } from './types'\n\n/**\n * Default warning handler - logs to console\n */\nfunction defaultWarningHandler(warning: TranslationWarning): void {\n const parts = [`[inline-i18n] Missing translation for locale \"${warning.requestedLocale}\"`]\n\n if (warning.key) {\n parts.push(`key: \"${warning.key}\"`)\n }\n\n parts.push(`Available: [${warning.availableLocales.join(', ')}]`)\n\n if (warning.fallbackUsed) {\n parts.push(`Using fallback: \"${warning.fallbackUsed}\"`)\n }\n\n console.warn(parts.join(' | '))\n}\n\n/**\n * Check if we're in development mode\n */\nfunction isDevMode(): boolean {\n try {\n // Check for Node.js environment\n if (typeof globalThis !== 'undefined' && 'process' in globalThis) {\n const proc = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process\n return proc?.env?.NODE_ENV !== 'production'\n }\n return false\n } catch {\n return false\n }\n}\n\nconst defaultConfig: Required<Config> = {\n defaultLocale: 'en',\n fallbackLocale: 'en',\n autoParentLocale: true,\n fallbackChain: {},\n warnOnMissing: isDevMode(),\n onMissingTranslation: defaultWarningHandler,\n}\n\nlet config: Config = { ...defaultConfig }\n\n/**\n * Configure inline-i18n-multi settings\n *\n * @example\n * configure({\n * fallbackLocale: 'en',\n * fallbackChain: { 'pt-BR': ['pt', 'es', 'en'] },\n * warnOnMissing: true,\n * })\n */\nexport function configure(options: Partial<Config>): void {\n config = { ...config, ...options }\n}\n\n/**\n * Get current configuration\n */\nexport function getConfig(): Required<Config> {\n return {\n ...defaultConfig,\n ...config,\n }\n}\n\n/**\n * Reset configuration to defaults\n */\nexport function resetConfig(): void {\n config = { ...defaultConfig }\n}\n\n/**\n * Derive parent locale from BCP 47 tag\n *\n * @example\n * getParentLocale('zh-TW') // => 'zh'\n * getParentLocale('en-US') // => 'en'\n * getParentLocale('en') // => undefined\n */\nexport function getParentLocale(locale: Locale): Locale | undefined {\n const dashIndex = locale.indexOf('-')\n if (dashIndex > 0) {\n return locale.substring(0, dashIndex)\n }\n return undefined\n}\n\n/**\n * Build fallback chain for a locale\n *\n * @example\n * // With autoParentLocale enabled (default)\n * buildFallbackChain('zh-TW') // => ['zh-TW', 'zh', 'en']\n * buildFallbackChain('en-US') // => ['en-US', 'en']\n *\n * // With custom fallback chain\n * configure({ fallbackChain: { 'pt-BR': ['pt', 'es', 'en'] } })\n * buildFallbackChain('pt-BR') // => ['pt-BR', 'pt', 'es', 'en']\n */\nexport function buildFallbackChain(locale: Locale): Locale[] {\n const cfg = getConfig()\n\n // Check for custom chain first\n if (cfg.fallbackChain[locale]) {\n return [locale, ...cfg.fallbackChain[locale]]\n }\n\n const chain: Locale[] = [locale]\n\n // Auto-derive parent locales if enabled\n if (cfg.autoParentLocale) {\n let current = locale\n while (true) {\n const parent = getParentLocale(current)\n if (parent && !chain.includes(parent)) {\n chain.push(parent)\n current = parent\n } else {\n break\n }\n }\n }\n\n // Add final fallback if not already in chain\n const finalFallback = cfg.fallbackLocale\n if (finalFallback && !chain.includes(finalFallback)) {\n chain.push(finalFallback)\n }\n\n return chain\n}\n\n/**\n * Emit a missing translation warning\n */\nexport function emitWarning(warning: TranslationWarning): void {\n const cfg = getConfig()\n if (cfg.warnOnMissing && cfg.onMissingTranslation) {\n cfg.onMissingTranslation(warning)\n }\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\nimport { buildFallbackChain, emitWarning } from './config'\n\ninterface ResolveResult {\n template: string\n locale: string\n}\n\nfunction resolveTemplate(translations: Translations): ResolveResult {\n const locale = getLocale()\n const availableLocales = Object.keys(translations)\n const fallbackChain = buildFallbackChain(locale)\n\n // Try each locale in the fallback chain\n for (const tryLocale of fallbackChain) {\n const template = translations[tryLocale]\n if (template) {\n // Warn if we had to fall back\n if (tryLocale !== locale) {\n emitWarning({\n type: 'missing_translation',\n requestedLocale: locale,\n availableLocales,\n fallbackUsed: tryLocale,\n })\n }\n return { template, locale: tryLocale }\n }\n }\n\n // Last resort: use first available translation\n const firstAvailable = Object.entries(translations)[0]\n if (firstAvailable) {\n emitWarning({\n type: 'missing_translation',\n requestedLocale: locale,\n availableLocales,\n fallbackUsed: firstAvailable[0],\n })\n return { template: firstAvailable[1], locale: firstAvailable[0] }\n }\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${availableLocales.join(', ')}`\n )\n}\n\n/**\n * Translate with two languages (shorthand)\n * @param ko - Korean text\n * @param en - English text\n * @param vars - Variables for interpolation\n */\nexport function it(ko: string, en: string, vars?: TranslationVars): string\n\n/**\n * Translate with multiple languages (object syntax)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function it(translations: Translations, vars?: TranslationVars): string\n\nexport function it(\n first: string | Translations,\n second?: string | TranslationVars,\n third?: TranslationVars,\n): string {\n // object syntax: it({ ko: '...', en: '...' }, vars?)\n if (typeof first === 'object') {\n const translations = first\n const vars = second as TranslationVars | undefined\n const { template, locale } = resolveTemplate(translations)\n return interpolate(template, vars, locale)\n }\n\n // shorthand syntax: it('한글', 'English', vars?)\n const ko = first\n const en = second as string\n const vars = third\n\n const translations: Translations = { ko, en }\n const { template, locale } = resolveTemplate(translations)\n return interpolate(template, vars, locale)\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\nimport { buildFallbackChain, emitWarning } from './config'\n\n/**\n * Runtime lookup function for plugin-transformed code.\n * This is called by code that has been processed by @inline-i18n-multi/babel-plugin\n * or @inline-i18n-multi/swc-plugin.\n *\n * @param _hash - Content hash (for caching/debugging, unused at runtime)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function __i18n_lookup(\n _hash: string,\n translations: Translations,\n vars?: TranslationVars\n): string {\n const locale = getLocale()\n const availableLocales = Object.keys(translations)\n const fallbackChain = buildFallbackChain(locale)\n\n // Try each locale in the fallback chain\n for (const tryLocale of fallbackChain) {\n const template = translations[tryLocale]\n if (template) {\n // Warn if we had to fall back\n if (tryLocale !== locale) {\n emitWarning({\n type: 'missing_translation',\n requestedLocale: locale,\n availableLocales,\n fallbackUsed: tryLocale,\n })\n }\n return interpolate(template, vars, tryLocale)\n }\n }\n\n // Last resort: use first available translation\n const firstAvailable = Object.entries(translations)[0]\n if (firstAvailable) {\n emitWarning({\n type: 'missing_translation',\n requestedLocale: locale,\n availableLocales,\n fallbackUsed: firstAvailable[0],\n })\n return interpolate(firstAvailable[1], vars, firstAvailable[0])\n }\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${availableLocales.join(', ')}`\n )\n}\n\n// Register __i18n_lookup globally for plugin transformations\n// This makes it available without explicit import after bundle\nif (typeof globalThis !== 'undefined') {\n (globalThis as Record<string, unknown>).__i18n_lookup = __i18n_lookup\n}\n","import type { Locale, Translations, TranslationVars } from './types'\nimport { it } from './translate'\n\ntype PairFunction = (\n text1: string,\n text2: string,\n vars?: TranslationVars,\n) => string\n\nfunction createPair(lang1: Locale, lang2: Locale): PairFunction {\n return (text1, text2, vars) => {\n const translations: Translations = {\n [lang1]: text1,\n [lang2]: text2,\n }\n return it(translations, vars)\n }\n}\n\n// Korean combinations\nexport const it_ja = createPair('ko', 'ja')\nexport const it_zh = createPair('ko', 'zh')\nexport const it_es = createPair('ko', 'es')\nexport const it_fr = createPair('ko', 'fr')\nexport const it_de = createPair('ko', 'de')\n\n// English combinations\nexport const en_ja = createPair('en', 'ja')\nexport const en_zh = createPair('en', 'zh')\nexport const en_es = createPair('en', 'es')\nexport const en_fr = createPair('en', 'fr')\nexport const en_de = createPair('en', 'de')\n\n// Other combinations\nexport const ja_zh = createPair('ja', 'zh')\nexport const ja_es = createPair('ja', 'es')\nexport const zh_es = createPair('zh', 'es')\n","import { getLocale } from './context'\nimport type { Locale, TranslationVars } from './types'\nimport { interpolate } from './interpolation'\nimport { buildFallbackChain, emitWarning } from './config'\n\n/**\n * Nested dictionary structure for translations\n * @example { greeting: { hello: \"Hello\", goodbye: \"Goodbye\" } }\n */\nexport type Dictionary = {\n [key: string]: string | Dictionary\n}\n\n/**\n * All loaded dictionaries by locale\n */\nexport type Dictionaries = Record<Locale, Dictionary>\n\n/**\n * Plural rules configuration\n */\nexport interface PluralRules {\n zero?: string\n one?: string\n two?: string\n few?: string\n many?: string\n other: string\n}\n\n// Global dictionary storage\nlet dictionaries: Dictionaries = {}\n\n/**\n * Load translations from dictionary objects\n * @param dicts - Dictionary objects keyed by locale\n * @example\n * loadDictionaries({\n * en: { greeting: { hello: \"Hello\" } },\n * ko: { greeting: { hello: \"안녕하세요\" } }\n * })\n */\nexport function loadDictionaries(dicts: Dictionaries): void {\n dictionaries = { ...dictionaries, ...dicts }\n}\n\n/**\n * Load a single locale's dictionary\n * @param locale - Locale code\n * @param dict - Dictionary object\n */\nexport function loadDictionary(locale: Locale, dict: Dictionary): void {\n dictionaries[locale] = { ...dictionaries[locale], ...dict }\n}\n\n/**\n * Clear all loaded dictionaries\n */\nexport function clearDictionaries(): void {\n dictionaries = {}\n}\n\n/**\n * Get a nested value from dictionary using dot notation\n * @param dict - Dictionary object\n * @param key - Dot-separated key path\n */\nfunction getNestedValue(dict: Dictionary, key: string): string | undefined {\n const parts = key.split('.')\n let current: string | Dictionary | undefined = dict\n\n for (const part of parts) {\n if (typeof current !== 'object' || current === null) {\n return undefined\n }\n current = current[part]\n if (current === undefined) {\n return undefined\n }\n }\n\n return typeof current === 'string' ? current : undefined\n}\n\n/**\n * Get plural category using Intl.PluralRules\n */\nfunction getPluralCategory(count: number, locale: Locale): Intl.LDMLPluralRule {\n const rules = new Intl.PluralRules(locale)\n return rules.select(count)\n}\n\n/**\n * Try to find a translation in a dictionary, handling plurals\n */\nfunction findInDictionary(\n dict: Dictionary,\n key: string,\n vars: TranslationVars | undefined,\n locale: Locale\n): string | undefined {\n let template = getNestedValue(dict, key)\n\n // Handle plurals if count is provided\n if (vars && typeof vars.count === 'number') {\n const pluralKey = `${key}_${getPluralCategory(vars.count, locale)}`\n const pluralTemplate = getNestedValue(dict, pluralKey)\n if (pluralTemplate) {\n template = pluralTemplate\n }\n }\n\n return template\n}\n\n/**\n * Translate using key-based lookup (i18n compatible)\n * @param key - Dot-separated translation key\n * @param vars - Variables for interpolation (including 'count' for plurals)\n * @param locale - Override locale (optional)\n * @example\n * t('greeting.hello') // \"Hello\"\n * t('items.count', { count: 5 }) // \"5 items\"\n */\nexport function t(\n key: string,\n vars?: TranslationVars,\n locale?: Locale\n): string {\n const currentLocale = locale ?? getLocale()\n const fallbackChain = buildFallbackChain(currentLocale)\n const availableLocales = Object.keys(dictionaries)\n\n let template: string | undefined\n let usedLocale: Locale | undefined\n\n // Try each locale in the fallback chain\n for (const tryLocale of fallbackChain) {\n const dict = dictionaries[tryLocale]\n if (!dict) continue\n\n const found = findInDictionary(dict, key, vars, tryLocale)\n if (found) {\n template = found\n usedLocale = tryLocale\n break\n }\n }\n\n if (!template) {\n emitWarning({\n type: 'missing_translation',\n key,\n requestedLocale: currentLocale,\n availableLocales,\n })\n return key\n }\n\n // Warn if we used a fallback\n if (usedLocale && usedLocale !== currentLocale) {\n emitWarning({\n type: 'missing_translation',\n key,\n requestedLocale: currentLocale,\n availableLocales,\n fallbackUsed: usedLocale,\n })\n }\n\n return interpolate(template, vars, usedLocale || currentLocale)\n}\n\n/**\n * Check if a translation key exists\n */\nexport function hasTranslation(key: string, locale?: Locale): boolean {\n const currentLocale = locale ?? getLocale()\n const dict = dictionaries[currentLocale]\n return dict ? getNestedValue(dict, key) !== undefined : false\n}\n\n/**\n * Get all loaded locales\n */\nexport function getLoadedLocales(): Locale[] {\n return Object.keys(dictionaries)\n}\n\n/**\n * Get dictionary for a specific locale\n */\nexport function getDictionary(locale: Locale): Dictionary | undefined {\n return dictionaries[locale]\n}\n"]}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { parse, isLiteralElement, isArgumentElement, isPoundElement, isPluralElement, isSelectElement } from '@formatjs/icu-messageformat-parser';
1
+ import { parse, isLiteralElement, isArgumentElement, isPoundElement, isPluralElement, isSelectElement, isNumberElement, isDateElement, isTimeElement } from '@formatjs/icu-messageformat-parser';
2
2
 
3
3
  // src/context.ts
4
4
  var currentLocale = "en";
@@ -8,6 +8,96 @@ function setLocale(locale) {
8
8
  function getLocale() {
9
9
  return currentLocale;
10
10
  }
11
+ var DATE_STYLES = {
12
+ short: { dateStyle: "short" },
13
+ medium: { dateStyle: "medium" },
14
+ long: { dateStyle: "long" },
15
+ full: { dateStyle: "full" }
16
+ };
17
+ var TIME_STYLES = {
18
+ short: { timeStyle: "short" },
19
+ medium: { timeStyle: "medium" },
20
+ long: { timeStyle: "long" },
21
+ full: { timeStyle: "full" }
22
+ };
23
+ var NUMBER_STYLES = {
24
+ decimal: { style: "decimal" },
25
+ percent: { style: "percent" },
26
+ integer: { style: "decimal", maximumFractionDigits: 0 }
27
+ };
28
+ function toDate(value) {
29
+ if (value instanceof Date) {
30
+ return value;
31
+ }
32
+ return new Date(value);
33
+ }
34
+ function formatNumberElement(el, vars, locale) {
35
+ const value = vars[el.value];
36
+ if (value === void 0) {
37
+ return `{${el.value}}`;
38
+ }
39
+ const num = typeof value === "number" ? value : Number(value);
40
+ if (isNaN(num)) {
41
+ return `{${el.value}}`;
42
+ }
43
+ let options = {};
44
+ if (el.style) {
45
+ if (typeof el.style === "string") {
46
+ if (el.style === "currency") {
47
+ options = { style: "currency", currency: "USD" };
48
+ } else if (NUMBER_STYLES[el.style]) {
49
+ options = NUMBER_STYLES[el.style];
50
+ }
51
+ } else if ("parsedOptions" in el.style) {
52
+ options = el.style.parsedOptions;
53
+ }
54
+ }
55
+ try {
56
+ return new Intl.NumberFormat(locale, options).format(num);
57
+ } catch {
58
+ return String(num);
59
+ }
60
+ }
61
+ function formatDateElement(el, vars, locale) {
62
+ const value = vars[el.value];
63
+ if (value === void 0) {
64
+ return `{${el.value}}`;
65
+ }
66
+ let options = {};
67
+ if (el.style) {
68
+ if (typeof el.style === "string") {
69
+ options = DATE_STYLES[el.style] || {};
70
+ } else if ("parsedOptions" in el.style) {
71
+ options = el.style.parsedOptions;
72
+ }
73
+ }
74
+ try {
75
+ const date = toDate(value);
76
+ return new Intl.DateTimeFormat(locale, options).format(date);
77
+ } catch {
78
+ return `{${el.value}}`;
79
+ }
80
+ }
81
+ function formatTimeElement(el, vars, locale) {
82
+ const value = vars[el.value];
83
+ if (value === void 0) {
84
+ return `{${el.value}}`;
85
+ }
86
+ let options = {};
87
+ if (el.style) {
88
+ if (typeof el.style === "string") {
89
+ options = TIME_STYLES[el.style] || {};
90
+ } else if ("parsedOptions" in el.style) {
91
+ options = el.style.parsedOptions;
92
+ }
93
+ }
94
+ try {
95
+ const date = toDate(value);
96
+ return new Intl.DateTimeFormat(locale, options).format(date);
97
+ } catch {
98
+ return `{${el.value}}`;
99
+ }
100
+ }
11
101
  function interpolateICU(template, vars, locale) {
12
102
  const ast = parse(template);
13
103
  return formatElements(ast, vars, locale, null);
@@ -32,6 +122,15 @@ function formatElement(el, vars, locale, currentPluralValue) {
32
122
  if (isSelectElement(el)) {
33
123
  return formatSelect(el, vars, locale);
34
124
  }
125
+ if (isNumberElement(el)) {
126
+ return formatNumberElement(el, vars, locale);
127
+ }
128
+ if (isDateElement(el)) {
129
+ return formatDateElement(el, vars, locale);
130
+ }
131
+ if (isTimeElement(el)) {
132
+ return formatTimeElement(el, vars, locale);
133
+ }
35
134
  return "";
36
135
  }
37
136
  function formatPlural(el, vars, locale) {
@@ -65,7 +164,7 @@ function formatSelect(el, vars, locale) {
65
164
  }
66
165
  return `{${el.value}}`;
67
166
  }
68
- var ICU_PATTERN = /\{[^}]+,\s*(plural|select|selectordinal)\s*,/;
167
+ var ICU_PATTERN = /\{[^}]+,\s*(plural|select|selectordinal|number|date|time)\s*[,}]/;
69
168
  function hasICUPattern(template) {
70
169
  return ICU_PATTERN.test(template);
71
170
  }
@@ -83,15 +182,119 @@ function interpolate(template, vars, locale) {
83
182
  });
84
183
  }
85
184
 
185
+ // src/config.ts
186
+ function defaultWarningHandler(warning) {
187
+ const parts = [`[inline-i18n] Missing translation for locale "${warning.requestedLocale}"`];
188
+ if (warning.key) {
189
+ parts.push(`key: "${warning.key}"`);
190
+ }
191
+ parts.push(`Available: [${warning.availableLocales.join(", ")}]`);
192
+ if (warning.fallbackUsed) {
193
+ parts.push(`Using fallback: "${warning.fallbackUsed}"`);
194
+ }
195
+ console.warn(parts.join(" | "));
196
+ }
197
+ function isDevMode() {
198
+ try {
199
+ if (typeof globalThis !== "undefined" && "process" in globalThis) {
200
+ const proc = globalThis.process;
201
+ return proc?.env?.NODE_ENV !== "production";
202
+ }
203
+ return false;
204
+ } catch {
205
+ return false;
206
+ }
207
+ }
208
+ var defaultConfig = {
209
+ defaultLocale: "en",
210
+ fallbackLocale: "en",
211
+ autoParentLocale: true,
212
+ fallbackChain: {},
213
+ warnOnMissing: isDevMode(),
214
+ onMissingTranslation: defaultWarningHandler
215
+ };
216
+ var config = { ...defaultConfig };
217
+ function configure(options) {
218
+ config = { ...config, ...options };
219
+ }
220
+ function getConfig() {
221
+ return {
222
+ ...defaultConfig,
223
+ ...config
224
+ };
225
+ }
226
+ function resetConfig() {
227
+ config = { ...defaultConfig };
228
+ }
229
+ function getParentLocale(locale) {
230
+ const dashIndex = locale.indexOf("-");
231
+ if (dashIndex > 0) {
232
+ return locale.substring(0, dashIndex);
233
+ }
234
+ return void 0;
235
+ }
236
+ function buildFallbackChain(locale) {
237
+ const cfg = getConfig();
238
+ if (cfg.fallbackChain[locale]) {
239
+ return [locale, ...cfg.fallbackChain[locale]];
240
+ }
241
+ const chain = [locale];
242
+ if (cfg.autoParentLocale) {
243
+ let current = locale;
244
+ while (true) {
245
+ const parent = getParentLocale(current);
246
+ if (parent && !chain.includes(parent)) {
247
+ chain.push(parent);
248
+ current = parent;
249
+ } else {
250
+ break;
251
+ }
252
+ }
253
+ }
254
+ const finalFallback = cfg.fallbackLocale;
255
+ if (finalFallback && !chain.includes(finalFallback)) {
256
+ chain.push(finalFallback);
257
+ }
258
+ return chain;
259
+ }
260
+ function emitWarning(warning) {
261
+ const cfg = getConfig();
262
+ if (cfg.warnOnMissing && cfg.onMissingTranslation) {
263
+ cfg.onMissingTranslation(warning);
264
+ }
265
+ }
266
+
86
267
  // src/translate.ts
87
268
  function resolveTemplate(translations) {
88
269
  const locale = getLocale();
89
- const template = translations[locale];
90
- if (template) return { template, locale };
91
- const fallback = translations.en ?? Object.values(translations)[0];
92
- if (fallback) return { template: fallback, locale: "en" };
270
+ const availableLocales = Object.keys(translations);
271
+ const fallbackChain = buildFallbackChain(locale);
272
+ for (const tryLocale of fallbackChain) {
273
+ const template = translations[tryLocale];
274
+ if (template) {
275
+ if (tryLocale !== locale) {
276
+ emitWarning({
277
+ type: "missing_translation",
278
+ requestedLocale: locale,
279
+ availableLocales,
280
+ fallbackUsed: tryLocale
281
+ });
282
+ }
283
+ return { template, locale: tryLocale };
284
+ }
285
+ }
286
+ const firstAvailable = Object.entries(translations)[0];
287
+ if (firstAvailable) {
288
+ emitWarning({
289
+ type: "missing_translation",
290
+ requestedLocale: locale,
291
+ availableLocales,
292
+ fallbackUsed: firstAvailable[0]
293
+ });
294
+ return { template: firstAvailable[1], locale: firstAvailable[0] };
295
+ }
93
296
  throw new Error(
94
- `No translation found for locale "${locale}". Available: ${Object.keys(translations).join(", ")}`
297
+ `No translation found for locale "${locale}". Available: ${availableLocales.join(", ")}`
95
298
  );
96
299
  }
97
300
  function it(first, second, third) {
@@ -112,16 +315,34 @@ function it(first, second, third) {
112
315
  // src/runtime.ts
113
316
  function __i18n_lookup(_hash, translations, vars) {
114
317
  const locale = getLocale();
115
- const template = translations[locale];
116
- if (template) {
117
- return interpolate(template, vars);
318
+ const availableLocales = Object.keys(translations);
319
+ const fallbackChain = buildFallbackChain(locale);
320
+ for (const tryLocale of fallbackChain) {
321
+ const template = translations[tryLocale];
322
+ if (template) {
323
+ if (tryLocale !== locale) {
324
+ emitWarning({
325
+ type: "missing_translation",
326
+ requestedLocale: locale,
327
+ availableLocales,
328
+ fallbackUsed: tryLocale
329
+ });
330
+ }
331
+ return interpolate(template, vars, tryLocale);
332
+ }
118
333
  }
119
- const fallback = translations.en ?? Object.values(translations)[0];
120
- if (fallback) {
121
- return interpolate(fallback, vars);
334
+ const firstAvailable = Object.entries(translations)[0];
335
+ if (firstAvailable) {
336
+ emitWarning({
337
+ type: "missing_translation",
338
+ requestedLocale: locale,
339
+ availableLocales,
340
+ fallbackUsed: firstAvailable[0]
341
+ });
342
+ return interpolate(firstAvailable[1], vars, firstAvailable[0]);
122
343
  }
123
344
  throw new Error(
124
- `No translation found for locale "${locale}". Available: ${Object.keys(translations).join(", ")}`
345
+ `No translation found for locale "${locale}". Available: ${availableLocales.join(", ")}`
125
346
  );
126
347
  }
127
348
  if (typeof globalThis !== "undefined") {
@@ -181,32 +402,52 @@ function getPluralCategory(count, locale) {
181
402
  const rules = new Intl.PluralRules(locale);
182
403
  return rules.select(count);
183
404
  }
184
- function t(key, vars, locale) {
185
- const currentLocale2 = locale ?? getLocale();
186
- const dict = dictionaries[currentLocale2];
187
- if (!dict) {
188
- console.warn(`[inline-i18n] No dictionary loaded for locale: ${currentLocale2}`);
189
- return key;
190
- }
405
+ function findInDictionary(dict, key, vars, locale) {
191
406
  let template = getNestedValue(dict, key);
192
407
  if (vars && typeof vars.count === "number") {
193
- const pluralKey = `${key}_${getPluralCategory(vars.count, currentLocale2)}`;
408
+ const pluralKey = `${key}_${getPluralCategory(vars.count, locale)}`;
194
409
  const pluralTemplate = getNestedValue(dict, pluralKey);
195
410
  if (pluralTemplate) {
196
411
  template = pluralTemplate;
197
412
  }
198
413
  }
199
- if (!template) {
200
- const fallbackDict = dictionaries["en"];
201
- if (fallbackDict && currentLocale2 !== "en") {
202
- template = getNestedValue(fallbackDict, key);
414
+ return template;
415
+ }
416
+ function t(key, vars, locale) {
417
+ const currentLocale2 = locale ?? getLocale();
418
+ const fallbackChain = buildFallbackChain(currentLocale2);
419
+ const availableLocales = Object.keys(dictionaries);
420
+ let template;
421
+ let usedLocale;
422
+ for (const tryLocale of fallbackChain) {
423
+ const dict = dictionaries[tryLocale];
424
+ if (!dict) continue;
425
+ const found = findInDictionary(dict, key, vars, tryLocale);
426
+ if (found) {
427
+ template = found;
428
+ usedLocale = tryLocale;
429
+ break;
203
430
  }
204
431
  }
205
432
  if (!template) {
206
- console.warn(`[inline-i18n] Missing translation: ${key} (${currentLocale2})`);
433
+ emitWarning({
434
+ type: "missing_translation",
435
+ key,
436
+ requestedLocale: currentLocale2,
437
+ availableLocales
438
+ });
207
439
  return key;
208
440
  }
209
- return interpolate(template, vars, currentLocale2);
441
+ if (usedLocale && usedLocale !== currentLocale2) {
442
+ emitWarning({
443
+ type: "missing_translation",
444
+ key,
445
+ requestedLocale: currentLocale2,
446
+ availableLocales,
447
+ fallbackUsed: usedLocale
448
+ });
449
+ }
450
+ return interpolate(template, vars, usedLocale || currentLocale2);
210
451
  }
211
452
  function hasTranslation(key, locale) {
212
453
  const currentLocale2 = locale ?? getLocale();
@@ -220,6 +461,6 @@ function getDictionary(locale) {
220
461
  return dictionaries[locale];
221
462
  }
222
463
 
223
- export { __i18n_lookup, clearDictionaries, en_de, en_es, en_fr, en_ja, en_zh, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, setLocale, t, zh_es };
464
+ export { __i18n_lookup, clearDictionaries, configure, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, resetConfig, setLocale, t, zh_es };
224
465
  //# sourceMappingURL=index.mjs.map
225
466
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context.ts","../src/icu.ts","../src/interpolation.ts","../src/translate.ts","../src/runtime.ts","../src/pairs.ts","../src/dictionary.ts"],"names":["translations","vars","template","locale","currentLocale"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Locale } from './types'\n\nlet currentLocale: Locale = 'en'\n\nexport function setLocale(locale: Locale): void {\n currentLocale = locale\n}\n\nexport function getLocale(): Locale {\n return currentLocale\n}\n","import {\n parse,\n TYPE,\n type MessageFormatElement,\n type PluralElement,\n type SelectElement,\n isLiteralElement,\n isArgumentElement,\n isPluralElement,\n isSelectElement,\n isPoundElement,\n} from '@formatjs/icu-messageformat-parser'\n\nexport type ICUVars = Record<string, string | number>\n\n/**\n * Parse and format an ICU Message Format string\n */\nexport function interpolateICU(\n template: string,\n vars: ICUVars,\n locale: string\n): string {\n const ast = parse(template)\n return formatElements(ast, vars, locale, null)\n}\n\nfunction formatElements(\n elements: MessageFormatElement[],\n vars: ICUVars,\n locale: string,\n currentPluralValue: number | null\n): string {\n return elements\n .map((el) => formatElement(el, vars, locale, currentPluralValue))\n .join('')\n}\n\nfunction formatElement(\n el: MessageFormatElement,\n vars: ICUVars,\n locale: string,\n currentPluralValue: number | null\n): string {\n if (isLiteralElement(el)) {\n return el.value\n }\n\n if (isArgumentElement(el)) {\n const value = vars[el.value]\n return value !== undefined ? String(value) : `{${el.value}}`\n }\n\n if (isPoundElement(el)) {\n // # is replaced with the current plural value\n return currentPluralValue !== null ? String(currentPluralValue) : '#'\n }\n\n if (isPluralElement(el)) {\n return formatPlural(el, vars, locale)\n }\n\n if (isSelectElement(el)) {\n return formatSelect(el, vars, locale)\n }\n\n // Unsupported types (number, date, time, tag) - return as-is for now\n return ''\n}\n\nfunction formatPlural(\n el: PluralElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n if (typeof value !== 'number') {\n return `{${el.value}}`\n }\n\n const adjustedValue = value - el.offset\n const pluralRules = new Intl.PluralRules(locale, { type: el.pluralType })\n const category = pluralRules.select(adjustedValue)\n\n // Try exact match first (=0, =1, =2, etc.)\n const exactKey = `=${value}`\n if (el.options[exactKey]) {\n return formatElements(el.options[exactKey].value, vars, locale, adjustedValue)\n }\n\n // Then try plural category (zero, one, two, few, many, other)\n if (el.options[category]) {\n return formatElements(el.options[category].value, vars, locale, adjustedValue)\n }\n\n // Fallback to 'other'\n if (el.options.other) {\n return formatElements(el.options.other.value, vars, locale, adjustedValue)\n }\n\n return `{${el.value}}`\n}\n\nfunction formatSelect(\n el: SelectElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n const key = String(value)\n\n // Try exact match\n if (el.options[key]) {\n return formatElements(el.options[key].value, vars, locale, null)\n }\n\n // Fallback to 'other'\n if (el.options.other) {\n return formatElements(el.options.other.value, vars, locale, null)\n }\n\n return `{${el.value}}`\n}\n\n// Pattern to detect ICU format (plural, select, selectordinal)\nexport const ICU_PATTERN = /\\{[^}]+,\\s*(plural|select|selectordinal)\\s*,/\n\n/**\n * Check if a template contains ICU Message Format patterns\n */\nexport function hasICUPattern(template: string): boolean {\n return ICU_PATTERN.test(template)\n}\n","import type { TranslationVars } from './types'\nimport { hasICUPattern, interpolateICU } from './icu'\n\nconst VARIABLE_PATTERN = /\\{(\\w+)\\}/g\n\nexport function interpolate(\n template: string,\n vars?: TranslationVars,\n locale?: string,\n): string {\n if (!vars) return template\n\n // ICU Message Format (plural, select)\n if (hasICUPattern(template)) {\n return interpolateICU(template, vars, locale || 'en')\n }\n\n // Simple variable substitution\n return template.replace(VARIABLE_PATTERN, (_, key) => {\n const value = vars[key]\n return value !== undefined ? String(value) : `{${key}}`\n })\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\n\ninterface ResolveResult {\n template: string\n locale: string\n}\n\nfunction resolveTemplate(translations: Translations): ResolveResult {\n const locale = getLocale()\n\n const template = translations[locale]\n if (template) return { template, locale }\n\n // fallback: en -> first available\n const fallback = translations.en ?? Object.values(translations)[0]\n if (fallback) return { template: fallback, locale: 'en' }\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${Object.keys(translations).join(', ')}`\n )\n}\n\n/**\n * Translate with two languages (shorthand)\n * @param ko - Korean text\n * @param en - English text\n * @param vars - Variables for interpolation\n */\nexport function it(ko: string, en: string, vars?: TranslationVars): string\n\n/**\n * Translate with multiple languages (object syntax)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function it(translations: Translations, vars?: TranslationVars): string\n\nexport function it(\n first: string | Translations,\n second?: string | TranslationVars,\n third?: TranslationVars,\n): string {\n // object syntax: it({ ko: '...', en: '...' }, vars?)\n if (typeof first === 'object') {\n const translations = first\n const vars = second as TranslationVars | undefined\n const { template, locale } = resolveTemplate(translations)\n return interpolate(template, vars, locale)\n }\n\n // shorthand syntax: it('한글', 'English', vars?)\n const ko = first\n const en = second as string\n const vars = third\n\n const translations: Translations = { ko, en }\n const { template, locale } = resolveTemplate(translations)\n return interpolate(template, vars, locale)\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\n\n/**\n * Runtime lookup function for plugin-transformed code.\n * This is called by code that has been processed by @inline-i18n-multi/babel-plugin\n * or @inline-i18n-multi/swc-plugin.\n *\n * @param _hash - Content hash (for caching/debugging, unused at runtime)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function __i18n_lookup(\n _hash: string,\n translations: Translations,\n vars?: TranslationVars\n): string {\n const locale = getLocale()\n\n const template = translations[locale]\n if (template) {\n return interpolate(template, vars)\n }\n\n // fallback: en -> first available\n const fallback = translations.en ?? Object.values(translations)[0]\n if (fallback) {\n return interpolate(fallback, vars)\n }\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${Object.keys(translations).join(', ')}`\n )\n}\n\n// Register __i18n_lookup globally for plugin transformations\n// This makes it available without explicit import after bundle\nif (typeof globalThis !== 'undefined') {\n (globalThis as Record<string, unknown>).__i18n_lookup = __i18n_lookup\n}\n","import type { Locale, Translations, TranslationVars } from './types'\nimport { it } from './translate'\n\ntype PairFunction = (\n text1: string,\n text2: string,\n vars?: TranslationVars,\n) => string\n\nfunction createPair(lang1: Locale, lang2: Locale): PairFunction {\n return (text1, text2, vars) => {\n const translations: Translations = {\n [lang1]: text1,\n [lang2]: text2,\n }\n return it(translations, vars)\n }\n}\n\n// Korean combinations\nexport const it_ja = createPair('ko', 'ja')\nexport const it_zh = createPair('ko', 'zh')\nexport const it_es = createPair('ko', 'es')\nexport const it_fr = createPair('ko', 'fr')\nexport const it_de = createPair('ko', 'de')\n\n// English combinations\nexport const en_ja = createPair('en', 'ja')\nexport const en_zh = createPair('en', 'zh')\nexport const en_es = createPair('en', 'es')\nexport const en_fr = createPair('en', 'fr')\nexport const en_de = createPair('en', 'de')\n\n// Other combinations\nexport const ja_zh = createPair('ja', 'zh')\nexport const ja_es = createPair('ja', 'es')\nexport const zh_es = createPair('zh', 'es')\n","import { getLocale } from './context'\nimport type { Locale, TranslationVars } from './types'\nimport { interpolate } from './interpolation'\n\n/**\n * Nested dictionary structure for translations\n * @example { greeting: { hello: \"Hello\", goodbye: \"Goodbye\" } }\n */\nexport type Dictionary = {\n [key: string]: string | Dictionary\n}\n\n/**\n * All loaded dictionaries by locale\n */\nexport type Dictionaries = Record<Locale, Dictionary>\n\n/**\n * Plural rules configuration\n */\nexport interface PluralRules {\n zero?: string\n one?: string\n two?: string\n few?: string\n many?: string\n other: string\n}\n\n// Global dictionary storage\nlet dictionaries: Dictionaries = {}\n\n/**\n * Load translations from dictionary objects\n * @param dicts - Dictionary objects keyed by locale\n * @example\n * loadDictionaries({\n * en: { greeting: { hello: \"Hello\" } },\n * ko: { greeting: { hello: \"안녕하세요\" } }\n * })\n */\nexport function loadDictionaries(dicts: Dictionaries): void {\n dictionaries = { ...dictionaries, ...dicts }\n}\n\n/**\n * Load a single locale's dictionary\n * @param locale - Locale code\n * @param dict - Dictionary object\n */\nexport function loadDictionary(locale: Locale, dict: Dictionary): void {\n dictionaries[locale] = { ...dictionaries[locale], ...dict }\n}\n\n/**\n * Clear all loaded dictionaries\n */\nexport function clearDictionaries(): void {\n dictionaries = {}\n}\n\n/**\n * Get a nested value from dictionary using dot notation\n * @param dict - Dictionary object\n * @param key - Dot-separated key path\n */\nfunction getNestedValue(dict: Dictionary, key: string): string | undefined {\n const parts = key.split('.')\n let current: string | Dictionary | undefined = dict\n\n for (const part of parts) {\n if (typeof current !== 'object' || current === null) {\n return undefined\n }\n current = current[part]\n if (current === undefined) {\n return undefined\n }\n }\n\n return typeof current === 'string' ? current : undefined\n}\n\n/**\n * Get plural category using Intl.PluralRules\n */\nfunction getPluralCategory(count: number, locale: Locale): Intl.LDMLPluralRule {\n const rules = new Intl.PluralRules(locale)\n return rules.select(count)\n}\n\n/**\n * Translate using key-based lookup (i18n compatible)\n * @param key - Dot-separated translation key\n * @param vars - Variables for interpolation (including 'count' for plurals)\n * @param locale - Override locale (optional)\n * @example\n * t('greeting.hello') // \"Hello\"\n * t('items.count', { count: 5 }) // \"5 items\"\n */\nexport function t(\n key: string,\n vars?: TranslationVars,\n locale?: Locale\n): string {\n const currentLocale = locale ?? getLocale()\n const dict = dictionaries[currentLocale]\n\n if (!dict) {\n console.warn(`[inline-i18n] No dictionary loaded for locale: ${currentLocale}`)\n return key\n }\n\n let template = getNestedValue(dict, key)\n\n // Handle plurals if count is provided\n if (vars && typeof vars.count === 'number') {\n const pluralKey = `${key}_${getPluralCategory(vars.count, currentLocale)}`\n const pluralTemplate = getNestedValue(dict, pluralKey)\n if (pluralTemplate) {\n template = pluralTemplate\n }\n }\n\n if (!template) {\n // Try fallback to English\n const fallbackDict = dictionaries['en']\n if (fallbackDict && currentLocale !== 'en') {\n template = getNestedValue(fallbackDict, key)\n }\n }\n\n if (!template) {\n console.warn(`[inline-i18n] Missing translation: ${key} (${currentLocale})`)\n return key\n }\n\n return interpolate(template, vars, currentLocale)\n}\n\n/**\n * Check if a translation key exists\n */\nexport function hasTranslation(key: string, locale?: Locale): boolean {\n const currentLocale = locale ?? getLocale()\n const dict = dictionaries[currentLocale]\n return dict ? getNestedValue(dict, key) !== undefined : false\n}\n\n/**\n * Get all loaded locales\n */\nexport function getLoadedLocales(): Locale[] {\n return Object.keys(dictionaries)\n}\n\n/**\n * Get dictionary for a specific locale\n */\nexport function getDictionary(locale: Locale): Dictionary | undefined {\n return dictionaries[locale]\n}\n"]}
1
+ {"version":3,"sources":["../src/context.ts","../src/icu.ts","../src/interpolation.ts","../src/config.ts","../src/translate.ts","../src/runtime.ts","../src/pairs.ts","../src/dictionary.ts"],"names":["translations","vars","template","locale","currentLocale"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Locale } from './types'\n\nlet currentLocale: Locale = 'en'\n\nexport function setLocale(locale: Locale): void {\n currentLocale = locale\n}\n\nexport function getLocale(): Locale {\n return currentLocale\n}\n","import {\n parse,\n TYPE,\n type MessageFormatElement,\n type PluralElement,\n type SelectElement,\n type NumberElement,\n type DateElement,\n type TimeElement,\n isLiteralElement,\n isArgumentElement,\n isPluralElement,\n isSelectElement,\n isPoundElement,\n isNumberElement,\n isDateElement,\n isTimeElement,\n} from '@formatjs/icu-messageformat-parser'\n\nexport type ICUVars = Record<string, string | number | Date>\n\n/**\n * Map ICU date style names to Intl.DateTimeFormat options\n */\nconst DATE_STYLES: Record<string, Intl.DateTimeFormatOptions> = {\n short: { dateStyle: 'short' },\n medium: { dateStyle: 'medium' },\n long: { dateStyle: 'long' },\n full: { dateStyle: 'full' },\n}\n\n/**\n * Map ICU time style names to Intl.DateTimeFormat options\n */\nconst TIME_STYLES: Record<string, Intl.DateTimeFormatOptions> = {\n short: { timeStyle: 'short' },\n medium: { timeStyle: 'medium' },\n long: { timeStyle: 'long' },\n full: { timeStyle: 'full' },\n}\n\n/**\n * Map ICU number style names to Intl.NumberFormat options\n */\nconst NUMBER_STYLES: Record<string, Intl.NumberFormatOptions> = {\n decimal: { style: 'decimal' },\n percent: { style: 'percent' },\n integer: { style: 'decimal', maximumFractionDigits: 0 },\n}\n\n/**\n * Convert value to Date\n */\nfunction toDate(value: string | number | Date): Date {\n if (value instanceof Date) {\n return value\n }\n return new Date(value)\n}\n\n/**\n * Format a number element\n */\nfunction formatNumberElement(\n el: NumberElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n if (value === undefined) {\n return `{${el.value}}`\n }\n\n const num = typeof value === 'number' ? value : Number(value)\n if (isNaN(num)) {\n return `{${el.value}}`\n }\n\n let options: Intl.NumberFormatOptions = {}\n\n if (el.style) {\n if (typeof el.style === 'string') {\n // Check for currency format: \"currency\" or specific currency like \"USD\"\n if (el.style === 'currency') {\n options = { style: 'currency', currency: 'USD' }\n } else if (NUMBER_STYLES[el.style]) {\n options = NUMBER_STYLES[el.style]\n }\n } else if ('parsedOptions' in el.style) {\n // NumberSkeleton with parsed options\n options = el.style.parsedOptions as Intl.NumberFormatOptions\n }\n }\n\n try {\n return new Intl.NumberFormat(locale, options).format(num)\n } catch {\n return String(num)\n }\n}\n\n/**\n * Format a date element\n */\nfunction formatDateElement(\n el: DateElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n if (value === undefined) {\n return `{${el.value}}`\n }\n\n let options: Intl.DateTimeFormatOptions = {}\n\n if (el.style) {\n if (typeof el.style === 'string') {\n options = DATE_STYLES[el.style] || {}\n } else if ('parsedOptions' in el.style) {\n // DateTimeSkeleton with parsed options\n options = el.style.parsedOptions as Intl.DateTimeFormatOptions\n }\n }\n\n try {\n const date = toDate(value)\n return new Intl.DateTimeFormat(locale, options).format(date)\n } catch {\n return `{${el.value}}`\n }\n}\n\n/**\n * Format a time element\n */\nfunction formatTimeElement(\n el: TimeElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n if (value === undefined) {\n return `{${el.value}}`\n }\n\n let options: Intl.DateTimeFormatOptions = {}\n\n if (el.style) {\n if (typeof el.style === 'string') {\n options = TIME_STYLES[el.style] || {}\n } else if ('parsedOptions' in el.style) {\n // DateTimeSkeleton with parsed options\n options = el.style.parsedOptions as Intl.DateTimeFormatOptions\n }\n }\n\n try {\n const date = toDate(value)\n return new Intl.DateTimeFormat(locale, options).format(date)\n } catch {\n return `{${el.value}}`\n }\n}\n\n/**\n * Parse and format an ICU Message Format string\n */\nexport function interpolateICU(\n template: string,\n vars: ICUVars,\n locale: string\n): string {\n const ast = parse(template)\n return formatElements(ast, vars, locale, null)\n}\n\nfunction formatElements(\n elements: MessageFormatElement[],\n vars: ICUVars,\n locale: string,\n currentPluralValue: number | null\n): string {\n return elements\n .map((el) => formatElement(el, vars, locale, currentPluralValue))\n .join('')\n}\n\nfunction formatElement(\n el: MessageFormatElement,\n vars: ICUVars,\n locale: string,\n currentPluralValue: number | null\n): string {\n if (isLiteralElement(el)) {\n return el.value\n }\n\n if (isArgumentElement(el)) {\n const value = vars[el.value]\n return value !== undefined ? String(value) : `{${el.value}}`\n }\n\n if (isPoundElement(el)) {\n // # is replaced with the current plural value\n return currentPluralValue !== null ? String(currentPluralValue) : '#'\n }\n\n if (isPluralElement(el)) {\n return formatPlural(el, vars, locale)\n }\n\n if (isSelectElement(el)) {\n return formatSelect(el, vars, locale)\n }\n\n if (isNumberElement(el)) {\n return formatNumberElement(el, vars, locale)\n }\n\n if (isDateElement(el)) {\n return formatDateElement(el, vars, locale)\n }\n\n if (isTimeElement(el)) {\n return formatTimeElement(el, vars, locale)\n }\n\n // Tag elements - not supported yet\n return ''\n}\n\nfunction formatPlural(\n el: PluralElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n if (typeof value !== 'number') {\n return `{${el.value}}`\n }\n\n const adjustedValue = value - el.offset\n const pluralRules = new Intl.PluralRules(locale, { type: el.pluralType })\n const category = pluralRules.select(adjustedValue)\n\n // Try exact match first (=0, =1, =2, etc.)\n const exactKey = `=${value}`\n if (el.options[exactKey]) {\n return formatElements(el.options[exactKey].value, vars, locale, adjustedValue)\n }\n\n // Then try plural category (zero, one, two, few, many, other)\n if (el.options[category]) {\n return formatElements(el.options[category].value, vars, locale, adjustedValue)\n }\n\n // Fallback to 'other'\n if (el.options.other) {\n return formatElements(el.options.other.value, vars, locale, adjustedValue)\n }\n\n return `{${el.value}}`\n}\n\nfunction formatSelect(\n el: SelectElement,\n vars: ICUVars,\n locale: string\n): string {\n const value = vars[el.value]\n const key = String(value)\n\n // Try exact match\n if (el.options[key]) {\n return formatElements(el.options[key].value, vars, locale, null)\n }\n\n // Fallback to 'other'\n if (el.options.other) {\n return formatElements(el.options.other.value, vars, locale, null)\n }\n\n return `{${el.value}}`\n}\n\n// Pattern to detect ICU format (plural, select, selectordinal, number, date, time)\nexport const ICU_PATTERN = /\\{[^}]+,\\s*(plural|select|selectordinal|number|date|time)\\s*[,}]/\n\n/**\n * Check if a template contains ICU Message Format patterns\n */\nexport function hasICUPattern(template: string): boolean {\n return ICU_PATTERN.test(template)\n}\n","import type { TranslationVars } from './types'\nimport { hasICUPattern, interpolateICU } from './icu'\n\nconst VARIABLE_PATTERN = /\\{(\\w+)\\}/g\n\nexport function interpolate(\n template: string,\n vars?: TranslationVars,\n locale?: string,\n): string {\n if (!vars) return template\n\n // ICU Message Format (plural, select)\n if (hasICUPattern(template)) {\n return interpolateICU(template, vars, locale || 'en')\n }\n\n // Simple variable substitution\n return template.replace(VARIABLE_PATTERN, (_, key) => {\n const value = vars[key]\n return value !== undefined ? String(value) : `{${key}}`\n })\n}\n","import type { Config, Locale, TranslationWarning } from './types'\n\n/**\n * Default warning handler - logs to console\n */\nfunction defaultWarningHandler(warning: TranslationWarning): void {\n const parts = [`[inline-i18n] Missing translation for locale \"${warning.requestedLocale}\"`]\n\n if (warning.key) {\n parts.push(`key: \"${warning.key}\"`)\n }\n\n parts.push(`Available: [${warning.availableLocales.join(', ')}]`)\n\n if (warning.fallbackUsed) {\n parts.push(`Using fallback: \"${warning.fallbackUsed}\"`)\n }\n\n console.warn(parts.join(' | '))\n}\n\n/**\n * Check if we're in development mode\n */\nfunction isDevMode(): boolean {\n try {\n // Check for Node.js environment\n if (typeof globalThis !== 'undefined' && 'process' in globalThis) {\n const proc = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process\n return proc?.env?.NODE_ENV !== 'production'\n }\n return false\n } catch {\n return false\n }\n}\n\nconst defaultConfig: Required<Config> = {\n defaultLocale: 'en',\n fallbackLocale: 'en',\n autoParentLocale: true,\n fallbackChain: {},\n warnOnMissing: isDevMode(),\n onMissingTranslation: defaultWarningHandler,\n}\n\nlet config: Config = { ...defaultConfig }\n\n/**\n * Configure inline-i18n-multi settings\n *\n * @example\n * configure({\n * fallbackLocale: 'en',\n * fallbackChain: { 'pt-BR': ['pt', 'es', 'en'] },\n * warnOnMissing: true,\n * })\n */\nexport function configure(options: Partial<Config>): void {\n config = { ...config, ...options }\n}\n\n/**\n * Get current configuration\n */\nexport function getConfig(): Required<Config> {\n return {\n ...defaultConfig,\n ...config,\n }\n}\n\n/**\n * Reset configuration to defaults\n */\nexport function resetConfig(): void {\n config = { ...defaultConfig }\n}\n\n/**\n * Derive parent locale from BCP 47 tag\n *\n * @example\n * getParentLocale('zh-TW') // => 'zh'\n * getParentLocale('en-US') // => 'en'\n * getParentLocale('en') // => undefined\n */\nexport function getParentLocale(locale: Locale): Locale | undefined {\n const dashIndex = locale.indexOf('-')\n if (dashIndex > 0) {\n return locale.substring(0, dashIndex)\n }\n return undefined\n}\n\n/**\n * Build fallback chain for a locale\n *\n * @example\n * // With autoParentLocale enabled (default)\n * buildFallbackChain('zh-TW') // => ['zh-TW', 'zh', 'en']\n * buildFallbackChain('en-US') // => ['en-US', 'en']\n *\n * // With custom fallback chain\n * configure({ fallbackChain: { 'pt-BR': ['pt', 'es', 'en'] } })\n * buildFallbackChain('pt-BR') // => ['pt-BR', 'pt', 'es', 'en']\n */\nexport function buildFallbackChain(locale: Locale): Locale[] {\n const cfg = getConfig()\n\n // Check for custom chain first\n if (cfg.fallbackChain[locale]) {\n return [locale, ...cfg.fallbackChain[locale]]\n }\n\n const chain: Locale[] = [locale]\n\n // Auto-derive parent locales if enabled\n if (cfg.autoParentLocale) {\n let current = locale\n while (true) {\n const parent = getParentLocale(current)\n if (parent && !chain.includes(parent)) {\n chain.push(parent)\n current = parent\n } else {\n break\n }\n }\n }\n\n // Add final fallback if not already in chain\n const finalFallback = cfg.fallbackLocale\n if (finalFallback && !chain.includes(finalFallback)) {\n chain.push(finalFallback)\n }\n\n return chain\n}\n\n/**\n * Emit a missing translation warning\n */\nexport function emitWarning(warning: TranslationWarning): void {\n const cfg = getConfig()\n if (cfg.warnOnMissing && cfg.onMissingTranslation) {\n cfg.onMissingTranslation(warning)\n }\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\nimport { buildFallbackChain, emitWarning } from './config'\n\ninterface ResolveResult {\n template: string\n locale: string\n}\n\nfunction resolveTemplate(translations: Translations): ResolveResult {\n const locale = getLocale()\n const availableLocales = Object.keys(translations)\n const fallbackChain = buildFallbackChain(locale)\n\n // Try each locale in the fallback chain\n for (const tryLocale of fallbackChain) {\n const template = translations[tryLocale]\n if (template) {\n // Warn if we had to fall back\n if (tryLocale !== locale) {\n emitWarning({\n type: 'missing_translation',\n requestedLocale: locale,\n availableLocales,\n fallbackUsed: tryLocale,\n })\n }\n return { template, locale: tryLocale }\n }\n }\n\n // Last resort: use first available translation\n const firstAvailable = Object.entries(translations)[0]\n if (firstAvailable) {\n emitWarning({\n type: 'missing_translation',\n requestedLocale: locale,\n availableLocales,\n fallbackUsed: firstAvailable[0],\n })\n return { template: firstAvailable[1], locale: firstAvailable[0] }\n }\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${availableLocales.join(', ')}`\n )\n}\n\n/**\n * Translate with two languages (shorthand)\n * @param ko - Korean text\n * @param en - English text\n * @param vars - Variables for interpolation\n */\nexport function it(ko: string, en: string, vars?: TranslationVars): string\n\n/**\n * Translate with multiple languages (object syntax)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function it(translations: Translations, vars?: TranslationVars): string\n\nexport function it(\n first: string | Translations,\n second?: string | TranslationVars,\n third?: TranslationVars,\n): string {\n // object syntax: it({ ko: '...', en: '...' }, vars?)\n if (typeof first === 'object') {\n const translations = first\n const vars = second as TranslationVars | undefined\n const { template, locale } = resolveTemplate(translations)\n return interpolate(template, vars, locale)\n }\n\n // shorthand syntax: it('한글', 'English', vars?)\n const ko = first\n const en = second as string\n const vars = third\n\n const translations: Translations = { ko, en }\n const { template, locale } = resolveTemplate(translations)\n return interpolate(template, vars, locale)\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\nimport { buildFallbackChain, emitWarning } from './config'\n\n/**\n * Runtime lookup function for plugin-transformed code.\n * This is called by code that has been processed by @inline-i18n-multi/babel-plugin\n * or @inline-i18n-multi/swc-plugin.\n *\n * @param _hash - Content hash (for caching/debugging, unused at runtime)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function __i18n_lookup(\n _hash: string,\n translations: Translations,\n vars?: TranslationVars\n): string {\n const locale = getLocale()\n const availableLocales = Object.keys(translations)\n const fallbackChain = buildFallbackChain(locale)\n\n // Try each locale in the fallback chain\n for (const tryLocale of fallbackChain) {\n const template = translations[tryLocale]\n if (template) {\n // Warn if we had to fall back\n if (tryLocale !== locale) {\n emitWarning({\n type: 'missing_translation',\n requestedLocale: locale,\n availableLocales,\n fallbackUsed: tryLocale,\n })\n }\n return interpolate(template, vars, tryLocale)\n }\n }\n\n // Last resort: use first available translation\n const firstAvailable = Object.entries(translations)[0]\n if (firstAvailable) {\n emitWarning({\n type: 'missing_translation',\n requestedLocale: locale,\n availableLocales,\n fallbackUsed: firstAvailable[0],\n })\n return interpolate(firstAvailable[1], vars, firstAvailable[0])\n }\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${availableLocales.join(', ')}`\n )\n}\n\n// Register __i18n_lookup globally for plugin transformations\n// This makes it available without explicit import after bundle\nif (typeof globalThis !== 'undefined') {\n (globalThis as Record<string, unknown>).__i18n_lookup = __i18n_lookup\n}\n","import type { Locale, Translations, TranslationVars } from './types'\nimport { it } from './translate'\n\ntype PairFunction = (\n text1: string,\n text2: string,\n vars?: TranslationVars,\n) => string\n\nfunction createPair(lang1: Locale, lang2: Locale): PairFunction {\n return (text1, text2, vars) => {\n const translations: Translations = {\n [lang1]: text1,\n [lang2]: text2,\n }\n return it(translations, vars)\n }\n}\n\n// Korean combinations\nexport const it_ja = createPair('ko', 'ja')\nexport const it_zh = createPair('ko', 'zh')\nexport const it_es = createPair('ko', 'es')\nexport const it_fr = createPair('ko', 'fr')\nexport const it_de = createPair('ko', 'de')\n\n// English combinations\nexport const en_ja = createPair('en', 'ja')\nexport const en_zh = createPair('en', 'zh')\nexport const en_es = createPair('en', 'es')\nexport const en_fr = createPair('en', 'fr')\nexport const en_de = createPair('en', 'de')\n\n// Other combinations\nexport const ja_zh = createPair('ja', 'zh')\nexport const ja_es = createPair('ja', 'es')\nexport const zh_es = createPair('zh', 'es')\n","import { getLocale } from './context'\nimport type { Locale, TranslationVars } from './types'\nimport { interpolate } from './interpolation'\nimport { buildFallbackChain, emitWarning } from './config'\n\n/**\n * Nested dictionary structure for translations\n * @example { greeting: { hello: \"Hello\", goodbye: \"Goodbye\" } }\n */\nexport type Dictionary = {\n [key: string]: string | Dictionary\n}\n\n/**\n * All loaded dictionaries by locale\n */\nexport type Dictionaries = Record<Locale, Dictionary>\n\n/**\n * Plural rules configuration\n */\nexport interface PluralRules {\n zero?: string\n one?: string\n two?: string\n few?: string\n many?: string\n other: string\n}\n\n// Global dictionary storage\nlet dictionaries: Dictionaries = {}\n\n/**\n * Load translations from dictionary objects\n * @param dicts - Dictionary objects keyed by locale\n * @example\n * loadDictionaries({\n * en: { greeting: { hello: \"Hello\" } },\n * ko: { greeting: { hello: \"안녕하세요\" } }\n * })\n */\nexport function loadDictionaries(dicts: Dictionaries): void {\n dictionaries = { ...dictionaries, ...dicts }\n}\n\n/**\n * Load a single locale's dictionary\n * @param locale - Locale code\n * @param dict - Dictionary object\n */\nexport function loadDictionary(locale: Locale, dict: Dictionary): void {\n dictionaries[locale] = { ...dictionaries[locale], ...dict }\n}\n\n/**\n * Clear all loaded dictionaries\n */\nexport function clearDictionaries(): void {\n dictionaries = {}\n}\n\n/**\n * Get a nested value from dictionary using dot notation\n * @param dict - Dictionary object\n * @param key - Dot-separated key path\n */\nfunction getNestedValue(dict: Dictionary, key: string): string | undefined {\n const parts = key.split('.')\n let current: string | Dictionary | undefined = dict\n\n for (const part of parts) {\n if (typeof current !== 'object' || current === null) {\n return undefined\n }\n current = current[part]\n if (current === undefined) {\n return undefined\n }\n }\n\n return typeof current === 'string' ? current : undefined\n}\n\n/**\n * Get plural category using Intl.PluralRules\n */\nfunction getPluralCategory(count: number, locale: Locale): Intl.LDMLPluralRule {\n const rules = new Intl.PluralRules(locale)\n return rules.select(count)\n}\n\n/**\n * Try to find a translation in a dictionary, handling plurals\n */\nfunction findInDictionary(\n dict: Dictionary,\n key: string,\n vars: TranslationVars | undefined,\n locale: Locale\n): string | undefined {\n let template = getNestedValue(dict, key)\n\n // Handle plurals if count is provided\n if (vars && typeof vars.count === 'number') {\n const pluralKey = `${key}_${getPluralCategory(vars.count, locale)}`\n const pluralTemplate = getNestedValue(dict, pluralKey)\n if (pluralTemplate) {\n template = pluralTemplate\n }\n }\n\n return template\n}\n\n/**\n * Translate using key-based lookup (i18n compatible)\n * @param key - Dot-separated translation key\n * @param vars - Variables for interpolation (including 'count' for plurals)\n * @param locale - Override locale (optional)\n * @example\n * t('greeting.hello') // \"Hello\"\n * t('items.count', { count: 5 }) // \"5 items\"\n */\nexport function t(\n key: string,\n vars?: TranslationVars,\n locale?: Locale\n): string {\n const currentLocale = locale ?? getLocale()\n const fallbackChain = buildFallbackChain(currentLocale)\n const availableLocales = Object.keys(dictionaries)\n\n let template: string | undefined\n let usedLocale: Locale | undefined\n\n // Try each locale in the fallback chain\n for (const tryLocale of fallbackChain) {\n const dict = dictionaries[tryLocale]\n if (!dict) continue\n\n const found = findInDictionary(dict, key, vars, tryLocale)\n if (found) {\n template = found\n usedLocale = tryLocale\n break\n }\n }\n\n if (!template) {\n emitWarning({\n type: 'missing_translation',\n key,\n requestedLocale: currentLocale,\n availableLocales,\n })\n return key\n }\n\n // Warn if we used a fallback\n if (usedLocale && usedLocale !== currentLocale) {\n emitWarning({\n type: 'missing_translation',\n key,\n requestedLocale: currentLocale,\n availableLocales,\n fallbackUsed: usedLocale,\n })\n }\n\n return interpolate(template, vars, usedLocale || currentLocale)\n}\n\n/**\n * Check if a translation key exists\n */\nexport function hasTranslation(key: string, locale?: Locale): boolean {\n const currentLocale = locale ?? getLocale()\n const dict = dictionaries[currentLocale]\n return dict ? getNestedValue(dict, key) !== undefined : false\n}\n\n/**\n * Get all loaded locales\n */\nexport function getLoadedLocales(): Locale[] {\n return Object.keys(dictionaries)\n}\n\n/**\n * Get dictionary for a specific locale\n */\nexport function getDictionary(locale: Locale): Dictionary | undefined {\n return dictionaries[locale]\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inline-i18n-multi",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Inline i18n - write translations inline, support multiple languages",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",