@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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,127 @@
|
|
|
1
1
|
# @object-ui/i18n
|
|
2
2
|
|
|
3
|
+
## 7.0.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 89e113c: ADR-0044 send-back-for-revision in the approvals inbox (framework #1744/#1769). Approvers get a "Send back" action (violet, with its own dialog) that ends the round as `returned` and unlocks the record; the submitter sees a revision panel on the returned request — edit-record link, optional comment, Resubmit (opens round N+1) and Recall (abandons the revision). New `returned` status badge/filter, Round-N chips (list + drawer), timeline rendering for `revise`/`resubmit` actions, `approvalsApi.sendBack/resubmit`, and ten-locale `approvalsInbox` strings.
|
|
8
|
+
- 18d0339: Relabel metadata-driven UI on a language switch without a page refresh (#1319)
|
|
9
|
+
|
|
10
|
+
Switching the UI language left server-resolved metadata labels (object/field/
|
|
11
|
+
view labels, action-dialog text) in the old language until a hard refresh,
|
|
12
|
+
because renderers cache those labels by object name and never refetch on a
|
|
13
|
+
language change.
|
|
14
|
+
|
|
15
|
+
**`@object-ui/auth`** — `createAuthenticatedFetch` now folds the active
|
|
16
|
+
`<html lang>` into `Accept-Language` on API calls (never clobbering an explicit
|
|
17
|
+
header), so a switch carries the new locale on every subsequent request.
|
|
18
|
+
|
|
19
|
+
**`@object-ui/app-shell`** — `ConnectedShellInner` drops the adapter's
|
|
20
|
+
locale-blind metadata cache in the render phase and remounts the metadata
|
|
21
|
+
subtree via `key={language}`, so every renderer refetches in the new locale.
|
|
22
|
+
The adapter and its connection sit above the key and are preserved — an in-app
|
|
23
|
+
relabel, not a reconnect.
|
|
24
|
+
|
|
25
|
+
**`@object-ui/i18n`** — dev-mode missing-key warnings: `createI18n` gains
|
|
26
|
+
`warnMissingKeys` (default on outside production) wiring a deduped i18next
|
|
27
|
+
`missingKeyHandler`. `useObjectLabel`'s convention-key probes are flagged so
|
|
28
|
+
their intentional misses (which fall back to server metadata) stay silent.
|
|
29
|
+
|
|
30
|
+
Pairs with the framework-side locale-aware metadata changes in
|
|
31
|
+
`@objectstack/client` / `@objectstack/objectql` / `@objectstack/rest`.
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- 77cc6bb: Cloud Connection bind v2 UX (cloud ADR runtime-identity-binding §2.3): the binding flow becomes one click. `CloudConnectionPanel` drops the environment-id input entirely (registration happens cloud-side at approval), auto-opens the approval page in a popup on Connect (user-code display stays as the popup-blocked fallback), and shows the registered runtime name + runtime id once bound. `DeviceAuthPage` displays the requesting device's context (`runtime_name` / `runtime_version` from the verification URL) plus an "only approve if you started this" warning — the informed-consent surface for the RFC 8628 flow. Two new `auth.device.*` keys across all locales.
|
|
36
|
+
- 97c6831: Localize AI workspace, shell navigation, startup, connection, toast, and chatbot affordance text across core console screens.
|
|
37
|
+
- c09f44e: Docs: mermaid diagrams + long-doc table of contents (ADR-0046).
|
|
38
|
+
|
|
39
|
+
- **plugin-markdown** renders ```mermaid fenced blocks as diagrams (`<Mermaid>`: lazy-loaded mermaid, `securityLevel: 'strict'`, rendered post-`rehype-sanitize`by a trusted component, degrades to the raw source on error). Mermaid is text → SVG, so it stays within the v1 image/binary ban. Adds`extractToc(markdown)`— a TOC builder whose slugs are generated with the same`github-slugger` `rehype-slug`uses, so`#id` links resolve to the rendered heading anchors.
|
|
40
|
+
- **console** `DocPage` shows a sticky right-rail table of contents (h2–h3) for docs with ≥3 headings, plus an app-independent `/apps/:packageId/docs` index already added earlier.
|
|
41
|
+
- **i18n** adds `help.onThisPage` (en/zh; other locales fall back).
|
|
42
|
+
|
|
43
|
+
- 6cfa330: feat(dashboard): drill "Open in list" escape hatch + unify report drill
|
|
44
|
+
|
|
45
|
+
Adopts the mainstream BI peek-then-escalate drill model. Drill-through opens an
|
|
46
|
+
in-place drawer (keep context) and offers an "Open in list →" affordance to
|
|
47
|
+
escalate to the object's full list page (sort / bulk-select / export / shareable
|
|
48
|
+
URL) — the Looker / Power BI "see records → open in page" pattern.
|
|
49
|
+
|
|
50
|
+
- New `DrillNavigationContext` (`@object-ui/react`): the app shell provides
|
|
51
|
+
`openRecordList`; the renderer stays decoupled from console routing.
|
|
52
|
+
- The drill drawers (pivot / dataset / chart / KPI) render the escape hatch when
|
|
53
|
+
a host navigation handler is present, and hide it otherwise (self-contained
|
|
54
|
+
peek). `DashboardView` provides the handler via `useOpenRecordList`.
|
|
55
|
+
- `DrillDownConfig.target` gains `'navigate'` — skip the drawer and open the
|
|
56
|
+
list directly; degrades to `'drawer'` when no host handler is available.
|
|
57
|
+
- `ReportView` drill-through now opens the same in-place drawer (peek records →
|
|
58
|
+
click a row to open a record) instead of navigating away; the escape hatch
|
|
59
|
+
preserves the previous navigate-to-list behavior. Dashboard and report drill
|
|
60
|
+
are now unified.
|
|
61
|
+
- i18n: `dashboard.openInList` (en / zh).
|
|
62
|
+
|
|
63
|
+
- 0ad72a6: fix: pass full gantt config to renderer, render multi-value lookups in gantt tooltips, persist `bodyExtra` on dataSource actions, and complete zh/en gantt labels
|
|
64
|
+
|
|
65
|
+
Four platform gaps that the EHR app previously worked around with `node_modules` patches:
|
|
66
|
+
|
|
67
|
+
- **app-shell / ObjectView** — the `config.gantt → renderer props` adapter was a hardcoded 6-field whitelist, so `parentField`/`typeField` (and `baseline*`, `groupByField`, `resourceView`, `tooltipFields`, `quickFilters`, …) never reached the renderer and the chart degraded to a flat list. It now spreads the full `viewDef.gantt` first, then applies the three required defaults last (mirroring the gallery branch).
|
|
68
|
+
- **plugin-gantt / ObjectGantt** — the tooltip value formatter only handled single-object lookups, so a multi-value lookup (a populated `[{name},{name}]` array) fell through to `'—'`. It now maps each array element to its display value and joins them.
|
|
69
|
+
- **app-shell / useConsoleActionRuntime** — `bodyExtra` was merged only on the absolute-HTTP path; the generic `dataSource.update` path ignored it, so a pure-confirmation action (no params array) left an empty payload and persisted nothing. `bodyExtra` is now merged last on that path too, matching the documented semantics.
|
|
70
|
+
- **i18n** — added the gantt labels the 9.x renderer references but the bundles lacked: `toolbar.thisWeek/thisMonth/exportPdf/saveLayout`, `viewMode.year`, `menu.add*/removeDependency/noCandidates`, the `linkType.*` and `conflict.*` blocks, and `readOnly*` — in both `en` (canonical key source) and `zh`.
|
|
71
|
+
|
|
72
|
+
- 3fa23a7: feat(header): context-aware Help & Documentation menu + app-scoped docs index
|
|
73
|
+
|
|
74
|
+
The top-right "?" was a bare external link to `docs.objectstack.ai`, duplicating
|
|
75
|
+
the left sidebar's in-product `/docs` entry and ignoring the ADR-0046 docs hub.
|
|
76
|
+
It is now an aggregated, context-aware menu:
|
|
77
|
+
|
|
78
|
+
- **This app's docs** — shown only when the current app's package owns docs
|
|
79
|
+
(matched by `_packageId`). A single-doc app deep-links straight to the
|
|
80
|
+
viewer; a multi-doc app lands on the new app-scoped index.
|
|
81
|
+
- **All documentation** — the in-product `/docs` portal.
|
|
82
|
+
- **Online documentation** — `docs.objectstack.ai` (opens in a new tab).
|
|
83
|
+
|
|
84
|
+
Docs are lazily fetched once on first menu open (names/labels only), so the menu
|
|
85
|
+
adds no cost until used; a failed fetch soft-degrades to the static entries.
|
|
86
|
+
|
|
87
|
+
Also adds the app-scoped docs index route **`/apps/:packageId/docs`**
|
|
88
|
+
(`AppDocsIndex`) — the package-scoped sibling of `/docs`, listing just that
|
|
89
|
+
app's docs — which the "This app's docs" entry targets when an app ships more
|
|
90
|
+
than one. New `help.*` strings added to the `en` and `zh` bundles (other
|
|
91
|
+
locales fall back to `en`).
|
|
92
|
+
|
|
93
|
+
- 59b6bbb: i18n the managed-by empty states for system / append-only / better-auth object lists.
|
|
94
|
+
|
|
95
|
+
`resolveManagedByEmptyState` previously hardcoded English titles and messages (e.g. "No identity records", "No events recorded"), so list views for managed objects (identity, audit logs, system-generated records) rendered English regardless of locale. It now takes the `t` translator and resolves `list.managedBy.{system,appendOnly,betterAuth}.{title,message}` (English kept as `defaultValue` fallbacks); `ObjectView` passes its `t` through. Added the keys to the `en` and `zh` locale packs.
|
|
96
|
+
|
|
97
|
+
- bd8b054: fix(currency): resolve the tenant default currency across the long-tail renderers
|
|
98
|
+
|
|
99
|
+
Phase 2b of the currency-resolution work (ADR-0053). The cell/field renderers
|
|
100
|
+
already funnelled through `resolveFieldCurrency` + `useLocalization` (#1856),
|
|
101
|
+
but the rest of the renderers still hard-coded `USD` or read only one of
|
|
102
|
+
`currency`/`defaultCurrency`. They now share the same resolution chain — explicit
|
|
103
|
+
field currency -> `currencyConfig.defaultCurrency` -> legacy `defaultCurrency` ->
|
|
104
|
+
tenant `localization.currency` -> plain number:
|
|
105
|
+
|
|
106
|
+
- `plugin-dashboard` `ObjectMetricWidget` (inferred currency), `ObjectDataTable`
|
|
107
|
+
(symbol-format fallback).
|
|
108
|
+
- `plugin-grid` `useColumnSummary` (footer agrees with the cells) and
|
|
109
|
+
`ObjectGrid` (compact amount + name-inferred currency cells).
|
|
110
|
+
- `plugin-detail` `DetailView` summary metrics.
|
|
111
|
+
- `plugin-gantt` `ObjectGantt` currency tooltips.
|
|
112
|
+
- `components` `element:number` (`format: 'currency'`) — tenant default instead
|
|
113
|
+
of a baked-in `USD`, and renders with the tenant locale.
|
|
114
|
+
|
|
115
|
+
`resolveFieldCurrency` now lives in `@object-ui/i18n` (co-located with
|
|
116
|
+
`useLocalization`, which supplies the tenant default); `@object-ui/fields`
|
|
117
|
+
re-exports it, so the existing import path is unchanged. No behavior change when
|
|
118
|
+
no tenant currency is configured — a field that declares its own currency, or a
|
|
119
|
+
deployment with no `localization.currency`, renders exactly as before.
|
|
120
|
+
|
|
121
|
+
- 2f31406: Refine Studio package-scoped navigation and home overview.
|
|
122
|
+
|
|
123
|
+
Studio now treats the selected package as the home overview scope, flattens the root Overview sidebar group, hides the duplicate all-metadata sidebar entry, redirects the invalid package metadata route to package management, preserves the selected package across package-management navigation, and adds a localized package-management sidebar label.
|
|
124
|
+
|
|
3
125
|
## 6.2.3
|
|
4
126
|
|
|
5
127
|
## 6.2.2
|
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ function MyComponent() {
|
|
|
42
42
|
return (
|
|
43
43
|
<div dir={direction}>
|
|
44
44
|
<h1>{t('common.save')}</h1>
|
|
45
|
-
<button onClick={() => changeLanguage('zh')}
|
|
45
|
+
<button onClick={() => changeLanguage('zh')}>Chinese</button>
|
|
46
46
|
<button onClick={() => changeLanguage('ar')}>العربية</button>
|
|
47
47
|
</div>
|
|
48
48
|
);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* LocalizationContext — the tenant's resolved REGIONAL defaults (currency,
|
|
10
|
+
* locale) for the current request, surfaced to every renderer.
|
|
11
|
+
*
|
|
12
|
+
* This is the client half of ADR-0053: the framework resolves a workspace
|
|
13
|
+
* `localization.currency` / `locale` onto each request's ExecutionContext and
|
|
14
|
+
* exposes them at `GET /api/v1/auth/me/localization`. A fetching wrapper (in
|
|
15
|
+
* app-shell) loads them once and feeds this PURE context, so low-level field /
|
|
16
|
+
* measure renderers can resolve a currency code down to the org default —
|
|
17
|
+
* instead of hard-coding `$`/`¥`/`USD` or degrading to a bare number — without
|
|
18
|
+
* any of them depending on app-shell or making their own fetch.
|
|
19
|
+
*
|
|
20
|
+
* Undefined values mean "no tenant default known" → consumers render a plain
|
|
21
|
+
* number (the existing safe behavior).
|
|
22
|
+
*/
|
|
23
|
+
import * as React from 'react';
|
|
24
|
+
export interface LocalizationValue {
|
|
25
|
+
/** Tenant default currency (ISO 4217), or undefined when unconfigured. */
|
|
26
|
+
currency?: string;
|
|
27
|
+
/** Tenant/display locale (BCP-47) for Intl formatting, or undefined. */
|
|
28
|
+
locale?: string;
|
|
29
|
+
}
|
|
30
|
+
/** Pure provider — the fetching/loading concern lives in the app shell. */
|
|
31
|
+
export declare function LocalizationProvider({ value, children, }: {
|
|
32
|
+
value: LocalizationValue;
|
|
33
|
+
children: React.ReactNode;
|
|
34
|
+
}): React.JSX.Element;
|
|
35
|
+
/**
|
|
36
|
+
* Read the tenant regional defaults. Safe outside a provider — returns `{}`
|
|
37
|
+
* (no tenant default), so a renderer mounted standalone degrades gracefully.
|
|
38
|
+
*/
|
|
39
|
+
export declare function useLocalization(): LocalizationValue;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* ObjectUI
|
|
4
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* LocalizationContext — the tenant's resolved REGIONAL defaults (currency,
|
|
11
|
+
* locale) for the current request, surfaced to every renderer.
|
|
12
|
+
*
|
|
13
|
+
* This is the client half of ADR-0053: the framework resolves a workspace
|
|
14
|
+
* `localization.currency` / `locale` onto each request's ExecutionContext and
|
|
15
|
+
* exposes them at `GET /api/v1/auth/me/localization`. A fetching wrapper (in
|
|
16
|
+
* app-shell) loads them once and feeds this PURE context, so low-level field /
|
|
17
|
+
* measure renderers can resolve a currency code down to the org default —
|
|
18
|
+
* instead of hard-coding `$`/`¥`/`USD` or degrading to a bare number — without
|
|
19
|
+
* any of them depending on app-shell or making their own fetch.
|
|
20
|
+
*
|
|
21
|
+
* Undefined values mean "no tenant default known" → consumers render a plain
|
|
22
|
+
* number (the existing safe behavior).
|
|
23
|
+
*/
|
|
24
|
+
import * as React from 'react';
|
|
25
|
+
const LocalizationCtx = React.createContext({});
|
|
26
|
+
/** Pure provider — the fetching/loading concern lives in the app shell. */
|
|
27
|
+
export function LocalizationProvider({ value, children, }) {
|
|
28
|
+
// Stable identity unless the resolved values actually change.
|
|
29
|
+
const memo = React.useMemo(() => ({ currency: value.currency, locale: value.locale }), [value.currency, value.locale]);
|
|
30
|
+
return _jsx(LocalizationCtx.Provider, { value: memo, children: children });
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Read the tenant regional defaults. Safe outside a provider — returns `{}`
|
|
34
|
+
* (no tenant default), so a renderer mounted standalone degrades gracefully.
|
|
35
|
+
*/
|
|
36
|
+
export function useLocalization() {
|
|
37
|
+
return React.useContext(LocalizationCtx);
|
|
38
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the display currency code for a currency-typed field, in precedence
|
|
10
|
+
* order: the field's explicit `currency` -> its `currencyConfig.defaultCurrency`
|
|
11
|
+
* (fixed mode) -> a legacy top-level `defaultCurrency` -> the tenant default
|
|
12
|
+
* (`localization.currency`, ADR-0053, surfaced via {@link useLocalization}).
|
|
13
|
+
* Returns `undefined` when none is known, so the renderer shows a plain number
|
|
14
|
+
* rather than guessing a symbol.
|
|
15
|
+
*
|
|
16
|
+
* This is the single resolution every field / measure / cell renderer shares -
|
|
17
|
+
* ending the per-renderer drift where some read only `currency`, others only
|
|
18
|
+
* `defaultCurrency`, and others `currencyConfig`. It lives in `@object-ui/i18n`
|
|
19
|
+
* (alongside `useLocalization`) because the tenant default is a localization
|
|
20
|
+
* concern; `@object-ui/fields` re-exports it for backward compatibility.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveFieldCurrency(field: {
|
|
23
|
+
currency?: string;
|
|
24
|
+
defaultCurrency?: string;
|
|
25
|
+
currencyConfig?: {
|
|
26
|
+
defaultCurrency?: string;
|
|
27
|
+
};
|
|
28
|
+
} | null | undefined, tenantDefault?: string): string | undefined;
|
package/dist/currency.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the display currency code for a currency-typed field, in precedence
|
|
10
|
+
* order: the field's explicit `currency` -> its `currencyConfig.defaultCurrency`
|
|
11
|
+
* (fixed mode) -> a legacy top-level `defaultCurrency` -> the tenant default
|
|
12
|
+
* (`localization.currency`, ADR-0053, surfaced via {@link useLocalization}).
|
|
13
|
+
* Returns `undefined` when none is known, so the renderer shows a plain number
|
|
14
|
+
* rather than guessing a symbol.
|
|
15
|
+
*
|
|
16
|
+
* This is the single resolution every field / measure / cell renderer shares -
|
|
17
|
+
* ending the per-renderer drift where some read only `currency`, others only
|
|
18
|
+
* `defaultCurrency`, and others `currencyConfig`. It lives in `@object-ui/i18n`
|
|
19
|
+
* (alongside `useLocalization`) because the tenant default is a localization
|
|
20
|
+
* concern; `@object-ui/fields` re-exports it for backward compatibility.
|
|
21
|
+
*/
|
|
22
|
+
export function resolveFieldCurrency(field, tenantDefault) {
|
|
23
|
+
return (field?.currency ||
|
|
24
|
+
field?.currencyConfig?.defaultCurrency ||
|
|
25
|
+
field?.defaultCurrency ||
|
|
26
|
+
tenantDefault ||
|
|
27
|
+
undefined);
|
|
28
|
+
}
|
package/dist/i18n.d.ts
CHANGED
|
@@ -20,7 +20,25 @@ export interface I18nConfig {
|
|
|
20
20
|
prefix?: string;
|
|
21
21
|
suffix?: string;
|
|
22
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* Warn (once per key) in the dev console when a translation key is missing
|
|
25
|
+
* and the UI falls back to the key/defaultValue. Helps catch un-translated
|
|
26
|
+
* static strings while iterating. Defaults to ON outside production builds.
|
|
27
|
+
*
|
|
28
|
+
* Convention-key probes from `useObjectLabel` (object/field/view labels that
|
|
29
|
+
* intentionally fall back to server metadata) are excluded — they are not
|
|
30
|
+
* real "missing keys", just speculative lookups.
|
|
31
|
+
*/
|
|
32
|
+
warnMissingKeys?: boolean;
|
|
23
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Internal `t()` option flag set by `useObjectLabel` on its convention-key
|
|
36
|
+
* probes. The missing-key handler skips any lookup carrying this flag, so the
|
|
37
|
+
* deliberate object/field/view label probes (which usually miss and fall back
|
|
38
|
+
* to server metadata) never surface as dev warnings. Not part of the public
|
|
39
|
+
* API — shared between `i18n.ts` and `useObjectLabel.ts` to avoid drift.
|
|
40
|
+
*/
|
|
41
|
+
export declare const I18N_PROBE_FLAG = "__ouiLabelProbe";
|
|
24
42
|
/**
|
|
25
43
|
* Create and initialize an i18next instance with Object UI defaults
|
|
26
44
|
*/
|
package/dist/i18n.js
CHANGED
|
@@ -6,11 +6,43 @@
|
|
|
6
6
|
import i18next from 'i18next';
|
|
7
7
|
import { initReactI18next } from 'react-i18next';
|
|
8
8
|
import { builtInLocales, isRTL } from './locales/index';
|
|
9
|
+
/**
|
|
10
|
+
* Internal `t()` option flag set by `useObjectLabel` on its convention-key
|
|
11
|
+
* probes. The missing-key handler skips any lookup carrying this flag, so the
|
|
12
|
+
* deliberate object/field/view label probes (which usually miss and fall back
|
|
13
|
+
* to server metadata) never surface as dev warnings. Not part of the public
|
|
14
|
+
* API — shared between `i18n.ts` and `useObjectLabel.ts` to avoid drift.
|
|
15
|
+
*/
|
|
16
|
+
export const I18N_PROBE_FLAG = '__ouiLabelProbe';
|
|
17
|
+
/** True outside production builds (bundlers statically replace this). */
|
|
18
|
+
function isDevEnv() {
|
|
19
|
+
return typeof process === 'undefined' || process.env.NODE_ENV !== 'production';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build a dev-only i18next `missingKeyHandler`. Dedupes by language+key so a
|
|
23
|
+
* missing string warns once, not on every re-render, and stays silent for the
|
|
24
|
+
* convention-key probes flagged with {@link I18N_PROBE_FLAG}.
|
|
25
|
+
*/
|
|
26
|
+
function createMissingKeyHandler() {
|
|
27
|
+
const seen = new Set();
|
|
28
|
+
return (lngs, _ns, key, fallbackValue, _updateMissing, options) => {
|
|
29
|
+
if (options && options[I18N_PROBE_FLAG])
|
|
30
|
+
return;
|
|
31
|
+
const lng = Array.isArray(lngs) ? lngs[0] : String(lngs ?? '');
|
|
32
|
+
const dedupeKey = `${lng}:${key}`;
|
|
33
|
+
if (seen.has(dedupeKey))
|
|
34
|
+
return;
|
|
35
|
+
seen.add(dedupeKey);
|
|
36
|
+
const fb = fallbackValue ? `"${fallbackValue}"` : 'the key itself';
|
|
37
|
+
// eslint-disable-next-line no-console
|
|
38
|
+
console.warn(`[object-ui i18n] Missing translation for "${key}" (language "${lng}") — falling back to ${fb}.`);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
9
41
|
/**
|
|
10
42
|
* Create and initialize an i18next instance with Object UI defaults
|
|
11
43
|
*/
|
|
12
44
|
export function createI18n(config = {}) {
|
|
13
|
-
const { defaultLanguage = 'en', fallbackLanguage = 'en', resources = {}, detectBrowserLanguage = true, interpolation, } = config;
|
|
45
|
+
const { defaultLanguage = 'en', fallbackLanguage = 'en', resources = {}, detectBrowserLanguage = true, interpolation, warnMissingKeys = isDevEnv(), } = config;
|
|
14
46
|
// Merge built-in locales with user-provided resources
|
|
15
47
|
const mergedResources = {};
|
|
16
48
|
for (const [lang, translations] of Object.entries(builtInLocales)) {
|
|
@@ -50,6 +82,10 @@ export function createI18n(config = {}) {
|
|
|
50
82
|
...interpolation,
|
|
51
83
|
},
|
|
52
84
|
returnNull: false,
|
|
85
|
+
// Dev-only: surface un-translated static keys in the console (deduped,
|
|
86
|
+
// and silent for useObjectLabel's intentional convention-key probes).
|
|
87
|
+
saveMissing: warnMissingKeys,
|
|
88
|
+
missingKeyHandler: warnMissingKeys ? createMissingKeyHandler() : undefined,
|
|
53
89
|
react: {
|
|
54
90
|
useSuspense: false,
|
|
55
91
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
export { createI18n, getDirection, getAvailableLanguages, type I18nConfig, type TranslationKeys } from './i18n';
|
|
34
34
|
export { I18nProvider, useObjectTranslation, useI18nContext, type I18nProviderProps } from './provider';
|
|
35
|
-
export { createSafeTranslation } from './useSafeTranslation';
|
|
35
|
+
export { createSafeTranslation, useSafeTranslate } from './useSafeTranslation';
|
|
36
36
|
export { useObjectLabel, useSafeFieldLabel } from './useObjectLabel';
|
|
37
37
|
export { builtInLocales, isRTL, RTL_LANGUAGES } from './locales/index';
|
|
38
38
|
export { default as en } from './locales/en';
|
|
@@ -48,3 +48,6 @@ export { default as ar } from './locales/ar';
|
|
|
48
48
|
export { formatDate, formatDateTime, formatRelativeTime, formatCurrency, formatNumber, type DateFormatOptions, type CurrencyFormatOptions, type NumberFormatOptions, } from './utils/index';
|
|
49
49
|
export { resolvePlural, formatDateSpec, formatNumberSpec, applyLocaleConfig, type SpecPluralRule, type SpecDateFormat, type SpecNumberFormat, type SpecLocaleConfig, } from './utils/index';
|
|
50
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';
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ export { createI18n, getDirection, getAvailableLanguages } from './i18n';
|
|
|
35
35
|
// React integration
|
|
36
36
|
export { I18nProvider, useObjectTranslation, useI18nContext } from './provider';
|
|
37
37
|
// Safe translation hook factory
|
|
38
|
-
export { createSafeTranslation } from './useSafeTranslation';
|
|
38
|
+
export { createSafeTranslation, useSafeTranslate } from './useSafeTranslation';
|
|
39
39
|
// Convention-based object/field label i18n
|
|
40
40
|
export { useObjectLabel, useSafeFieldLabel } from './useObjectLabel';
|
|
41
41
|
// Locale packs
|
|
@@ -58,3 +58,6 @@ export { resolvePlural, formatDateSpec, formatNumberSpec, applyLocaleConfig, } f
|
|
|
58
58
|
// `useObjectLabel`). Exposed so apps don't have to copy/paste — see
|
|
59
59
|
// `apps/console/src/loadLanguage.ts` for the canonical consumer.
|
|
60
60
|
export { isSpecTranslationData, transformSpecTranslations, } from './utils/index';
|
|
61
|
+
export { pickLocalized } from './pickLocalized';
|
|
62
|
+
export { LocalizationProvider, useLocalization } from './LocalizationContext';
|
|
63
|
+
export { resolveFieldCurrency } from './currency';
|