inline-i18n-multi 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,10 +53,12 @@ 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, select, date, number, and time formatting
56
+ - **ICU Message Format** - Plural, select, date, number, time, relative time, and list formatting
57
57
  - **Variable interpolation** - `{name}` syntax for dynamic values
58
58
  - **Locale Fallback Chain** - BCP 47 parent locale support (`zh-TW` → `zh` → `en`)
59
59
  - **Missing Translation Warning** - Development-time diagnostics with customizable handlers
60
+ - **Namespace Support** - Organize translations for large apps (`t('common:greeting')`)
61
+ - **Debug Mode** - Visual indicators for missing/fallback translations
60
62
 
61
63
  ---
62
64
 
@@ -205,6 +207,75 @@ it({
205
207
  - `date`: `short`, `medium`, `long`, `full`
206
208
  - `time`: `short`, `medium`, `long`, `full`
207
209
 
210
+ ### Relative Time Formatting
211
+
212
+ ```typescript
213
+ it({
214
+ en: 'Updated {time, relativeTime}',
215
+ ko: '{time, relativeTime} 업데이트됨'
216
+ }, { time: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000) })
217
+ // → "Updated 3 days ago"
218
+
219
+ // Styles: long (default), short, narrow
220
+ it({ en: '{time, relativeTime, short}' }, { time: pastDate })
221
+ ```
222
+
223
+ ### List Formatting
224
+
225
+ ```typescript
226
+ it({
227
+ en: 'Invited: {names, list}',
228
+ ko: '초대됨: {names, list}'
229
+ }, { names: ['Alice', 'Bob', 'Charlie'] })
230
+ // → "Invited: Alice, Bob, and Charlie"
231
+
232
+ // Types: conjunction (and), disjunction (or), unit
233
+ it({ en: '{options, list, disjunction}' }, { options: ['A', 'B'] })
234
+ // → "A or B"
235
+ ```
236
+
237
+ ---
238
+
239
+ ## Namespace Support
240
+
241
+ Organize translations for large applications:
242
+
243
+ ```typescript
244
+ import { loadDictionaries, t, getLoadedNamespaces, clearDictionaries } from 'inline-i18n-multi'
245
+
246
+ // Load with namespace
247
+ loadDictionaries({
248
+ en: { hello: 'Hello' },
249
+ ko: { hello: '안녕하세요' }
250
+ }, 'common')
251
+
252
+ // Use with namespace prefix
253
+ t('common:hello') // → "Hello"
254
+
255
+ // Without namespace = 'default' (backward compatible)
256
+ loadDictionaries({ en: { greeting: 'Hi' } })
257
+ t('greeting') // → "Hi"
258
+
259
+ getLoadedNamespaces() // → ['common', 'default']
260
+ clearDictionaries('common') // Clear specific namespace
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Debug Mode
266
+
267
+ Visual indicators for debugging:
268
+
269
+ ```typescript
270
+ import { configure, setLocale, it, t } from 'inline-i18n-multi'
271
+
272
+ configure({ debugMode: true })
273
+
274
+ setLocale('fr')
275
+ it({ en: 'Hello', ko: '안녕하세요' }) // → "[fr -> en] Hello"
276
+ t('missing.key') // → "[MISSING: fr] missing.key"
277
+ ```
278
+
208
279
  ---
209
280
 
210
281
  ## Configuration
@@ -280,17 +351,19 @@ Available helpers:
280
351
  | Function | Description |
281
352
  |----------|-------------|
282
353
  | `t(key, vars?, locale?)` | Key-based translation with optional locale override |
283
- | `loadDictionaries(dicts)` | Load translation dictionaries for multiple locales |
284
- | `loadDictionary(locale, dict)` | Load dictionary for a single locale |
285
- | `hasTranslation(key, locale?)` | Check if translation key exists |
354
+ | `loadDictionaries(dicts, namespace?)` | Load translation dictionaries with optional namespace |
355
+ | `loadDictionary(locale, dict, namespace?)` | Load dictionary for a single locale with optional namespace |
356
+ | `hasTranslation(key, locale?)` | Check if translation key exists (supports namespace:key) |
286
357
  | `getLoadedLocales()` | Get array of loaded locale codes |
287
- | `getDictionary(locale)` | Get dictionary for a specific locale |
358
+ | `getLoadedNamespaces()` | Get array of loaded namespace names |
359
+ | `getDictionary(locale, namespace?)` | Get dictionary for a specific locale and namespace |
360
+ | `clearDictionaries(namespace?)` | Clear dictionaries (all or specific namespace) |
288
361
 
289
362
  ### Configuration
290
363
 
291
364
  | Function | Description |
292
365
  |----------|-------------|
293
- | `configure(options)` | Configure global settings (fallback, warnings) |
366
+ | `configure(options)` | Configure global settings (fallback, warnings, debug) |
294
367
  | `getConfig()` | Get current configuration |
295
368
  | `resetConfig()` | Reset configuration to defaults |
296
369
 
@@ -299,7 +372,7 @@ Available helpers:
299
372
  ```typescript
300
373
  type Locale = string
301
374
  type Translations = Record<Locale, string>
302
- type TranslationVars = Record<string, string | number | Date>
375
+ type TranslationVars = Record<string, string | number | Date | string[]>
303
376
 
304
377
  interface Config {
305
378
  defaultLocale: Locale
@@ -308,6 +381,14 @@ interface Config {
308
381
  fallbackChain?: Record<Locale, Locale[]>
309
382
  warnOnMissing?: boolean
310
383
  onMissingTranslation?: WarningHandler
384
+ debugMode?: boolean | DebugModeOptions
385
+ }
386
+
387
+ interface DebugModeOptions {
388
+ showMissingPrefix?: boolean
389
+ showFallbackPrefix?: boolean
390
+ missingPrefixFormat?: (locale: string, key?: string) => string
391
+ fallbackPrefixFormat?: (requestedLocale: string, usedLocale: string, key?: string) => string
311
392
  }
312
393
 
313
394
  interface TranslationWarning {
package/dist/index.d.mts CHANGED
@@ -8,9 +8,10 @@ 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
11
+ * Supports string, number, Date values for ICU formatting
12
+ * Supports string[] for list formatting
12
13
  */
13
- type TranslationVars = Record<string, string | number | Date>;
14
+ type TranslationVars = Record<string, string | number | Date | string[]>;
14
15
  /**
15
16
  * Warning information for missing translations
16
17
  */
@@ -29,6 +30,19 @@ interface TranslationWarning {
29
30
  * Warning handler function type
30
31
  */
31
32
  type WarningHandler = (warning: TranslationWarning) => void;
33
+ /**
34
+ * Debug mode options for visual indicators
35
+ */
36
+ interface DebugModeOptions {
37
+ /** Show visual prefix for missing translations (default: true) */
38
+ showMissingPrefix?: boolean;
39
+ /** Show visual prefix for fallback translations (default: true) */
40
+ showFallbackPrefix?: boolean;
41
+ /** Custom prefix format for missing translations */
42
+ missingPrefixFormat?: (locale: string, key?: string) => string;
43
+ /** Custom prefix format for fallback translations */
44
+ fallbackPrefixFormat?: (requestedLocale: string, usedLocale: string, key?: string) => string;
45
+ }
32
46
  /**
33
47
  * Configuration options
34
48
  */
@@ -45,6 +59,8 @@ interface Config {
45
59
  warnOnMissing?: boolean;
46
60
  /** Custom warning handler */
47
61
  onMissingTranslation?: WarningHandler;
62
+ /** Enable debug mode with visual indicators (default: false) */
63
+ debugMode?: boolean | DebugModeOptions;
48
64
  }
49
65
 
50
66
  /**
@@ -115,45 +131,65 @@ interface PluralRules {
115
131
  /**
116
132
  * Load translations from dictionary objects
117
133
  * @param dicts - Dictionary objects keyed by locale
134
+ * @param namespace - Optional namespace (defaults to 'default')
118
135
  * @example
136
+ * // Without namespace (backward compatible)
119
137
  * loadDictionaries({
120
138
  * en: { greeting: { hello: "Hello" } },
121
139
  * ko: { greeting: { hello: "안녕하세요" } }
122
140
  * })
141
+ *
142
+ * // With namespace
143
+ * loadDictionaries({
144
+ * en: { hello: "Hello" },
145
+ * ko: { hello: "안녕하세요" }
146
+ * }, 'common')
123
147
  */
124
- declare function loadDictionaries(dicts: Dictionaries): void;
148
+ declare function loadDictionaries(dicts: Dictionaries, namespace?: string): void;
125
149
  /**
126
150
  * Load a single locale's dictionary
127
151
  * @param locale - Locale code
128
152
  * @param dict - Dictionary object
153
+ * @param namespace - Optional namespace (defaults to 'default')
129
154
  */
130
- declare function loadDictionary(locale: Locale, dict: Dictionary): void;
155
+ declare function loadDictionary(locale: Locale, dict: Dictionary, namespace?: string): void;
131
156
  /**
132
- * Clear all loaded dictionaries
157
+ * Clear loaded dictionaries
158
+ * @param namespace - Optional namespace to clear (clears all if not specified)
133
159
  */
134
- declare function clearDictionaries(): void;
160
+ declare function clearDictionaries(namespace?: string): void;
135
161
  /**
136
162
  * Translate using key-based lookup (i18n compatible)
137
- * @param key - Dot-separated translation key
163
+ * @param key - Dot-separated translation key, optionally prefixed with namespace
138
164
  * @param vars - Variables for interpolation (including 'count' for plurals)
139
165
  * @param locale - Override locale (optional)
140
166
  * @example
141
- * t('greeting.hello') // "Hello"
167
+ * t('greeting.hello') // Uses default namespace
168
+ * t('common:greeting.hello') // Uses 'common' namespace
142
169
  * t('items.count', { count: 5 }) // "5 items"
143
170
  */
144
171
  declare function t(key: string, vars?: TranslationVars, locale?: Locale): string;
145
172
  /**
146
173
  * Check if a translation key exists
174
+ * @param key - Translation key (may include namespace prefix)
175
+ * @param locale - Optional locale to check
147
176
  */
148
177
  declare function hasTranslation(key: string, locale?: Locale): boolean;
149
178
  /**
150
179
  * Get all loaded locales
180
+ * @param namespace - Optional namespace (returns from all if not specified)
151
181
  */
152
- declare function getLoadedLocales(): Locale[];
182
+ declare function getLoadedLocales(namespace?: string): Locale[];
153
183
  /**
154
184
  * Get dictionary for a specific locale
185
+ * @param locale - Locale code
186
+ * @param namespace - Optional namespace (defaults to 'default')
187
+ */
188
+ declare function getDictionary(locale: Locale, namespace?: string): Dictionary | undefined;
189
+ /**
190
+ * Get all loaded namespaces
155
191
  */
156
- declare function getDictionary(locale: Locale): Dictionary | undefined;
192
+ declare function getLoadedNamespaces(): string[];
157
193
 
158
194
  /**
159
195
  * Configure inline-i18n-multi settings
@@ -175,4 +211,4 @@ declare function getConfig(): Required<Config>;
175
211
  */
176
212
  declare function resetConfig(): void;
177
213
 
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 };
214
+ export { type Config, type DebugModeOptions, 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, getLoadedNamespaces, 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
@@ -8,9 +8,10 @@ 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
11
+ * Supports string, number, Date values for ICU formatting
12
+ * Supports string[] for list formatting
12
13
  */
13
- type TranslationVars = Record<string, string | number | Date>;
14
+ type TranslationVars = Record<string, string | number | Date | string[]>;
14
15
  /**
15
16
  * Warning information for missing translations
16
17
  */
@@ -29,6 +30,19 @@ interface TranslationWarning {
29
30
  * Warning handler function type
30
31
  */
31
32
  type WarningHandler = (warning: TranslationWarning) => void;
33
+ /**
34
+ * Debug mode options for visual indicators
35
+ */
36
+ interface DebugModeOptions {
37
+ /** Show visual prefix for missing translations (default: true) */
38
+ showMissingPrefix?: boolean;
39
+ /** Show visual prefix for fallback translations (default: true) */
40
+ showFallbackPrefix?: boolean;
41
+ /** Custom prefix format for missing translations */
42
+ missingPrefixFormat?: (locale: string, key?: string) => string;
43
+ /** Custom prefix format for fallback translations */
44
+ fallbackPrefixFormat?: (requestedLocale: string, usedLocale: string, key?: string) => string;
45
+ }
32
46
  /**
33
47
  * Configuration options
34
48
  */
@@ -45,6 +59,8 @@ interface Config {
45
59
  warnOnMissing?: boolean;
46
60
  /** Custom warning handler */
47
61
  onMissingTranslation?: WarningHandler;
62
+ /** Enable debug mode with visual indicators (default: false) */
63
+ debugMode?: boolean | DebugModeOptions;
48
64
  }
49
65
 
50
66
  /**
@@ -115,45 +131,65 @@ interface PluralRules {
115
131
  /**
116
132
  * Load translations from dictionary objects
117
133
  * @param dicts - Dictionary objects keyed by locale
134
+ * @param namespace - Optional namespace (defaults to 'default')
118
135
  * @example
136
+ * // Without namespace (backward compatible)
119
137
  * loadDictionaries({
120
138
  * en: { greeting: { hello: "Hello" } },
121
139
  * ko: { greeting: { hello: "안녕하세요" } }
122
140
  * })
141
+ *
142
+ * // With namespace
143
+ * loadDictionaries({
144
+ * en: { hello: "Hello" },
145
+ * ko: { hello: "안녕하세요" }
146
+ * }, 'common')
123
147
  */
124
- declare function loadDictionaries(dicts: Dictionaries): void;
148
+ declare function loadDictionaries(dicts: Dictionaries, namespace?: string): void;
125
149
  /**
126
150
  * Load a single locale's dictionary
127
151
  * @param locale - Locale code
128
152
  * @param dict - Dictionary object
153
+ * @param namespace - Optional namespace (defaults to 'default')
129
154
  */
130
- declare function loadDictionary(locale: Locale, dict: Dictionary): void;
155
+ declare function loadDictionary(locale: Locale, dict: Dictionary, namespace?: string): void;
131
156
  /**
132
- * Clear all loaded dictionaries
157
+ * Clear loaded dictionaries
158
+ * @param namespace - Optional namespace to clear (clears all if not specified)
133
159
  */
134
- declare function clearDictionaries(): void;
160
+ declare function clearDictionaries(namespace?: string): void;
135
161
  /**
136
162
  * Translate using key-based lookup (i18n compatible)
137
- * @param key - Dot-separated translation key
163
+ * @param key - Dot-separated translation key, optionally prefixed with namespace
138
164
  * @param vars - Variables for interpolation (including 'count' for plurals)
139
165
  * @param locale - Override locale (optional)
140
166
  * @example
141
- * t('greeting.hello') // "Hello"
167
+ * t('greeting.hello') // Uses default namespace
168
+ * t('common:greeting.hello') // Uses 'common' namespace
142
169
  * t('items.count', { count: 5 }) // "5 items"
143
170
  */
144
171
  declare function t(key: string, vars?: TranslationVars, locale?: Locale): string;
145
172
  /**
146
173
  * Check if a translation key exists
174
+ * @param key - Translation key (may include namespace prefix)
175
+ * @param locale - Optional locale to check
147
176
  */
148
177
  declare function hasTranslation(key: string, locale?: Locale): boolean;
149
178
  /**
150
179
  * Get all loaded locales
180
+ * @param namespace - Optional namespace (returns from all if not specified)
151
181
  */
152
- declare function getLoadedLocales(): Locale[];
182
+ declare function getLoadedLocales(namespace?: string): Locale[];
153
183
  /**
154
184
  * Get dictionary for a specific locale
185
+ * @param locale - Locale code
186
+ * @param namespace - Optional namespace (defaults to 'default')
187
+ */
188
+ declare function getDictionary(locale: Locale, namespace?: string): Dictionary | undefined;
189
+ /**
190
+ * Get all loaded namespaces
155
191
  */
156
- declare function getDictionary(locale: Locale): Dictionary | undefined;
192
+ declare function getLoadedNamespaces(): string[];
157
193
 
158
194
  /**
159
195
  * Configure inline-i18n-multi settings
@@ -175,4 +211,4 @@ declare function getConfig(): Required<Config>;
175
211
  */
176
212
  declare function resetConfig(): void;
177
213
 
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 };
214
+ export { type Config, type DebugModeOptions, 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, getLoadedNamespaces, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, resetConfig, setLocale, t, zh_es };