@object-ui/i18n 6.2.3 → 7.0.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/CHANGELOG.md +122 -0
- package/README.md +1 -1
- package/dist/LocalizationContext.d.ts +39 -0
- package/dist/LocalizationContext.js +38 -0
- package/dist/currency.d.ts +28 -0
- package/dist/currency.js +28 -0
- package/dist/i18n.d.ts +18 -0
- package/dist/i18n.js +37 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/locales/ar.d.ts +1937 -1216
- package/dist/locales/ar.js +1855 -1129
- package/dist/locales/de.d.ts +1937 -1215
- package/dist/locales/de.js +1853 -1140
- package/dist/locales/en.d.ts +632 -5
- package/dist/locales/en.js +636 -5
- package/dist/locales/es.d.ts +1937 -1215
- package/dist/locales/es.js +1855 -1128
- package/dist/locales/fr.d.ts +1937 -1215
- package/dist/locales/fr.js +1829 -1116
- package/dist/locales/index.d.ts +17413 -10371
- package/dist/locales/ja.d.ts +1937 -1226
- package/dist/locales/ja.js +1855 -1139
- package/dist/locales/ko.d.ts +1937 -1215
- package/dist/locales/ko.js +1855 -1128
- package/dist/locales/pt.d.ts +1937 -1215
- package/dist/locales/pt.js +1855 -1128
- package/dist/locales/ru.d.ts +1937 -1226
- package/dist/locales/ru.js +1855 -1148
- package/dist/locales/zh.d.ts +641 -4
- package/dist/locales/zh.js +645 -4
- package/dist/pickLocalized.d.ts +14 -0
- package/dist/pickLocalized.js +33 -0
- package/dist/useObjectLabel.d.ts +21 -0
- package/dist/useObjectLabel.js +53 -1
- package/dist/useSafeTranslation.d.ts +13 -0
- package/dist/useSafeTranslation.js +32 -0
- package/package.json +6 -6
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a possibly-localized value to the best string for a language.
|
|
3
|
+
*
|
|
4
|
+
* Accepts a plain string (passed through) or an i18n object keyed by language
|
|
5
|
+
* code — e.g. `{ en: 'Pricing', 'zh-CN': '定价', zh: '定价', default: 'Pricing' }`.
|
|
6
|
+
* Resolution order: exact language -> base language (`zh-CN` -> `zh`) -> `default`
|
|
7
|
+
* -> `en` -> first value. Unlike a `default`/`en`-only resolver this is genuinely
|
|
8
|
+
* locale-aware, so server-driven metadata (page text, action param labels) can
|
|
9
|
+
* carry inline translations instead of rendering "[object Object]" or English.
|
|
10
|
+
*
|
|
11
|
+
* Pure — pair it with `useObjectTranslation().language` (or any current-locale
|
|
12
|
+
* source) at the call site.
|
|
13
|
+
*/
|
|
14
|
+
export declare function pickLocalized(value: unknown, language: string | undefined | null): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a possibly-localized value to the best string for a language.
|
|
3
|
+
*
|
|
4
|
+
* Accepts a plain string (passed through) or an i18n object keyed by language
|
|
5
|
+
* code — e.g. `{ en: 'Pricing', 'zh-CN': '定价', zh: '定价', default: 'Pricing' }`.
|
|
6
|
+
* Resolution order: exact language -> base language (`zh-CN` -> `zh`) -> `default`
|
|
7
|
+
* -> `en` -> first value. Unlike a `default`/`en`-only resolver this is genuinely
|
|
8
|
+
* locale-aware, so server-driven metadata (page text, action param labels) can
|
|
9
|
+
* carry inline translations instead of rendering "[object Object]" or English.
|
|
10
|
+
*
|
|
11
|
+
* Pure — pair it with `useObjectTranslation().language` (or any current-locale
|
|
12
|
+
* source) at the call site.
|
|
13
|
+
*/
|
|
14
|
+
export function pickLocalized(value, language) {
|
|
15
|
+
if (value == null)
|
|
16
|
+
return '';
|
|
17
|
+
if (typeof value === 'string')
|
|
18
|
+
return value;
|
|
19
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
20
|
+
return String(value);
|
|
21
|
+
if (typeof value === 'object') {
|
|
22
|
+
const o = value;
|
|
23
|
+
const lang = (language || 'en').trim();
|
|
24
|
+
const base = lang.split('-')[0];
|
|
25
|
+
const pick = o[lang] ??
|
|
26
|
+
o[base] ??
|
|
27
|
+
o.default ??
|
|
28
|
+
o.en ??
|
|
29
|
+
Object.values(o).find((v) => typeof v === 'string');
|
|
30
|
+
return pick == null ? '' : String(pick);
|
|
31
|
+
}
|
|
32
|
+
return String(value);
|
|
33
|
+
}
|
package/dist/useObjectLabel.d.ts
CHANGED
|
@@ -196,6 +196,27 @@ export declare function useObjectLabel(): {
|
|
|
196
196
|
* Convention: `{ns}.objects.{objectName}._actions.{actionName}.successMessage`.
|
|
197
197
|
*/
|
|
198
198
|
actionSuccess: (objectName: string | undefined, actionName: string, fallback?: string) => string | undefined;
|
|
199
|
+
/**
|
|
200
|
+
* Resolve translated action description (the explanatory line shown in the
|
|
201
|
+
* action's param dialog / sheet / drawer header).
|
|
202
|
+
* Convention: `{ns}.objects.{objectName}._actions.{actionName}.description`.
|
|
203
|
+
* Falls back to `{ns}.globalActions.{actionName}.description`, then the
|
|
204
|
+
* metadata's literal string; undefined when nothing resolves.
|
|
205
|
+
*/
|
|
206
|
+
actionDescription: (objectName: string | undefined, actionName: string | undefined, fallback?: string) => string | undefined;
|
|
207
|
+
/**
|
|
208
|
+
* Resolve translated action-PARAMETER text (label / placeholder / helpText).
|
|
209
|
+
* Convention: `{ns}.objects.{objectName}._actions.{actionName}.params.{paramName}.{attr}`.
|
|
210
|
+
* Falls back to the provided value (the metadata's literal string) when no
|
|
211
|
+
* translation exists, so untranslated params keep rendering as authored.
|
|
212
|
+
*/
|
|
213
|
+
actionParamText: (objectName: string | undefined, actionName: string | undefined, paramName: string, attr: "label" | "placeholder" | "helpText", fallback?: string) => string | undefined;
|
|
214
|
+
/**
|
|
215
|
+
* Resolve a translated action-parameter SELECT OPTION label.
|
|
216
|
+
* Convention: `{ns}.objects.{objectName}._actions.{actionName}.params.{paramName}.options.{optionValue}`.
|
|
217
|
+
* Falls back to the provided (English metadata) label when untranslated.
|
|
218
|
+
*/
|
|
219
|
+
actionParamOptionLabel: (objectName: string | undefined, actionName: string | undefined, paramName: string, optionValue: string, fallback: string) => string;
|
|
199
220
|
};
|
|
200
221
|
/**
|
|
201
222
|
* Safe wrapper for useObjectLabel that falls back to identity functions
|
package/dist/useObjectLabel.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { useMemo } from 'react';
|
|
20
20
|
import { useObjectTranslation } from './provider';
|
|
21
|
+
import { I18N_PROBE_FLAG } from './i18n';
|
|
21
22
|
/**
|
|
22
23
|
* Built-in Object UI top-level locale keys — not app namespaces.
|
|
23
24
|
* Update this set when new top-level platform translation keys are added
|
|
@@ -88,7 +89,10 @@ export function useObjectLabel() {
|
|
|
88
89
|
for (const ns of namespaces) {
|
|
89
90
|
for (const suffix of suffixList) {
|
|
90
91
|
const key = `${ns}.${suffix}`;
|
|
91
|
-
|
|
92
|
+
// `I18N_PROBE_FLAG` marks this as a speculative convention lookup so
|
|
93
|
+
// the dev missing-key warner stays silent when it (expectedly) misses
|
|
94
|
+
// and we fall back to the server-resolved label.
|
|
95
|
+
const translated = t(key, { defaultValue: '', [I18N_PROBE_FLAG]: true });
|
|
92
96
|
if (translated && translated !== key && translated !== '') {
|
|
93
97
|
return translated;
|
|
94
98
|
}
|
|
@@ -328,6 +332,54 @@ export function useObjectLabel() {
|
|
|
328
332
|
const resolved = resolve(suffixes, fb);
|
|
329
333
|
return resolved || undefined;
|
|
330
334
|
},
|
|
335
|
+
/**
|
|
336
|
+
* Resolve translated action description (the explanatory line shown in the
|
|
337
|
+
* action's param dialog / sheet / drawer header).
|
|
338
|
+
* Convention: `{ns}.objects.{objectName}._actions.{actionName}.description`.
|
|
339
|
+
* Falls back to `{ns}.globalActions.{actionName}.description`, then the
|
|
340
|
+
* metadata's literal string; undefined when nothing resolves.
|
|
341
|
+
*/
|
|
342
|
+
actionDescription: (objectName, actionName, fallback) => {
|
|
343
|
+
const fb = fallback ?? '';
|
|
344
|
+
if (!actionName)
|
|
345
|
+
return fb || undefined;
|
|
346
|
+
const suffixes = objectName
|
|
347
|
+
? objectSuffixes(objectName, `_actions.${actionName}.description`)
|
|
348
|
+
: `globalActions.${actionName}.description`;
|
|
349
|
+
const resolved = resolve(suffixes, fb);
|
|
350
|
+
return resolved || undefined;
|
|
351
|
+
},
|
|
352
|
+
/**
|
|
353
|
+
* Resolve translated action-PARAMETER text (label / placeholder / helpText).
|
|
354
|
+
* Convention: `{ns}.objects.{objectName}._actions.{actionName}.params.{paramName}.{attr}`.
|
|
355
|
+
* Falls back to the provided value (the metadata's literal string) when no
|
|
356
|
+
* translation exists, so untranslated params keep rendering as authored.
|
|
357
|
+
*/
|
|
358
|
+
actionParamText: (objectName, actionName, paramName, attr, fallback) => {
|
|
359
|
+
const fb = fallback ?? '';
|
|
360
|
+
if (!actionName || !paramName)
|
|
361
|
+
return fb || undefined;
|
|
362
|
+
const suffix = `_actions.${actionName}.params.${paramName}.${attr}`;
|
|
363
|
+
const suffixes = objectName
|
|
364
|
+
? objectSuffixes(objectName, suffix)
|
|
365
|
+
: `globalActions.${actionName}.params.${paramName}.${attr}`;
|
|
366
|
+
const resolved = resolve(suffixes, fb);
|
|
367
|
+
return resolved || undefined;
|
|
368
|
+
},
|
|
369
|
+
/**
|
|
370
|
+
* Resolve a translated action-parameter SELECT OPTION label.
|
|
371
|
+
* Convention: `{ns}.objects.{objectName}._actions.{actionName}.params.{paramName}.options.{optionValue}`.
|
|
372
|
+
* Falls back to the provided (English metadata) label when untranslated.
|
|
373
|
+
*/
|
|
374
|
+
actionParamOptionLabel: (objectName, actionName, paramName, optionValue, fallback) => {
|
|
375
|
+
if (!actionName || !paramName)
|
|
376
|
+
return fallback;
|
|
377
|
+
const suffix = `_actions.${actionName}.params.${paramName}.options.${optionValue}`;
|
|
378
|
+
const suffixes = objectName
|
|
379
|
+
? objectSuffixes(objectName, suffix)
|
|
380
|
+
: `globalActions.${actionName}.params.${paramName}.options.${optionValue}`;
|
|
381
|
+
return resolve(suffixes, fallback);
|
|
382
|
+
},
|
|
331
383
|
};
|
|
332
384
|
}, [t, i18n]);
|
|
333
385
|
}
|
|
@@ -3,3 +3,16 @@ export declare function createSafeTranslation(defaults: Record<string, string>,
|
|
|
3
3
|
} | {
|
|
4
4
|
t: import("i18next").TFunction<string, undefined>;
|
|
5
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* Per-call graceful translate hook for plugin renderers.
|
|
8
|
+
*
|
|
9
|
+
* Returns `t(keyOrKeys, fallback)`: tries each i18n key in order and returns the
|
|
10
|
+
* first real translation; when no `I18nProvider` is mounted (tests / standalone)
|
|
11
|
+
* or every key is missing, returns the English `fallback` — never a raw key.
|
|
12
|
+
*
|
|
13
|
+
* Unlike {@link createSafeTranslation} (a factory keyed by a defaults map), this
|
|
14
|
+
* takes the English default at each call site, which suits one-off labels like
|
|
15
|
+
* "Total". The key-array form supports a migration fallback chain, e.g.
|
|
16
|
+
* `tt(['common.total', 'dashboard.total'], 'Total')`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useSafeTranslate(): (keyOrKeys: string | string[], fallback: string) => string;
|
|
@@ -44,3 +44,35 @@ export function createSafeTranslation(defaults, testKey) {
|
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Per-call graceful translate hook for plugin renderers.
|
|
49
|
+
*
|
|
50
|
+
* Returns `t(keyOrKeys, fallback)`: tries each i18n key in order and returns the
|
|
51
|
+
* first real translation; when no `I18nProvider` is mounted (tests / standalone)
|
|
52
|
+
* or every key is missing, returns the English `fallback` — never a raw key.
|
|
53
|
+
*
|
|
54
|
+
* Unlike {@link createSafeTranslation} (a factory keyed by a defaults map), this
|
|
55
|
+
* takes the English default at each call site, which suits one-off labels like
|
|
56
|
+
* "Total". The key-array form supports a migration fallback chain, e.g.
|
|
57
|
+
* `tt(['common.total', 'dashboard.total'], 'Total')`.
|
|
58
|
+
*/
|
|
59
|
+
export function useSafeTranslate() {
|
|
60
|
+
let t;
|
|
61
|
+
try {
|
|
62
|
+
t = useObjectTranslation().t;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
t = undefined;
|
|
66
|
+
}
|
|
67
|
+
return (keyOrKeys, fallback) => {
|
|
68
|
+
if (!t)
|
|
69
|
+
return fallback;
|
|
70
|
+
const keys = Array.isArray(keyOrKeys) ? keyOrKeys : [keyOrKeys];
|
|
71
|
+
for (const key of keys) {
|
|
72
|
+
const v = t(key);
|
|
73
|
+
if (v && v !== key)
|
|
74
|
+
return v;
|
|
75
|
+
}
|
|
76
|
+
return fallback;
|
|
77
|
+
};
|
|
78
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/i18n",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,17 +30,17 @@
|
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"i18next": "^26.
|
|
34
|
-
"react-i18next": "^17.0.
|
|
33
|
+
"i18next": "^26.3.1",
|
|
34
|
+
"react-i18next": "^17.0.8"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": "^18.0.0 || ^19.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@types/react": "19.2.
|
|
41
|
-
"react": "19.2.
|
|
40
|
+
"@types/react": "19.2.17",
|
|
41
|
+
"react": "19.2.7",
|
|
42
42
|
"typescript": "^6.0.3",
|
|
43
|
-
"vitest": "^4.1.
|
|
43
|
+
"vitest": "^4.1.9"
|
|
44
44
|
},
|
|
45
45
|
"keywords": [
|
|
46
46
|
"objectui",
|