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 +81 -2
- package/dist/index.d.mts +52 -3
- package/dist/index.d.ts +52 -3
- package/dist/index.js +271 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +270 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
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: ${
|
|
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
|
|
118
|
-
|
|
119
|
-
|
|
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
|
|
122
|
-
if (
|
|
123
|
-
|
|
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: ${
|
|
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
|
|
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,
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
-
|
|
435
|
+
emitWarning({
|
|
436
|
+
type: "missing_translation",
|
|
437
|
+
key,
|
|
438
|
+
requestedLocale: currentLocale2,
|
|
439
|
+
availableLocales
|
|
440
|
+
});
|
|
209
441
|
return key;
|
|
210
442
|
}
|
|
211
|
-
|
|
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":";;;;;AAEA,IAAI,aAAA,GAAwB,IAAA;AAErB,SAAS,UAAU,MAAA,EAAsB;AAC9C,EAAA,aAAA,GAAgB,MAAA;AAClB;AAEO,SAAS,SAAA,GAAoB;AAClC,EAAA,OAAO,aAAA;AACT;ACQO,SAAS,cAAA,CACd,QAAA,EACA,IAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAM,GAAA,GAAMA,6BAAM,QAAQ,CAAA;AAC1B,EAAA,OAAO,cAAA,CAAe,GAAA,EAAK,IAAA,EAAM,MAAA,EAAQ,IAAI,CAAA;AAC/C;AAEA,SAAS,cAAA,CACP,QAAA,EACA,IAAA,EACA,MAAA,EACA,kBAAA,EACQ;AACR,EAAA,OAAO,QAAA,CACJ,GAAA,CAAI,CAAC,EAAA,KAAO,aAAA,CAAc,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,kBAAkB,CAAC,CAAA,CAC/D,IAAA,CAAK,EAAE,CAAA;AACZ;AAEA,SAAS,aAAA,CACP,EAAA,EACA,IAAA,EACA,MAAA,EACA,kBAAA,EACQ;AACR,EAAA,IAAIC,uCAAA,CAAiB,EAAE,CAAA,EAAG;AACxB,IAAA,OAAO,EAAA,CAAG,KAAA;AAAA,EACZ;AAEA,EAAA,IAAIC,wCAAA,CAAkB,EAAE,CAAA,EAAG;AACzB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,EAAA,CAAG,KAAK,CAAA;AAC3B,IAAA,OAAO,UAAU,MAAA,GAAY,MAAA,CAAO,KAAK,CAAA,GAAI,CAAA,CAAA,EAAI,GAAG,KAAK,CAAA,CAAA,CAAA;AAAA,EAC3D;AAEA,EAAA,IAAIC,qCAAA,CAAe,EAAE,CAAA,EAAG;AAEtB,IAAA,OAAO,kBAAA,KAAuB,IAAA,GAAO,MAAA,CAAO,kBAAkB,CAAA,GAAI,GAAA;AAAA,EACpE;AAEA,EAAA,IAAIC,sCAAA,CAAgB,EAAE,CAAA,EAAG;AACvB,IAAA,OAAO,YAAA,CAAa,EAAA,EAAI,IAAA,EAAM,MAAM,CAAA;AAAA,EACtC;AAEA,EAAA,IAAIC,sCAAA,CAAgB,EAAE,CAAA,EAAG;AACvB,IAAA,OAAO,YAAA,CAAa,EAAA,EAAI,IAAA,EAAM,MAAM,CAAA;AAAA,EACtC;AAGA,EAAA,OAAO,EAAA;AACT;AAEA,SAAS,YAAA,CACP,EAAA,EACA,IAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,EAAA,CAAG,KAAK,CAAA;AAC3B,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,CAAA,CAAA,EAAI,GAAG,KAAK,CAAA,CAAA,CAAA;AAAA,EACrB;AAEA,EAAA,MAAM,aAAA,GAAgB,QAAQ,EAAA,CAAG,MAAA;AACjC,EAAA,MAAM,WAAA,GAAc,IAAI,IAAA,CAAK,WAAA,CAAY,QAAQ,EAAE,IAAA,EAAM,EAAA,CAAG,UAAA,EAAY,CAAA;AACxE,EAAA,MAAM,QAAA,GAAW,WAAA,CAAY,MAAA,CAAO,aAAa,CAAA;AAGjD,EAAA,MAAM,QAAA,GAAW,IAAI,KAAK,CAAA,CAAA;AAC1B,EAAA,IAAI,EAAA,CAAG,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACxB,IAAA,OAAO,cAAA,CAAe,GAAG,OAAA,CAAQ,QAAQ,EAAE,KAAA,EAAO,IAAA,EAAM,QAAQ,aAAa,CAAA;AAAA,EAC/E;AAGA,EAAA,IAAI,EAAA,CAAG,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACxB,IAAA,OAAO,cAAA,CAAe,GAAG,OAAA,CAAQ,QAAQ,EAAE,KAAA,EAAO,IAAA,EAAM,QAAQ,aAAa,CAAA;AAAA,EAC/E;AAGA,EAAA,IAAI,EAAA,CAAG,QAAQ,KAAA,EAAO;AACpB,IAAA,OAAO,eAAe,EAAA,CAAG,OAAA,CAAQ,MAAM,KAAA,EAAO,IAAA,EAAM,QAAQ,aAAa,CAAA;AAAA,EAC3E;AAEA,EAAA,OAAO,CAAA,CAAA,EAAI,GAAG,KAAK,CAAA,CAAA,CAAA;AACrB;AAEA,SAAS,YAAA,CACP,EAAA,EACA,IAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,EAAA,CAAG,KAAK,CAAA;AAC3B,EAAA,MAAM,GAAA,GAAM,OAAO,KAAK,CAAA;AAGxB,EAAA,IAAI,EAAA,CAAG,OAAA,CAAQ,GAAG,CAAA,EAAG;AACnB,IAAA,OAAO,cAAA,CAAe,GAAG,OAAA,CAAQ,GAAG,EAAE,KAAA,EAAO,IAAA,EAAM,QAAQ,IAAI,CAAA;AAAA,EACjE;AAGA,EAAA,IAAI,EAAA,CAAG,QAAQ,KAAA,EAAO;AACpB,IAAA,OAAO,eAAe,EAAA,CAAG,OAAA,CAAQ,MAAM,KAAA,EAAO,IAAA,EAAM,QAAQ,IAAI,CAAA;AAAA,EAClE;AAEA,EAAA,OAAO,CAAA,CAAA,EAAI,GAAG,KAAK,CAAA,CAAA,CAAA;AACrB;AAGO,IAAM,WAAA,GAAc,8CAAA;AAKpB,SAAS,cAAc,QAAA,EAA2B;AACvD,EAAA,OAAO,WAAA,CAAY,KAAK,QAAQ,CAAA;AAClC;;;ACjIA,IAAM,gBAAA,GAAmB,YAAA;AAElB,SAAS,WAAA,CACd,QAAA,EACA,IAAA,EACA,MAAA,EACQ;AACR,EAAA,IAAI,CAAC,MAAM,OAAO,QAAA;AAGlB,EAAA,IAAI,aAAA,CAAc,QAAQ,CAAA,EAAG;AAC3B,IAAA,OAAO,cAAA,CAAe,QAAA,EAAU,IAAA,EAAM,MAAA,IAAU,IAAI,CAAA;AAAA,EACtD;AAGA,EAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,gBAAA,EAAkB,CAAC,GAAG,GAAA,KAAQ;AACpD,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAG,CAAA;AACtB,IAAA,OAAO,UAAU,MAAA,GAAY,MAAA,CAAO,KAAK,CAAA,GAAI,IAAI,GAAG,CAAA,CAAA,CAAA;AAAA,EACtD,CAAC,CAAA;AACH;;;ACbA,SAAS,gBAAgB,YAAA,EAA2C;AAClE,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA,MAAM,QAAA,GAAW,aAAa,MAAM,CAAA;AACpC,EAAA,IAAI,QAAA,EAAU,OAAO,EAAE,QAAA,EAAU,MAAA,EAAO;AAGxC,EAAA,MAAM,WAAW,YAAA,CAAa,EAAA,IAAM,OAAO,MAAA,CAAO,YAAY,EAAE,CAAC,CAAA;AACjE,EAAA,IAAI,UAAU,OAAO,EAAE,QAAA,EAAU,QAAA,EAAU,QAAQ,IAAA,EAAK;AAExD,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,CAAA,iCAAA,EAAoC,MAAM,CAAA,cAAA,EAAiB,MAAA,CAAO,KAAK,YAAY,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,GACjG;AACF;AAiBO,SAAS,EAAA,CACd,KAAA,EACA,MAAA,EACA,KAAA,EACQ;AAER,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,MAAMC,aAAAA,GAAe,KAAA;AACrB,IAAA,MAAMC,KAAAA,GAAO,MAAA;AACb,IAAA,MAAM,EAAE,QAAA,EAAAC,SAAAA,EAAU,QAAAC,OAAAA,EAAO,GAAI,gBAAgBH,aAAY,CAAA;AACzD,IAAA,OAAO,WAAA,CAAYE,SAAAA,EAAUD,KAAAA,EAAME,OAAM,CAAA;AAAA,EAC3C;AAGA,EAAA,MAAM,EAAA,GAAK,KAAA;AACX,EAAA,MAAM,EAAA,GAAK,MAAA;AACX,EAAA,MAAM,IAAA,GAAO,KAAA;AAEb,EAAA,MAAM,YAAA,GAA6B,EAAE,EAAA,EAAI,EAAA,EAAG;AAC5C,EAAA,MAAM,EAAE,QAAA,EAAU,MAAA,EAAO,GAAI,gBAAgB,YAAY,CAAA;AACzD,EAAA,OAAO,WAAA,CAAY,QAAA,EAAU,IAAA,EAAM,MAAM,CAAA;AAC3C;;;AC/CO,SAAS,aAAA,CACd,KAAA,EACA,YAAA,EACA,IAAA,EACQ;AACR,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA,MAAM,QAAA,GAAW,aAAa,MAAM,CAAA;AACpC,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,OAAO,WAAA,CAAY,UAAU,IAAI,CAAA;AAAA,EACnC;AAGA,EAAA,MAAM,WAAW,YAAA,CAAa,EAAA,IAAM,OAAO,MAAA,CAAO,YAAY,EAAE,CAAC,CAAA;AACjE,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,OAAO,WAAA,CAAY,UAAU,IAAI,CAAA;AAAA,EACnC;AAEA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,CAAA,iCAAA,EAAoC,MAAM,CAAA,cAAA,EAAiB,MAAA,CAAO,KAAK,YAAY,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,GACjG;AACF;AAIA,IAAI,OAAO,eAAe,WAAA,EAAa;AACrC,EAAC,WAAuC,aAAA,GAAgB,aAAA;AAC1D;;;AC/BA,SAAS,UAAA,CAAW,OAAe,KAAA,EAA6B;AAC9D,EAAA,OAAO,CAAC,KAAA,EAAO,KAAA,EAAO,IAAA,KAAS;AAC7B,IAAA,MAAM,YAAA,GAA6B;AAAA,MACjC,CAAC,KAAK,GAAG,KAAA;AAAA,MACT,CAAC,KAAK,GAAG;AAAA,KACX;AACA,IAAA,OAAO,EAAA,CAAG,cAAc,IAAI,CAAA;AAAA,EAC9B,CAAA;AACF;AAGO,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AAGnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AAGnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;;;ACN1C,IAAI,eAA6B,EAAC;AAW3B,SAAS,iBAAiB,KAAA,EAA2B;AAC1D,EAAA,YAAA,GAAe,EAAE,GAAG,YAAA,EAAc,GAAG,KAAA,EAAM;AAC7C;AAOO,SAAS,cAAA,CAAe,QAAgB,IAAA,EAAwB;AACrE,EAAA,YAAA,CAAa,MAAM,IAAI,EAAE,GAAG,aAAa,MAAM,CAAA,EAAG,GAAG,IAAA,EAAK;AAC5D;AAKO,SAAS,iBAAA,GAA0B;AACxC,EAAA,YAAA,GAAe,EAAC;AAClB;AAOA,SAAS,cAAA,CAAe,MAAkB,GAAA,EAAiC;AACzE,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AAC3B,EAAA,IAAI,OAAA,GAA2C,IAAA;AAE/C,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,EAAM;AACnD,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAA,GAAU,QAAQ,IAAI,CAAA;AACtB,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,OAAO,OAAA,KAAY,QAAA,GAAW,OAAA,GAAU,MAAA;AACjD;AAKA,SAAS,iBAAA,CAAkB,OAAe,MAAA,EAAqC;AAC7E,EAAA,MAAM,KAAA,GAAQ,IAAI,IAAA,CAAK,WAAA,CAAY,MAAM,CAAA;AACzC,EAAA,OAAO,KAAA,CAAM,OAAO,KAAK,CAAA;AAC3B;AAWO,SAAS,CAAA,CACd,GAAA,EACA,IAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAMC,cAAAA,GAAgB,UAAU,SAAA,EAAU;AAC1C,EAAA,MAAM,IAAA,GAAO,aAAaA,cAAa,CAAA;AAEvC,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,+CAAA,EAAkDA,cAAa,CAAA,CAAE,CAAA;AAC9E,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,IAAI,QAAA,GAAW,cAAA,CAAe,IAAA,EAAM,GAAG,CAAA;AAGvC,EAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,CAAK,KAAA,KAAU,QAAA,EAAU;AAC1C,IAAA,MAAM,SAAA,GAAY,GAAG,GAAG,CAAA,CAAA,EAAI,kBAAkB,IAAA,CAAK,KAAA,EAAOA,cAAa,CAAC,CAAA,CAAA;AACxE,IAAA,MAAM,cAAA,GAAiB,cAAA,CAAe,IAAA,EAAM,SAAS,CAAA;AACrD,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,QAAA,GAAW,cAAA;AAAA,IACb;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,QAAA,EAAU;AAEb,IAAA,MAAM,YAAA,GAAe,aAAa,IAAI,CAAA;AACtC,IAAA,IAAI,YAAA,IAAgBA,mBAAkB,IAAA,EAAM;AAC1C,MAAA,QAAA,GAAW,cAAA,CAAe,cAAc,GAAG,CAAA;AAAA,IAC7C;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,mCAAA,EAAsC,GAAG,CAAA,EAAA,EAAKA,cAAa,CAAA,CAAA,CAAG,CAAA;AAC3E,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,OAAO,WAAA,CAAY,QAAA,EAAU,IAAA,EAAMA,cAAa,CAAA;AAClD;AAKO,SAAS,cAAA,CAAe,KAAa,MAAA,EAA0B;AACpE,EAAA,MAAMA,cAAAA,GAAgB,UAAU,SAAA,EAAU;AAC1C,EAAA,MAAM,IAAA,GAAO,aAAaA,cAAa,CAAA;AACvC,EAAA,OAAO,IAAA,GAAO,cAAA,CAAe,IAAA,EAAM,GAAG,MAAM,MAAA,GAAY,KAAA;AAC1D;AAKO,SAAS,gBAAA,GAA6B;AAC3C,EAAA,OAAO,MAAA,CAAO,KAAK,YAAY,CAAA;AACjC;AAKO,SAAS,cAAc,MAAA,EAAwC;AACpE,EAAA,OAAO,aAAa,MAAM,CAAA;AAC5B","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
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
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: ${
|
|
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
|
|
116
|
-
|
|
117
|
-
|
|
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
|
|
120
|
-
if (
|
|
121
|
-
|
|
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: ${
|
|
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
|
|
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,
|
|
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
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
-
|
|
433
|
+
emitWarning({
|
|
434
|
+
type: "missing_translation",
|
|
435
|
+
key,
|
|
436
|
+
requestedLocale: currentLocale2,
|
|
437
|
+
availableLocales
|
|
438
|
+
});
|
|
207
439
|
return key;
|
|
208
440
|
}
|
|
209
|
-
|
|
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
|
package/dist/index.mjs.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":["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"]}
|