inline-i18n-multi 0.10.0 → 0.11.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
@@ -79,6 +79,9 @@ See "Hello" in your app? Just search for "Hello" in your codebase. **Done.**
79
79
  - **Fallback Value** - Custom fallback text when translation is missing (`t('key', { _fallback: 'Default' })`)
80
80
  - **Diff Command** - Compare translations between two locales (`npx inline-i18n diff en ko`)
81
81
  - **Stats Command** - Translation statistics dashboard (`npx inline-i18n stats`)
82
+ - **Locale Display Names** - Get human-readable locale names using `Intl.DisplayNames` (`getLocaleDisplayName('ko', 'en')` → `"Korean"`)
83
+ - **Translation Key Listing** - `getTranslationKeys(locale?, namespace?)` returns all loaded translation keys
84
+ - **Missing Translation Tracker** - Runtime collection of missing translation keys (`trackMissingKeys(true/false)`, `getMissingKeys()`, `clearMissingKeys()`)
82
85
 
83
86
  ---
84
87
 
@@ -814,6 +817,87 @@ Useful for providing user-friendly defaults in UI components where raw keys woul
814
817
 
815
818
  ---
816
819
 
820
+ ## Locale Display Names
821
+
822
+ Get human-readable display names for locale codes using `Intl.DisplayNames`:
823
+
824
+ ```typescript
825
+ import { getLocaleDisplayName, setLocale } from 'inline-i18n-multi'
826
+
827
+ setLocale('en')
828
+
829
+ // Get display name in a specific locale
830
+ getLocaleDisplayName('ko', 'en') // → "Korean"
831
+ getLocaleDisplayName('ja', 'en') // → "Japanese"
832
+ getLocaleDisplayName('zh', 'en') // → "Chinese"
833
+
834
+ // Display name in the target's own locale
835
+ getLocaleDisplayName('ko', 'ko') // → "한국어"
836
+ getLocaleDisplayName('en', 'ja') // → "英語"
837
+
838
+ // Omit displayLocale to use current locale
839
+ setLocale('ko')
840
+ getLocaleDisplayName('en') // → "영어"
841
+ ```
842
+
843
+ ---
844
+
845
+ ## Translation Key Listing
846
+
847
+ Get a list of all loaded translation keys:
848
+
849
+ ```typescript
850
+ import { getTranslationKeys, loadDictionaries } from 'inline-i18n-multi'
851
+
852
+ loadDictionaries({
853
+ en: { greeting: 'Hello', farewell: 'Goodbye' },
854
+ ko: { greeting: '안녕하세요' }
855
+ }, 'common')
856
+
857
+ // Get all keys for a specific locale and namespace
858
+ getTranslationKeys('en', 'common') // → ['greeting', 'farewell']
859
+ getTranslationKeys('ko', 'common') // → ['greeting']
860
+
861
+ // Omit namespace to get keys from all namespaces
862
+ getTranslationKeys('en') // → ['common:greeting', 'common:farewell']
863
+
864
+ // Omit all parameters to use current locale
865
+ getTranslationKeys() // → all keys for current locale
866
+ ```
867
+
868
+ ---
869
+
870
+ ## Missing Translation Tracker
871
+
872
+ Collect missing translation keys at runtime to identify what needs translating:
873
+
874
+ ```typescript
875
+ import { trackMissingKeys, getMissingKeys, clearMissingKeys, t, loadDictionaries } from 'inline-i18n-multi'
876
+
877
+ loadDictionaries({ en: { greeting: 'Hello' } })
878
+
879
+ // Enable missing key tracking
880
+ trackMissingKeys(true)
881
+
882
+ // Use keys that don't exist
883
+ t('missing.key')
884
+ t('another.missing')
885
+
886
+ // Get all missing keys
887
+ getMissingKeys() // → ['missing.key', 'another.missing']
888
+
889
+ // Clear the tracked list
890
+ clearMissingKeys()
891
+ getMissingKeys() // → []
892
+
893
+ // Disable tracking
894
+ trackMissingKeys(false)
895
+ ```
896
+
897
+ Useful for discovering untranslated content during development and testing.
898
+
899
+ ---
900
+
817
901
  ## Configuration
818
902
 
819
903
  Configure global settings for fallback behavior and warnings:
@@ -908,6 +992,11 @@ Available helpers:
908
992
  | `clearICUCache()` | Clear the ICU message AST cache |
909
993
  | `restoreLocale()` | Restore locale from configured persistent storage (cookie or localStorage) |
910
994
  | `createScope(namespace)` | Return a translation function scoped to the given namespace |
995
+ | `getLocaleDisplayName(locale, displayLocale?)` | Get human-readable display name for a locale using `Intl.DisplayNames` |
996
+ | `getTranslationKeys(locale?, namespace?)` | Get all loaded translation keys |
997
+ | `trackMissingKeys(enabled)` | Enable or disable missing translation key tracking |
998
+ | `getMissingKeys()` | Get all tracked missing translation keys |
999
+ | `clearMissingKeys()` | Clear the tracked missing keys list |
911
1000
 
912
1001
  ### Custom Formatters
913
1002
 
package/dist/index.d.mts CHANGED
@@ -233,6 +233,49 @@ declare function getDictionary(locale: Locale, namespace?: string): Dictionary |
233
233
  * Get all loaded namespaces
234
234
  */
235
235
  declare function getLoadedNamespaces(): string[];
236
+ /**
237
+ * Get the display name of a locale using Intl.DisplayNames (v0.11.0)
238
+ * @param locale - Locale code to get display name for (e.g., 'ko', 'ja', 'en-US')
239
+ * @param displayLocale - Locale in which to display the name (defaults to current locale)
240
+ * @returns Display name string (e.g., "Korean", "日本語")
241
+ *
242
+ * @example
243
+ * getLocaleDisplayName('ko', 'en') // → "Korean"
244
+ * getLocaleDisplayName('ko', 'ko') // → "한국어"
245
+ * getLocaleDisplayName('en', 'ja') // → "英語"
246
+ */
247
+ declare function getLocaleDisplayName(locale: Locale, displayLocale?: Locale): string;
248
+ /**
249
+ * Get all translation keys for a locale (v0.11.0)
250
+ * @param locale - Locale to get keys for (defaults to current locale)
251
+ * @param namespace - Optional namespace (returns from all if not specified)
252
+ * @returns Array of translation keys (dot-notation paths)
253
+ *
254
+ * @example
255
+ * getTranslationKeys('en') // → ['greeting.hello', 'greeting.goodbye', 'welcome']
256
+ * getTranslationKeys('en', 'common') // → ['hello', 'goodbye']
257
+ */
258
+ declare function getTranslationKeys(locale?: Locale, namespace?: string): string[];
259
+ /**
260
+ * Enable or disable missing translation tracking (v0.11.0)
261
+ * When enabled, all missing translation keys encountered via t() are recorded.
262
+ * @param enabled - Whether to enable tracking
263
+ *
264
+ * @example
265
+ * trackMissingKeys(true)
266
+ * t('nonexistent.key')
267
+ * getMissingKeys() // → ['nonexistent.key']
268
+ */
269
+ declare function trackMissingKeys(enabled: boolean): void;
270
+ /**
271
+ * Get all missing translation keys encountered since tracking was enabled (v0.11.0)
272
+ * @returns Array of missing keys
273
+ */
274
+ declare function getMissingKeys(): string[];
275
+ /**
276
+ * Clear the list of tracked missing keys (v0.11.0)
277
+ */
278
+ declare function clearMissingKeys(): void;
236
279
 
237
280
  type FullConfig = Required<Omit<Config, 'loader' | 'missingVarHandler' | 'persistLocale'>> & Pick<Config, 'loader' | 'missingVarHandler' | 'persistLocale'>;
238
281
  /**
@@ -344,4 +387,4 @@ interface RichTextSegment {
344
387
  */
345
388
  declare function parseRichText(template: string, componentNames: string[]): RichTextSegment[];
346
389
 
347
- export { type Config, type CustomFormatter, type DebugModeOptions, type DetectLocaleOptions, type DetectSource, type Dictionaries, type Dictionary, type Locale, type PluralRules, type RichTextSegment, type TranslationVars, type TranslationWarning, type Translations, type WarningHandler, __i18n_lookup, clearDictionaries, clearFormatters, clearICUCache, configure, createScope, detectLocale, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLoadedNamespaces, getLocale, hasTranslation, isLoaded, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadAsync, loadDictionaries, loadDictionary, parseRichText, registerFormatter, resetConfig, restoreLocale, setLocale, t, zh_es };
390
+ export { type Config, type CustomFormatter, type DebugModeOptions, type DetectLocaleOptions, type DetectSource, type Dictionaries, type Dictionary, type Locale, type PluralRules, type RichTextSegment, type TranslationVars, type TranslationWarning, type Translations, type WarningHandler, __i18n_lookup, clearDictionaries, clearFormatters, clearICUCache, clearMissingKeys, configure, createScope, detectLocale, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLoadedNamespaces, getLocale, getLocaleDisplayName, getMissingKeys, getTranslationKeys, hasTranslation, isLoaded, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadAsync, loadDictionaries, loadDictionary, parseRichText, registerFormatter, resetConfig, restoreLocale, setLocale, t, trackMissingKeys, zh_es };
package/dist/index.d.ts CHANGED
@@ -233,6 +233,49 @@ declare function getDictionary(locale: Locale, namespace?: string): Dictionary |
233
233
  * Get all loaded namespaces
234
234
  */
235
235
  declare function getLoadedNamespaces(): string[];
236
+ /**
237
+ * Get the display name of a locale using Intl.DisplayNames (v0.11.0)
238
+ * @param locale - Locale code to get display name for (e.g., 'ko', 'ja', 'en-US')
239
+ * @param displayLocale - Locale in which to display the name (defaults to current locale)
240
+ * @returns Display name string (e.g., "Korean", "日本語")
241
+ *
242
+ * @example
243
+ * getLocaleDisplayName('ko', 'en') // → "Korean"
244
+ * getLocaleDisplayName('ko', 'ko') // → "한국어"
245
+ * getLocaleDisplayName('en', 'ja') // → "英語"
246
+ */
247
+ declare function getLocaleDisplayName(locale: Locale, displayLocale?: Locale): string;
248
+ /**
249
+ * Get all translation keys for a locale (v0.11.0)
250
+ * @param locale - Locale to get keys for (defaults to current locale)
251
+ * @param namespace - Optional namespace (returns from all if not specified)
252
+ * @returns Array of translation keys (dot-notation paths)
253
+ *
254
+ * @example
255
+ * getTranslationKeys('en') // → ['greeting.hello', 'greeting.goodbye', 'welcome']
256
+ * getTranslationKeys('en', 'common') // → ['hello', 'goodbye']
257
+ */
258
+ declare function getTranslationKeys(locale?: Locale, namespace?: string): string[];
259
+ /**
260
+ * Enable or disable missing translation tracking (v0.11.0)
261
+ * When enabled, all missing translation keys encountered via t() are recorded.
262
+ * @param enabled - Whether to enable tracking
263
+ *
264
+ * @example
265
+ * trackMissingKeys(true)
266
+ * t('nonexistent.key')
267
+ * getMissingKeys() // → ['nonexistent.key']
268
+ */
269
+ declare function trackMissingKeys(enabled: boolean): void;
270
+ /**
271
+ * Get all missing translation keys encountered since tracking was enabled (v0.11.0)
272
+ * @returns Array of missing keys
273
+ */
274
+ declare function getMissingKeys(): string[];
275
+ /**
276
+ * Clear the list of tracked missing keys (v0.11.0)
277
+ */
278
+ declare function clearMissingKeys(): void;
236
279
 
237
280
  type FullConfig = Required<Omit<Config, 'loader' | 'missingVarHandler' | 'persistLocale'>> & Pick<Config, 'loader' | 'missingVarHandler' | 'persistLocale'>;
238
281
  /**
@@ -344,4 +387,4 @@ interface RichTextSegment {
344
387
  */
345
388
  declare function parseRichText(template: string, componentNames: string[]): RichTextSegment[];
346
389
 
347
- export { type Config, type CustomFormatter, type DebugModeOptions, type DetectLocaleOptions, type DetectSource, type Dictionaries, type Dictionary, type Locale, type PluralRules, type RichTextSegment, type TranslationVars, type TranslationWarning, type Translations, type WarningHandler, __i18n_lookup, clearDictionaries, clearFormatters, clearICUCache, configure, createScope, detectLocale, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLoadedNamespaces, getLocale, hasTranslation, isLoaded, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadAsync, loadDictionaries, loadDictionary, parseRichText, registerFormatter, resetConfig, restoreLocale, setLocale, t, zh_es };
390
+ export { type Config, type CustomFormatter, type DebugModeOptions, type DetectLocaleOptions, type DetectSource, type Dictionaries, type Dictionary, type Locale, type PluralRules, type RichTextSegment, type TranslationVars, type TranslationWarning, type Translations, type WarningHandler, __i18n_lookup, clearDictionaries, clearFormatters, clearICUCache, clearMissingKeys, configure, createScope, detectLocale, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLoadedNamespaces, getLocale, getLocaleDisplayName, getMissingKeys, getTranslationKeys, hasTranslation, isLoaded, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadAsync, loadDictionaries, loadDictionary, parseRichText, registerFormatter, resetConfig, restoreLocale, setLocale, t, trackMissingKeys, zh_es };
package/dist/index.js CHANGED
@@ -919,6 +919,7 @@ function t(key, vars, locale) {
919
919
  }
920
920
  }
921
921
  if (!template) {
922
+ recordMissingKey(key);
922
923
  emitWarning({
923
924
  type: "missing_translation",
924
925
  key,
@@ -987,6 +988,61 @@ function getDictionary(locale, namespace) {
987
988
  function getLoadedNamespaces() {
988
989
  return Object.keys(namespacedDictionaries);
989
990
  }
991
+ function getLocaleDisplayName(locale, displayLocale) {
992
+ const dl = displayLocale ?? getLocale();
993
+ try {
994
+ const displayNames = new Intl.DisplayNames([dl], { type: "language" });
995
+ return displayNames.of(locale) ?? locale;
996
+ } catch {
997
+ return locale;
998
+ }
999
+ }
1000
+ function getTranslationKeys(locale, namespace) {
1001
+ const loc = locale ?? getLocale();
1002
+ const keys = [];
1003
+ function collectKeys(dict, prefix) {
1004
+ for (const [k, v] of Object.entries(dict)) {
1005
+ const fullKey = prefix ? `${prefix}.${k}` : k;
1006
+ if (typeof v === "string") {
1007
+ keys.push(fullKey);
1008
+ } else {
1009
+ collectKeys(v, fullKey);
1010
+ }
1011
+ }
1012
+ }
1013
+ if (namespace) {
1014
+ const dict = namespacedDictionaries[namespace]?.[loc];
1015
+ if (dict) collectKeys(dict, "");
1016
+ } else {
1017
+ for (const [ns, dicts] of Object.entries(namespacedDictionaries)) {
1018
+ const dict = dicts[loc];
1019
+ if (dict) {
1020
+ const prefix = ns === DEFAULT_NAMESPACE ? "" : "";
1021
+ collectKeys(dict, prefix);
1022
+ }
1023
+ }
1024
+ }
1025
+ return keys;
1026
+ }
1027
+ var missingKeys = /* @__PURE__ */ new Set();
1028
+ var trackMissing = false;
1029
+ function trackMissingKeys(enabled) {
1030
+ trackMissing = enabled;
1031
+ if (!enabled) {
1032
+ missingKeys = /* @__PURE__ */ new Set();
1033
+ }
1034
+ }
1035
+ function getMissingKeys() {
1036
+ return Array.from(missingKeys);
1037
+ }
1038
+ function clearMissingKeys() {
1039
+ missingKeys = /* @__PURE__ */ new Set();
1040
+ }
1041
+ function recordMissingKey(key) {
1042
+ if (trackMissing) {
1043
+ missingKeys.add(key);
1044
+ }
1045
+ }
990
1046
 
991
1047
  // src/detect.ts
992
1048
  function matchLocale(candidate, supportedLocales) {
@@ -1122,6 +1178,7 @@ exports.__i18n_lookup = __i18n_lookup;
1122
1178
  exports.clearDictionaries = clearDictionaries;
1123
1179
  exports.clearFormatters = clearFormatters;
1124
1180
  exports.clearICUCache = clearICUCache;
1181
+ exports.clearMissingKeys = clearMissingKeys;
1125
1182
  exports.configure = configure;
1126
1183
  exports.createScope = createScope;
1127
1184
  exports.detectLocale = detectLocale;
@@ -1135,6 +1192,9 @@ exports.getDictionary = getDictionary;
1135
1192
  exports.getLoadedLocales = getLoadedLocales;
1136
1193
  exports.getLoadedNamespaces = getLoadedNamespaces;
1137
1194
  exports.getLocale = getLocale;
1195
+ exports.getLocaleDisplayName = getLocaleDisplayName;
1196
+ exports.getMissingKeys = getMissingKeys;
1197
+ exports.getTranslationKeys = getTranslationKeys;
1138
1198
  exports.hasTranslation = hasTranslation;
1139
1199
  exports.isLoaded = isLoaded;
1140
1200
  exports.it = it;
@@ -1154,6 +1214,7 @@ exports.resetConfig = resetConfig;
1154
1214
  exports.restoreLocale = restoreLocale;
1155
1215
  exports.setLocale = setLocale;
1156
1216
  exports.t = t;
1217
+ exports.trackMissingKeys = trackMissingKeys;
1157
1218
  exports.zh_es = zh_es;
1158
1219
  //# sourceMappingURL=index.js.map
1159
1220
  //# sourceMappingURL=index.js.map