@object-ui/i18n 17.3.0 → 17.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +1929 -1
  2. package/README.md +41 -12
  3. package/dist/i18n.d.ts +1 -1
  4. package/dist/i18n.js +1 -2
  5. package/dist/index.d.ts +23 -21
  6. package/dist/index.js +31 -21
  7. package/dist/locales/ar.d.ts +638 -369
  8. package/dist/locales/ar.js +744 -424
  9. package/dist/locales/de.d.ts +638 -369
  10. package/dist/locales/de.js +759 -446
  11. package/dist/locales/en.d.ts +673 -404
  12. package/dist/locales/en.js +899 -406
  13. package/dist/locales/es.d.ts +638 -369
  14. package/dist/locales/es.js +739 -427
  15. package/dist/locales/fr.d.ts +638 -369
  16. package/dist/locales/fr.js +738 -423
  17. package/dist/locales/index.d.ts +6476 -3786
  18. package/dist/locales/index.js +20 -20
  19. package/dist/locales/ja.d.ts +638 -369
  20. package/dist/locales/ja.js +732 -417
  21. package/dist/locales/ko.d.ts +638 -369
  22. package/dist/locales/ko.js +736 -424
  23. package/dist/locales/pt.d.ts +638 -369
  24. package/dist/locales/pt.js +737 -425
  25. package/dist/locales/ru.d.ts +638 -369
  26. package/dist/locales/ru.js +750 -424
  27. package/dist/locales/zh.d.ts +672 -403
  28. package/dist/locales/zh.js +720 -403
  29. package/dist/pickLocalized.d.ts +58 -0
  30. package/dist/pickLocalized.js +115 -7
  31. package/dist/provider.d.ts +84 -2
  32. package/dist/provider.js +305 -31
  33. package/dist/useDisplayLocale.d.ts +49 -0
  34. package/dist/useDisplayLocale.js +55 -0
  35. package/dist/useObjectLabel.d.ts +94 -14
  36. package/dist/useObjectLabel.js +134 -21
  37. package/dist/useSafeTranslation.js +51 -3
  38. package/dist/utils/index.d.ts +4 -3
  39. package/dist/utils/index.js +4 -3
  40. package/dist/utils/number-display.d.ts +32 -0
  41. package/dist/utils/number-display.js +32 -0
  42. package/dist/utils/spec-formatters.d.ts +39 -13
  43. package/dist/utils/spec-formatters.js +3 -3
  44. package/package.json +4 -3
package/README.md CHANGED
@@ -21,7 +21,6 @@ npm install @object-ui/i18n
21
21
 
22
22
  **Peer Dependencies:**
23
23
  - `react` ^18.0.0 || ^19.0.0
24
- - `react-dom` ^18.0.0 || ^19.0.0
25
24
 
26
25
  ## Quick Start
27
26
 
@@ -136,20 +135,50 @@ isRTL('ar'); // true
136
135
  isRTL('en'); // false
137
136
  ```
138
137
 
139
- <!-- release-metadata:v3.3.0 -->
140
-
141
- ## Compatibility
142
-
143
- - **React:** 18.x or 19.x
144
- - **Node.js:** ≥ 18
145
- - **TypeScript:** ≥ 5.0 (strict mode)
146
- - **`@objectstack/spec`:** ^3.3.0
147
- - **`@objectstack/client`:** ^3.3.0
148
- - **Tailwind CSS:** ≥ 3.4 (for packages with UI)
138
+ ## Scope — the `engine.*` carve-out (metadata-admin / Studio)
139
+
140
+ Not every user-facing string in this repository resolves through these packs.
141
+ The metadata-admin (Studio) surface — the metadata directory, the inspectors,
142
+ package management, the flow designer and their refusal messages — resolves its
143
+ `engine.*` keys through a module-local **two-locale** table in
144
+ [`packages/app-shell/src/views/metadata-admin/i18n.ts`](../app-shell/src/views/metadata-admin/i18n.ts):
145
+ a plain `Record` lookup over `en-US` and `zh-CN`, not an i18next namespace.
146
+ Roughly 1,300 keys per locale live there, and **no `engine.*` key exists in any
147
+ of the ten packs.**
148
+
149
+ That is design, not drift — the file's header records it as "Phase 3f". The
150
+ server holds the primary path: the engine consumes `label` from the
151
+ `/meta/types` response, sourced from the platform's metadata-type registry. The
152
+ module-local table is a **fallback** for deployments with no translation bundles
153
+ configured, and the interim source of truth for Chinese until the platform's
154
+ `setup.translation.ts` ships zh-CN coverage. Copying the namespace into the
155
+ packs would duplicate strings whose primary source is a server response.
156
+
157
+ Two consequences follow, and both are accepted rather than outstanding work:
158
+
159
+ - **Only `en` and `zh` are covered.** On an `ar` / `de` / `es` / `fr` / `ja` /
160
+ `ko` / `pt` / `ru` console, `engine.*` strings render English. That is the
161
+ price of the carve-out, not a backfill someone forgot.
162
+ - **The i18n gates cannot see this namespace, by construction.** Key parity
163
+ ([`src/__tests__/all-locales-key-parity.test.ts`](./src/__tests__/all-locales-key-parity.test.ts))
164
+ compares pack against pack, and `engine.*` is in no pack — so it is not an
165
+ *exception* to that test, it is outside its subject. The call-site gate
166
+ ([`scripts/check-i18n-call-site-keys.mjs`](../../scripts/check-i18n-call-site-keys.mjs))
167
+ skips these call sites **by declaration**: the module is registered in its
168
+ `EXCLUDED_TRANSLATORS` list with a reason, and an imported `t` from any
169
+ unregistered module is a hard error there — so a second local table cannot
170
+ appear silently, and this carve-out cannot quietly widen.
171
+
172
+ **When to revisit.** Migrating the namespace into the packs is mechanical but
173
+ wide (~1,300 keys × 8 further locales) and argues against the server-driven
174
+ design above, so it is not worth doing speculatively. The condition to reopen it
175
+ is concrete: a stated demand for an admin console in a language other than `en`
176
+ or `zh` — not a general wish for broader locale coverage, which the packs
177
+ already serve on every other surface. See objectui#4662 for the measurement and
178
+ the ruling.
149
179
 
150
180
  ## Links
151
181
 
152
- - 📚 [Documentation](https://www.objectui.org/docs/packages/i18n)
153
182
  - 📦 [npm package](https://www.npmjs.com/package/@object-ui/i18n)
154
183
  - 📝 [Changelog](./CHANGELOG.md)
155
184
  - 🐛 [Report an issue](https://github.com/objectstack-ai/objectui/issues)
package/dist/i18n.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * Wraps i18next with Object UI defaults and built-in locale support.
5
5
  */
6
6
  import { type i18n as I18nInstance } from 'i18next';
7
- import type { TranslationKeys } from './locales/en';
7
+ import type { TranslationKeys } from './locales/en.js';
8
8
  export interface I18nConfig {
9
9
  /** Default language (default: 'en') */
10
10
  defaultLanguage?: string;
package/dist/i18n.js CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import i18next from 'i18next';
7
7
  import { initReactI18next } from 'react-i18next';
8
- import { builtInLocales, isRTL } from './locales/index';
8
+ import { builtInLocales, isRTL } from './locales/index.js';
9
9
  /**
10
10
  * Internal `t()` option flag set by `useObjectLabel` on its convention-key
11
11
  * probes. The missing-key handler skips any lookup carrying this flag, so the
@@ -34,7 +34,6 @@ function createMissingKeyHandler() {
34
34
  return;
35
35
  seen.add(dedupeKey);
36
36
  const fb = fallbackValue ? `"${fallbackValue}"` : 'the key itself';
37
- // eslint-disable-next-line no-console
38
37
  console.warn(`[object-ui i18n] Missing translation for "${key}" (language "${lng}") — falling back to ${fb}.`);
39
38
  };
40
39
  }
package/dist/index.d.ts CHANGED
@@ -30,24 +30,26 @@
30
30
  *
31
31
  * @packageDocumentation
32
32
  */
33
- export { createI18n, getDirection, getAvailableLanguages, type I18nConfig, type TranslationKeys } from './i18n';
34
- export { I18nProvider, useObjectTranslation, useI18nContext, LOCALE_STORAGE_KEY, readStoredLanguage, type I18nProviderProps, } from './provider';
35
- export { createSafeTranslation, useSafeTranslate } from './useSafeTranslation';
36
- export { useObjectLabel, useSafeFieldLabel } from './useObjectLabel';
37
- export { builtInLocales, isRTL, RTL_LANGUAGES } from './locales/index';
38
- export { default as en } from './locales/en';
39
- export { default as zh } from './locales/zh';
40
- export { default as ja } from './locales/ja';
41
- export { default as ko } from './locales/ko';
42
- export { default as de } from './locales/de';
43
- export { default as fr } from './locales/fr';
44
- export { default as es } from './locales/es';
45
- export { default as pt } from './locales/pt';
46
- export { default as ru } from './locales/ru';
47
- export { default as ar } from './locales/ar';
48
- export { formatDate, formatDateTime, formatRelativeTime, formatCurrency, formatNumber, type DateFormatOptions, type CurrencyFormatOptions, type NumberFormatOptions, } from './utils/index';
49
- export { resolvePlural, formatDateSpec, formatNumberSpec, applyLocaleConfig, type SpecPluralRule, type SpecDateFormat, type SpecNumberFormat, type SpecLocaleConfig, } from './utils/index';
50
- export { isSpecTranslationData, transformSpecTranslations, type SpecTranslationData, } from './utils/index';
51
- export { pickLocalized } from './pickLocalized';
52
- export { LocalizationProvider, useLocalization, type LocalizationValue } from './LocalizationContext';
53
- export { resolveFieldCurrency } from './currency';
33
+ export { createI18n, getDirection, getAvailableLanguages, type I18nConfig, type TranslationKeys } from './i18n.js';
34
+ export { I18nProvider, useObjectTranslation, useI18nContext, LOCALE_STORAGE_KEY, readStoredLanguage, LOCALE_SEED_STORAGE_KEY, readCachedLanguageSeed, cacheLanguageSeed, type I18nProviderProps, } from './provider.js';
35
+ export { createSafeTranslation, useSafeTranslate } from './useSafeTranslation.js';
36
+ export { useObjectLabel, useSafeFieldLabel } from './useObjectLabel.js';
37
+ export { builtInLocales, isRTL, RTL_LANGUAGES } from './locales/index.js';
38
+ export { default as en } from './locales/en.js';
39
+ export { default as zh } from './locales/zh.js';
40
+ export { default as ja } from './locales/ja.js';
41
+ export { default as ko } from './locales/ko.js';
42
+ export { default as de } from './locales/de.js';
43
+ export { default as fr } from './locales/fr.js';
44
+ export { default as es } from './locales/es.js';
45
+ export { default as pt } from './locales/pt.js';
46
+ export { default as ru } from './locales/ru.js';
47
+ export { default as ar } from './locales/ar.js';
48
+ export { formatDate, formatDateTime, formatRelativeTime, formatCurrency, formatNumber, type DateFormatOptions, type CurrencyFormatOptions, type NumberFormatOptions, } from './utils/index.js';
49
+ export { resolvePlural, formatDateSpec, formatNumberSpec, applyLocaleConfig, type SpecPluralRule, type SpecDateFormat, type SpecNumberFormat, type SpecLocaleConfig, } from './utils/index.js';
50
+ export { isSpecTranslationData, transformSpecTranslations, type SpecTranslationData, } from './utils/index.js';
51
+ export { pickLocalized, setLocalized } from './pickLocalized.js';
52
+ export { LocalizationProvider, useLocalization, type LocalizationValue } from './LocalizationContext.js';
53
+ export { resolveFieldCurrency } from './currency.js';
54
+ export { useDisplayLocale } from './useDisplayLocale.js';
55
+ export { formatDisplayNumber, shouldGroupDisplayNumber, type DisplayNumberFormatOptions, } from './utils/index.js';
package/dist/index.js CHANGED
@@ -31,36 +31,46 @@
31
31
  * @packageDocumentation
32
32
  */
33
33
  // Core i18n setup
34
- export { createI18n, getDirection, getAvailableLanguages } from './i18n';
34
+ export { createI18n, getDirection, getAvailableLanguages } from './i18n.js';
35
35
  // React integration
36
36
  export { I18nProvider, useObjectTranslation, useI18nContext,
37
37
  // Language-preference persistence: the key the provider writes, and the
38
38
  // reader apps that bring their own i18next instance need to honour it.
39
- LOCALE_STORAGE_KEY, readStoredLanguage, } from './provider';
39
+ LOCALE_STORAGE_KEY, readStoredLanguage,
40
+ // Tenant locale seed (objectui#4035) — a SEPARATE slot from the explicit
41
+ // choice above, and never a substitute for it. An app that fetches its
42
+ // tenant's server-side locale caches it here; the provider applies it at
43
+ // bootstrap only when the user has chosen nothing themselves.
44
+ LOCALE_SEED_STORAGE_KEY, readCachedLanguageSeed, cacheLanguageSeed, } from './provider.js';
40
45
  // Safe translation hook factory
41
- export { createSafeTranslation, useSafeTranslate } from './useSafeTranslation';
46
+ export { createSafeTranslation, useSafeTranslate } from './useSafeTranslation.js';
42
47
  // Convention-based object/field label i18n
43
- export { useObjectLabel, useSafeFieldLabel } from './useObjectLabel';
48
+ export { useObjectLabel, useSafeFieldLabel } from './useObjectLabel.js';
44
49
  // Locale packs
45
- export { builtInLocales, isRTL, RTL_LANGUAGES } from './locales/index';
46
- export { default as en } from './locales/en';
47
- export { default as zh } from './locales/zh';
48
- export { default as ja } from './locales/ja';
49
- export { default as ko } from './locales/ko';
50
- export { default as de } from './locales/de';
51
- export { default as fr } from './locales/fr';
52
- export { default as es } from './locales/es';
53
- export { default as pt } from './locales/pt';
54
- export { default as ru } from './locales/ru';
55
- export { default as ar } from './locales/ar';
50
+ export { builtInLocales, isRTL, RTL_LANGUAGES } from './locales/index.js';
51
+ export { default as en } from './locales/en.js';
52
+ export { default as zh } from './locales/zh.js';
53
+ export { default as ja } from './locales/ja.js';
54
+ export { default as ko } from './locales/ko.js';
55
+ export { default as de } from './locales/de.js';
56
+ export { default as fr } from './locales/fr.js';
57
+ export { default as es } from './locales/es.js';
58
+ export { default as pt } from './locales/pt.js';
59
+ export { default as ru } from './locales/ru.js';
60
+ export { default as ar } from './locales/ar.js';
56
61
  // Formatting utilities
57
- export { formatDate, formatDateTime, formatRelativeTime, formatCurrency, formatNumber, } from './utils/index';
62
+ export { formatDate, formatDateTime, formatRelativeTime, formatCurrency, formatNumber, } from './utils/index.js';
58
63
  // Spec-aligned formatters (v2.0.7)
59
- export { resolvePlural, formatDateSpec, formatNumberSpec, applyLocaleConfig, } from './utils/index';
64
+ export { resolvePlural, formatDateSpec, formatNumberSpec, applyLocaleConfig, } from './utils/index.js';
60
65
  // Spec TranslationData → flat namespace transform (consumed by
61
66
  // `useObjectLabel`). Exposed so apps don't have to copy/paste — see
62
67
  // `apps/console/src/loadLanguage.ts` for the canonical consumer.
63
- export { isSpecTranslationData, transformSpecTranslations, } from './utils/index';
64
- export { pickLocalized } from './pickLocalized';
65
- export { LocalizationProvider, useLocalization } from './LocalizationContext';
66
- export { resolveFieldCurrency } from './currency';
68
+ export { isSpecTranslationData, transformSpecTranslations, } from './utils/index.js';
69
+ export { pickLocalized, setLocalized } from './pickLocalized.js';
70
+ export { LocalizationProvider, useLocalization } from './LocalizationContext.js';
71
+ export { resolveFieldCurrency } from './currency.js';
72
+ // The one number-display formatter (objectui#4033) and the locale it formats
73
+ // in. Every field cell / widget / metric renderer goes through this pair —
74
+ // see `utils/number-display.ts` for the grouping policy and its interim status.
75
+ export { useDisplayLocale } from './useDisplayLocale.js';
76
+ export { formatDisplayNumber, shouldGroupDisplayNumber, } from './utils/index.js';