@sonenta/react-i18next 2.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/LICENSE +21 -0
- package/README.md +540 -0
- package/dist/index.cjs +1326 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +540 -0
- package/dist/index.d.ts +540 -0
- package/dist/index.js +1299 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { i18n } from 'i18next';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Surface variants (#911) — a second resolution dimension layered ON TOP of
|
|
7
|
+
* the locale fallback chain. A "surface" (`desktop` / `mobile` / `tablet`) is
|
|
8
|
+
* an additive overlay: the base bundle applies to every surface, and a sparse
|
|
9
|
+
* surface overlay overrides individual keys for that surface only.
|
|
10
|
+
*
|
|
11
|
+
* This module is the framework-neutral surface helpers; the engine
|
|
12
|
+
* (`SonentaI18n`) owns the overlay loading/compose, and the provider wires
|
|
13
|
+
* the reactive viewport listener (web) — see `provider.tsx`.
|
|
14
|
+
*/
|
|
15
|
+
type Surface = "desktop" | "mobile" | "tablet";
|
|
16
|
+
/** Min-width (px) thresholds that map a viewport width to a surface. A width
|
|
17
|
+
* `< mobile` → `mobile`; `< tablet` → `tablet`; otherwise `desktop`. Mirrors
|
|
18
|
+
* the common mobile-first breakpoint ladder. */
|
|
19
|
+
interface SurfaceBreakpoints {
|
|
20
|
+
/** Upper bound (exclusive) of the `mobile` surface, in px. Default 640. */
|
|
21
|
+
mobile: number;
|
|
22
|
+
/** Upper bound (exclusive) of the `tablet` surface, in px. Default 1024. */
|
|
23
|
+
tablet: number;
|
|
24
|
+
}
|
|
25
|
+
declare const DEFAULT_SURFACE_BREAKPOINTS: SurfaceBreakpoints;
|
|
26
|
+
/**
|
|
27
|
+
* Map a viewport width (px) to a {@link Surface} using `breakpoints`
|
|
28
|
+
* (defaults to {@link DEFAULT_SURFACE_BREAKPOINTS}). Framework-neutral and
|
|
29
|
+
* pure — React Native callers can feed it `useWindowDimensions().width` and
|
|
30
|
+
* pass the result to `i18n.setSurface(...)`; the web provider uses it
|
|
31
|
+
* internally against `window.innerWidth`.
|
|
32
|
+
*/
|
|
33
|
+
declare function surfaceForWidth(width: number, breakpoints?: SurfaceBreakpoints): Surface;
|
|
34
|
+
|
|
35
|
+
type Locale = string;
|
|
36
|
+
type Namespace = string;
|
|
37
|
+
/** An asset variant ref carried by an overlay key (#911 minimal v1):
|
|
38
|
+
* `{ "$value": <str|pluralDict>, "$asset": { kind, ref } }`. The translated
|
|
39
|
+
* `$value` resolves through `t()` as usual; `$asset` is exposed via
|
|
40
|
+
* `i18n.asset(key, ns?)`. */
|
|
41
|
+
interface AssetRef {
|
|
42
|
+
kind: string;
|
|
43
|
+
ref: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A language-catalog entry — the subset of the public `GET /v1/languages`
|
|
47
|
+
* catalog the SDK uses to expose text direction and endonyms. Regional
|
|
48
|
+
* variants (`is_variant`) inherit `rtl`/`script` from their `parent_code`.
|
|
49
|
+
*/
|
|
50
|
+
interface LanguageMeta {
|
|
51
|
+
/** BCP-47 code, e.g. `fr`, `fr-CA`, `zh-Hant`. */
|
|
52
|
+
code: Locale;
|
|
53
|
+
/** Endonym (name in its own language), e.g. `français (Canada)`. */
|
|
54
|
+
native_name?: string;
|
|
55
|
+
/** English name, e.g. `French (Canada)`. */
|
|
56
|
+
english_name?: string;
|
|
57
|
+
/** Right-to-left script. */
|
|
58
|
+
rtl?: boolean;
|
|
59
|
+
/** ISO 15924 script code, e.g. `Latn`, `Arab`, `Hans`. */
|
|
60
|
+
script?: string;
|
|
61
|
+
/** True for a regional/script variant (e.g. `fr-CA`, `zh-Hant`). */
|
|
62
|
+
is_variant?: boolean;
|
|
63
|
+
/** Base language of a variant, e.g. `fr-CA` → `fr`. */
|
|
64
|
+
parent_code?: Locale | null;
|
|
65
|
+
/** CLDR plural categories present for this language. */
|
|
66
|
+
plural_categories?: string[];
|
|
67
|
+
}
|
|
68
|
+
interface MissingKeyEvent {
|
|
69
|
+
key: string;
|
|
70
|
+
namespace: Namespace;
|
|
71
|
+
language_code: Locale;
|
|
72
|
+
/**
|
|
73
|
+
* Canonical source-language value the developer asked for, WHEN one is
|
|
74
|
+
* available: the explicit `defaultValue` from `t()` first, else the
|
|
75
|
+
* fallback-language bundle value. OMITTED (undefined) when neither exists —
|
|
76
|
+
* the SDK never sends the key name as a value (the key is already in `key`).
|
|
77
|
+
* The backend promotes only a non-null `source_value`.
|
|
78
|
+
*/
|
|
79
|
+
source_value?: string;
|
|
80
|
+
sdk_meta?: Record<string, unknown>;
|
|
81
|
+
}
|
|
82
|
+
type MissingHandlerMode = "send" | "log" | "off";
|
|
83
|
+
type Transport = (batch: MissingKeyEvent[]) => void | Promise<void>;
|
|
84
|
+
interface SonentaConfig {
|
|
85
|
+
/** API key — format `vrb_live_<prefix>.<secret>` with `missing:write` scope. */
|
|
86
|
+
token: string;
|
|
87
|
+
/** Project UUID this provider is bound to. */
|
|
88
|
+
projectUuid: string;
|
|
89
|
+
/** Namespaces to preload on mount. Defaults to `['common']`. */
|
|
90
|
+
namespaces?: Namespace[];
|
|
91
|
+
/**
|
|
92
|
+
* react-i18next-style alias for the default namespace. Convenience for
|
|
93
|
+
* single-namespace apps: when `namespaces` is omitted, the SDK loads
|
|
94
|
+
* `[defaultNS]`. Ignored when `namespaces` is provided (use that — its
|
|
95
|
+
* first entry is the default namespace).
|
|
96
|
+
*/
|
|
97
|
+
defaultNS?: Namespace;
|
|
98
|
+
/**
|
|
99
|
+
* How keys map to the bundle structure. `false` = **flat** (keys are looked
|
|
100
|
+
* up literally, so dotted keys like `"App Version 6.3.8"` work); a string =
|
|
101
|
+
* **nested**, split on that separator (default `"."`). Explicit value here is
|
|
102
|
+
* an override; when omitted, the SDK auto-detects the project's
|
|
103
|
+
* `key_style` / `key_separator` from the version metadata (#754).
|
|
104
|
+
*/
|
|
105
|
+
keySeparator?: string | false;
|
|
106
|
+
/**
|
|
107
|
+
* Separator between namespace and key in `t("ns:key")`. Default `":"`.
|
|
108
|
+
* Set `false` (or `""`) to disable namespace parsing so keys may contain
|
|
109
|
+
* `":"`. i18next-parity companion to `keySeparator`.
|
|
110
|
+
*/
|
|
111
|
+
nsSeparator?: string | false;
|
|
112
|
+
/**
|
|
113
|
+
* Embedded build-time snapshot of translation bundles, keyed
|
|
114
|
+
* `locale -> namespace -> i18next tree` (the same shape as the CDN JSON).
|
|
115
|
+
* Primed synchronously on construction so the FIRST render is instant and
|
|
116
|
+
* works OFFLINE (before the first CDN/runtime fetch); the provider then
|
|
117
|
+
* swaps in fresh data when it arrives, with no flash. A failed initial fetch
|
|
118
|
+
* (offline) keeps the snapshot as last-known-good. Generate it with the
|
|
119
|
+
* `verbumia snapshot` CLI, or manually (fetch the CDN JSON and import it).
|
|
120
|
+
*/
|
|
121
|
+
initialBundles?: Record<Locale, Record<Namespace, Record<string, unknown>>>;
|
|
122
|
+
/** Initial locale (BCP-47). */
|
|
123
|
+
defaultLocale: Locale;
|
|
124
|
+
/**
|
|
125
|
+
* Fallback locale(s) used when a key is missing in the active locale.
|
|
126
|
+
* Accepts a single locale or an ordered chain. Regional variants also fall
|
|
127
|
+
* back to their base language automatically (e.g. `fr-CA → fr`), so the full
|
|
128
|
+
* lookup order for an active `fr-CA` is `fr-CA → fr → fallbackLng…` — the
|
|
129
|
+
* `fr-CA → fr → source` chain (native i18next semantics). The CDN already
|
|
130
|
+
* serves variants as merged bundles, so this is defense-in-depth.
|
|
131
|
+
*/
|
|
132
|
+
fallbackLng?: Locale | Locale[];
|
|
133
|
+
/**
|
|
134
|
+
* Embedded language catalog (offline/SSR/React Native), same items as the
|
|
135
|
+
* public `GET /v1/languages`. Primed synchronously so `dir()` / `nativeName()`
|
|
136
|
+
* work before — or entirely without — the network fetch; a successful fetch
|
|
137
|
+
* augments it. Pairs well with {@link SonentaConfig.initialBundles}.
|
|
138
|
+
*/
|
|
139
|
+
languageCatalog?: LanguageMeta[];
|
|
140
|
+
/**
|
|
141
|
+
* Skip the best-effort fetch of the public language catalog
|
|
142
|
+
* (`GET {apiBase}/v1/languages`, no auth, CDN-cached) that powers `dir()` /
|
|
143
|
+
* `nativeName()`. Set when you don't need direction/endonym metadata, or
|
|
144
|
+
* you supply {@link SonentaConfig.languageCatalog} yourself.
|
|
145
|
+
*/
|
|
146
|
+
disableLanguageCatalog?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Interpolation hooks forwarded to i18next. Currently exposes `format`, the
|
|
149
|
+
* value formatter i18next invokes for `{{value, format}}` placeholders — wire
|
|
150
|
+
* your own date/number formatter here (the SDK does NOT bundle one).
|
|
151
|
+
*
|
|
152
|
+
* Example (date-fns):
|
|
153
|
+
* ```ts
|
|
154
|
+
* import { format as formatDate } from "date-fns";
|
|
155
|
+
* interpolation: {
|
|
156
|
+
* format: (v, f) =>
|
|
157
|
+
* f === "long" && v instanceof Date ? formatDate(v, "PPPP") : String(v),
|
|
158
|
+
* }
|
|
159
|
+
* ```
|
|
160
|
+
* i18next always keeps `escapeValue: false` (React escapes for us); only
|
|
161
|
+
* `format` is configurable here.
|
|
162
|
+
*/
|
|
163
|
+
interpolation?: {
|
|
164
|
+
/**
|
|
165
|
+
* Called by i18next for each `{{value, format}}` placeholder. `value` is the
|
|
166
|
+
* interpolation variable, `format` the token after the comma (e.g. `"long"`,
|
|
167
|
+
* `"number"`), `lng` the active language, `options` the full `t()` options.
|
|
168
|
+
* Return the rendered string.
|
|
169
|
+
*/
|
|
170
|
+
format?: (value: unknown, format: string | undefined, lng: string | undefined, options: Record<string, unknown>) => string;
|
|
171
|
+
};
|
|
172
|
+
/** Override the API base. Defaults to `https://api.verbumia.dev`. */
|
|
173
|
+
apiBase?: string;
|
|
174
|
+
/** Override the CDN base. Defaults to `https://cdn.verbumia.ca`. */
|
|
175
|
+
cdnBase?: string;
|
|
176
|
+
/**
|
|
177
|
+
* Optional plugins that hook into THIS provider's tree/registry — e.g.
|
|
178
|
+
* `@sonenta/feedback`. Plugins do NOT introduce a second React
|
|
179
|
+
* context; the provider calls `setup({ i18n, config })` once on mount
|
|
180
|
+
* and renders each plugin's `render()` as an ISOLATED sibling leaf
|
|
181
|
+
* after `children`, so enabling a plugin never re-renders the host app.
|
|
182
|
+
*/
|
|
183
|
+
plugins?: SonentaPlugin[];
|
|
184
|
+
/**
|
|
185
|
+
* Optional override for missing-key delivery (in-app inspector,
|
|
186
|
+
* Storybook, Cypress mocks). When set, replaces the default POST.
|
|
187
|
+
*/
|
|
188
|
+
transport?: Transport;
|
|
189
|
+
/** `send` (default) | `log` | `off` */
|
|
190
|
+
missingHandler?: MissingHandlerMode;
|
|
191
|
+
/** Flush cadence for the missing-key batch. Default 5_000ms. */
|
|
192
|
+
flushIntervalMs?: number;
|
|
193
|
+
/** Max events per batch before forcing a flush. Default 50. */
|
|
194
|
+
flushBatchSize?: number;
|
|
195
|
+
/** Optional ring buffer cap for `i18n.missingEvents`. Default 200. */
|
|
196
|
+
missingEventsBufferSize?: number;
|
|
197
|
+
/**
|
|
198
|
+
* Project version slug used when fetching bundles (BCP-style slug, e.g.
|
|
199
|
+
* `main`, `v2`). Maps to the
|
|
200
|
+
* `/p/{projectUuid}/{version}/latest/{lang}/{ns}.json` CDN path layout.
|
|
201
|
+
* Defaults to `main`. Included in the SDK's bundle cache keys, so two
|
|
202
|
+
* providers configured with different `version` values keep separate
|
|
203
|
+
* bundle caches.
|
|
204
|
+
*/
|
|
205
|
+
version?: string;
|
|
206
|
+
/**
|
|
207
|
+
* @deprecated Use {@link SonentaConfig.version} instead. Kept as a
|
|
208
|
+
* back-compat alias of `version`; if both are set, `version` wins.
|
|
209
|
+
*/
|
|
210
|
+
versionSlug?: string;
|
|
211
|
+
/**
|
|
212
|
+
* Surface variant (#911) — a second resolution dimension layered over the
|
|
213
|
+
* locale chain: `t()` returns the surface-specific value when an overlay
|
|
214
|
+
* provides one, else the base. Set the INITIAL surface here; it also
|
|
215
|
+
* becomes reactive when {@link SonentaConfig.surfaceBreakpoints} is set
|
|
216
|
+
* (the provider listens to the viewport on web). Omit to disable surface
|
|
217
|
+
* resolution entirely (base bundles only — fully back-compatible).
|
|
218
|
+
*/
|
|
219
|
+
surface?: Surface;
|
|
220
|
+
/**
|
|
221
|
+
* Enable reactive surface detection from the viewport width (web): the
|
|
222
|
+
* provider maps `window.innerWidth` → surface via these min-width
|
|
223
|
+
* thresholds and calls `setSurface` on resize. Pass `true` for the default
|
|
224
|
+
* ladder (mobile <640 <tablet <1024 ≤desktop) or custom thresholds. On
|
|
225
|
+
* React Native (no `window`), set the initial {@link SonentaConfig.surface}
|
|
226
|
+
* and drive changes via `i18n.setSurface(surfaceForWidth(width))` from your
|
|
227
|
+
* own `useWindowDimensions`. Ignored when `surface` is unset.
|
|
228
|
+
*/
|
|
229
|
+
surfaceBreakpoints?: SurfaceBreakpoints | boolean;
|
|
230
|
+
/**
|
|
231
|
+
* Deployment environment. Drives where the SDK fetches translations from:
|
|
232
|
+
*
|
|
233
|
+
* Maps to the customer's version model: a *promoted production*
|
|
234
|
+
* version is `"prod"`; any non-promoted (working) version is `"dev"`.
|
|
235
|
+
*
|
|
236
|
+
* - "prod" (default): fetch from `cdnBase/p/<project>/<version>/latest/...`.
|
|
237
|
+
* Cheap + cache-friendly. Freshness is the CDN `latest/` alias at
|
|
238
|
+
* `max-age=60s` — a republish is picked up within ~a minute.
|
|
239
|
+
* - "dev": fetch from `apiBase/v1/projects/<id>/translations/runtime`.
|
|
240
|
+
* Live data, no CDN delay; the `token` (an API key with
|
|
241
|
+
* env_type="dev" + populated ip/origin allowlist) is sent as
|
|
242
|
+
* `Authorization: ApiKey ...`.
|
|
243
|
+
*
|
|
244
|
+
* Browser callers: `Origin` is automatically sent and validated against
|
|
245
|
+
* the key's origin_allowlist. Node clients (SSR, scripts) don't send
|
|
246
|
+
* Origin and must rely on `ip_allowlist`.
|
|
247
|
+
*/
|
|
248
|
+
env?: "prod" | "dev";
|
|
249
|
+
}
|
|
250
|
+
/** Context handed to a plugin's `setup()` — the live i18n instance + the
|
|
251
|
+
* resolved provider config (apiBase, projectUuid, locale, …). A plugin
|
|
252
|
+
* reuses these instead of asking the customer to re-configure. */
|
|
253
|
+
interface SonentaPluginContext {
|
|
254
|
+
i18n: I18nInstance;
|
|
255
|
+
config: SonentaConfig;
|
|
256
|
+
/**
|
|
257
|
+
* #806 — subscribe to RUNTIME language changes (alternative B in the
|
|
258
|
+
* SeedSower diagnosis: a stable, public plugin-context hook that does
|
|
259
|
+
* not couple plugins to the private `_i18next` field). Fires every
|
|
260
|
+
* time the active language changes via `setLocale()` /
|
|
261
|
+
* `changeLanguage()` / the drop-in `i18n.i18next.changeLanguage()`
|
|
262
|
+
* path. The handler receives the NEW language (BCP-47). The returned
|
|
263
|
+
* function unsubscribes — plugins MUST call it from their `setup()`
|
|
264
|
+
* teardown, otherwise the subscription survives the host's provider
|
|
265
|
+
* unmount.
|
|
266
|
+
*
|
|
267
|
+
* ADDITIVE: existing plugins that ignore the field keep working; the
|
|
268
|
+
* provider supplies it on every mount from 1.0.5 onwards. The shape
|
|
269
|
+
* mirrors a standard React-style `subscribe → unsubscribe` so other
|
|
270
|
+
* framework ports of the SDK (Vue, Svelte) can implement the same
|
|
271
|
+
* contract.
|
|
272
|
+
*/
|
|
273
|
+
onLanguageChange(cb: (lng: Locale) => void): () => void;
|
|
274
|
+
}
|
|
275
|
+
/** A provider plugin. `setup` runs once on mount (optional teardown via
|
|
276
|
+
* the returned fn). `render` returns an isolated sibling node the
|
|
277
|
+
* provider mounts after `children` — its state never re-renders the app. */
|
|
278
|
+
interface SonentaPlugin {
|
|
279
|
+
name: string;
|
|
280
|
+
setup?: (ctx: SonentaPluginContext) => void | (() => void);
|
|
281
|
+
render?: () => ReactNode;
|
|
282
|
+
}
|
|
283
|
+
interface I18nInstance {
|
|
284
|
+
/** True once the initial namespace bundles loaded for the active locale. */
|
|
285
|
+
ready: boolean;
|
|
286
|
+
locale: Locale;
|
|
287
|
+
/** Alias of `locale` for react-i18next compatibility. */
|
|
288
|
+
language: Locale;
|
|
289
|
+
setLocale: (l: Locale) => Promise<void>;
|
|
290
|
+
/**
|
|
291
|
+
* Alias of `setLocale` for react-i18next compatibility. Resolves once the
|
|
292
|
+
* new locale's namespace bundles have loaded.
|
|
293
|
+
*/
|
|
294
|
+
changeLanguage: (l: Locale) => Promise<void>;
|
|
295
|
+
/**
|
|
296
|
+
* Translate a key. Exposed here mainly for out-of-React use via
|
|
297
|
+
* `getI18n()`; inside components prefer the `t` returned by
|
|
298
|
+
* `useTranslation()` (it also feeds the on-screen key registry).
|
|
299
|
+
*/
|
|
300
|
+
t: TranslationFunction;
|
|
301
|
+
/** Recently captured missing-key events (most recent first). */
|
|
302
|
+
missingEvents: MissingKeyEvent[];
|
|
303
|
+
/** Force-flush the missing-key batch now. */
|
|
304
|
+
flushMissing: () => Promise<void>;
|
|
305
|
+
/**
|
|
306
|
+
* Bust-refetch already-loaded bundles and re-render. Without `opts`, all
|
|
307
|
+
* loaded `(locale, ns)` bundles are refreshed; pass `locale`/`namespace`
|
|
308
|
+
* to narrow. Used by `@sonenta/realtime` on a `translations_published`
|
|
309
|
+
* push and for manual refresh.
|
|
310
|
+
*/
|
|
311
|
+
reload: (opts?: {
|
|
312
|
+
locale?: Locale;
|
|
313
|
+
namespace?: Namespace;
|
|
314
|
+
}) => Promise<void>;
|
|
315
|
+
/**
|
|
316
|
+
* Force every `useTranslation` consumer to re-render WITHOUT refetching —
|
|
317
|
+
* re-resolves `t()` against the CURRENT resources (both this SDK's hooks and
|
|
318
|
+
* react-i18next-native consumers on the exposed instance). For plugins that
|
|
319
|
+
* mutate i18next resources directly — e.g. `@sonenta/in-context` applies a
|
|
320
|
+
* live edit via `i18next.addResource` — and need the snapshot to repaint in
|
|
321
|
+
* place. Unlike {@link reload}, does NO fetch, so the override is not
|
|
322
|
+
* clobbered. Additive in 1.0.6.
|
|
323
|
+
*/
|
|
324
|
+
refresh: () => void;
|
|
325
|
+
/**
|
|
326
|
+
* Active surface variant (#911), or `undefined` when surface resolution is
|
|
327
|
+
* off. `t()` resolves surface-overlay values on top of the base bundle.
|
|
328
|
+
*/
|
|
329
|
+
surface: Surface | undefined;
|
|
330
|
+
/**
|
|
331
|
+
* Switch the active surface and recompose the loaded bundles (base ⊕ the
|
|
332
|
+
* new surface's sparse overlay), then re-render. Pass `undefined` to drop
|
|
333
|
+
* back to base-only. Loads each loaded namespace's `{ns}.{surface}.json`
|
|
334
|
+
* overlay on demand. The provider calls this from its viewport listener
|
|
335
|
+
* when `surfaceBreakpoints` is set; call it yourself on React Native.
|
|
336
|
+
*/
|
|
337
|
+
setSurface: (surface: Surface | undefined) => Promise<void>;
|
|
338
|
+
/**
|
|
339
|
+
* The asset variant ref for a key under the ACTIVE locale+surface (#911
|
|
340
|
+
* minimal v1), or `undefined` when the resolved key carries no `$asset`.
|
|
341
|
+
* `t(key)` still returns the key's `$value`; this exposes the companion
|
|
342
|
+
* asset (e.g. an icon/image ref) for the host to render.
|
|
343
|
+
*/
|
|
344
|
+
asset: (key: string, namespace?: Namespace) => AssetRef | undefined;
|
|
345
|
+
/**
|
|
346
|
+
* Text direction of a locale (defaults to the active locale) — i18next
|
|
347
|
+
* parity. Sourced from the language catalog's `rtl` (variant → base
|
|
348
|
+
* inheritance); falls back to a built-in RTL-language list when the catalog
|
|
349
|
+
* is not loaded. Apply to `<html dir>` or a container's `dir` attribute.
|
|
350
|
+
*/
|
|
351
|
+
dir: (lng?: Locale) => "ltr" | "rtl";
|
|
352
|
+
/**
|
|
353
|
+
* Endonym (native name) of a locale from the catalog — the fallback for
|
|
354
|
+
* runtimes WITHOUT `Intl.DisplayNames` (React Native/Hermes, SSR). Returns
|
|
355
|
+
* `undefined` when the catalog has no entry. For UI-localized names prefer
|
|
356
|
+
* `Intl.DisplayNames(uiLocale, { type: "language" }).of(code)`; use this
|
|
357
|
+
* when that API is unavailable.
|
|
358
|
+
*/
|
|
359
|
+
nativeName: (lng?: Locale) => string | undefined;
|
|
360
|
+
/**
|
|
361
|
+
* Full language-catalog entry for a locale (script, plural categories,
|
|
362
|
+
* parent, …), defaulting to the active locale; `undefined` if unknown.
|
|
363
|
+
*/
|
|
364
|
+
languageMeta: (lng?: Locale) => LanguageMeta | undefined;
|
|
365
|
+
/**
|
|
366
|
+
* The underlying real `i18next` instance powering this SDK (thin-wrapper,
|
|
367
|
+
* #805). Exposed for react-i18next DROP-IN: pass it to react-i18next's own
|
|
368
|
+
* `<Trans i18n={…}>` or `useTranslation(ns, { i18n })` for rich JSX, or call
|
|
369
|
+
* any i18next API directly. Present on instances created by this SDK.
|
|
370
|
+
*/
|
|
371
|
+
i18next?: i18n;
|
|
372
|
+
}
|
|
373
|
+
type TranslationOptions = Record<string, unknown> & {
|
|
374
|
+
defaultValue?: string;
|
|
375
|
+
};
|
|
376
|
+
interface TranslationFunction {
|
|
377
|
+
/**
|
|
378
|
+
* react-i18next-style positional fallback: `t('key', 'Default text')`,
|
|
379
|
+
* optionally with interpolation/options as a 3rd argument:
|
|
380
|
+
* `t('key', 'Hi {{name}}', { name })`.
|
|
381
|
+
*/
|
|
382
|
+
(key: string, defaultValue: string, options?: TranslationOptions): string;
|
|
383
|
+
/** Native form: `t('key', { defaultValue, ...interpolation })`. */
|
|
384
|
+
(key: string, options?: TranslationOptions): string;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
interface SonentaProviderProps extends SonentaConfig {
|
|
388
|
+
children: ReactNode;
|
|
389
|
+
}
|
|
390
|
+
declare function SonentaProvider({ children, ...config }: SonentaProviderProps): react_jsx_runtime.JSX.Element;
|
|
391
|
+
|
|
392
|
+
interface UseTranslationResult {
|
|
393
|
+
t: TranslationFunction;
|
|
394
|
+
i18n: I18nInstance;
|
|
395
|
+
}
|
|
396
|
+
/** React hook — returns `{ t, i18n }`. Optional `defaultNamespace` lets you
|
|
397
|
+
* drop the `ns:` prefix on every call.
|
|
398
|
+
*
|
|
399
|
+
* Every key this hook resolves during a render is recorded into the
|
|
400
|
+
* on-screen key registry (so a mounted `@sonenta/feedback` widget lists
|
|
401
|
+
* only the strings rendered on the current view — spec ltm 373). The
|
|
402
|
+
* contribution is keyed to THIS hook instance and dropped on unmount, so
|
|
403
|
+
* navigating away removes its keys automatically. */
|
|
404
|
+
declare function useTranslation(defaultNamespace?: string): UseTranslationResult;
|
|
405
|
+
|
|
406
|
+
interface TransProps {
|
|
407
|
+
/** The translation key (optionally `ns:key`). */
|
|
408
|
+
i18nKey: string;
|
|
409
|
+
/** Default value if the key is missing — used as the fallback string. */
|
|
410
|
+
defaults?: string;
|
|
411
|
+
/** Variables interpolated into `{{var}}` placeholders. */
|
|
412
|
+
values?: Record<string, unknown>;
|
|
413
|
+
/** JSX components mapped by 0-based numeric index — `<0>bold</0>` etc. */
|
|
414
|
+
components?: ReactNode[];
|
|
415
|
+
/** Optional namespace shortcut. */
|
|
416
|
+
namespace?: string;
|
|
417
|
+
}
|
|
418
|
+
/** Bare-bones Trans component: resolves the key, interpolates values, and
|
|
419
|
+
* swaps `<0>...</0>` placeholders into the supplied React components.
|
|
420
|
+
* Keeps the surface minimal — full Trans semantics (nested keys, plural
|
|
421
|
+
* trees, gender) land in V1.1. */
|
|
422
|
+
declare function Trans({ i18nKey, defaults, values, components, namespace, }: TransProps): react_jsx_runtime.JSX.Element;
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Access the active i18n instance OUTSIDE React components — the
|
|
426
|
+
* react-i18next-style standalone singleton (e.g. for `t()`/`changeLanguage()`
|
|
427
|
+
* in plain modules, stores, or helpers).
|
|
428
|
+
*
|
|
429
|
+
* Returns the instance created by the mounted `<SonentaProvider>`; throws a
|
|
430
|
+
* clear error if no provider is mounted yet. Assumes a single app-wide
|
|
431
|
+
* provider (the common case); with multiple concurrent providers it returns
|
|
432
|
+
* the most recently mounted one.
|
|
433
|
+
*/
|
|
434
|
+
declare function getI18n(): I18nInstance;
|
|
435
|
+
/**
|
|
436
|
+
* SAFE variant of {@link getI18n} (#805): returns the active i18n instance, or
|
|
437
|
+
* `null` when no provider is mounted yet — it does NOT throw. Use at module
|
|
438
|
+
* load / in plain helpers where a provider may not be mounted.
|
|
439
|
+
*/
|
|
440
|
+
declare function getI18nSafe(): I18nInstance | null;
|
|
441
|
+
/**
|
|
442
|
+
* SAFE out-of-React translate (#805). Resolves against the active i18n instance
|
|
443
|
+
* when a provider is mounted; otherwise returns `options.defaultValue` (when a
|
|
444
|
+
* string) or the `key` — it NEVER throws. This makes module-load-time / helper
|
|
445
|
+
* `t()` calls safe before mount (the throwing {@link getI18n} would break them).
|
|
446
|
+
* Accepts both shapes: `t('k', { defaultValue })` and `t('k', 'Default', opts?)`.
|
|
447
|
+
*/
|
|
448
|
+
declare function t(key: string, optionsOrDefault?: (Record<string, unknown> & {
|
|
449
|
+
defaultValue?: string;
|
|
450
|
+
count?: number;
|
|
451
|
+
}) | string, maybeOptions?: Record<string, unknown> & {
|
|
452
|
+
defaultValue?: string;
|
|
453
|
+
count?: number;
|
|
454
|
+
}): string;
|
|
455
|
+
|
|
456
|
+
/** Default transport: POST to `${apiBase}/v1/missing` with the API key. */
|
|
457
|
+
declare function defaultTransport(opts: {
|
|
458
|
+
apiBase: string;
|
|
459
|
+
token: string;
|
|
460
|
+
projectUuid: string;
|
|
461
|
+
}): Transport;
|
|
462
|
+
/** Logs each event to console.warn — handy for dev. */
|
|
463
|
+
declare const logTransport: Transport;
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* On-screen key registry — the PRODUCER side of the tiny cross-package
|
|
467
|
+
* contract that `@sonenta/feedback` consumes via
|
|
468
|
+
* `globalThis.__verbumia_key_registry__` (see `@sonenta/feedback`'s
|
|
469
|
+
* `core/keys.ts`).
|
|
470
|
+
*
|
|
471
|
+
* Why this exists: the feedback widget must list only the translation
|
|
472
|
+
* strings RENDERED on the current screen (spec ltm 373) — NOT every
|
|
473
|
+
* project string. The widget can't know what's on screen; the i18n SDK
|
|
474
|
+
* does, because it resolves the keys. The registry exposes a minimal
|
|
475
|
+
* global with TWO producer paths feeding it:
|
|
476
|
+
*
|
|
477
|
+
* 1. HOOK-LEVEL — our own `useTranslation` / `Trans` push their
|
|
478
|
+
* per-render key set via `_set(token, set)`. Mount-tracking handles
|
|
479
|
+
* navigation: when a component unmounts, its keys drop out of the
|
|
480
|
+
* union automatically.
|
|
481
|
+
* 2. INSTANCE-LEVEL — SonentaI18n wraps `i18next.t` so EVERY resolved
|
|
482
|
+
* key (including those resolved through react-i18next's NATIVE
|
|
483
|
+
* `useTranslation` / `<Trans>` bound to the exposed i18next, or
|
|
484
|
+
* through a direct `i18n.t()` call) feeds `_track(token, id)`. This
|
|
485
|
+
* makes the registry "instance-level producer", per #806 SeedSower
|
|
486
|
+
* diagnosis: a 1.0.2 thin-wrapper drop-in lets host apps keep their
|
|
487
|
+
* `from 'react-i18next'` imports, so the hook-level producer alone
|
|
488
|
+
* misses 100% of those keys. Without this, the widget shows "no
|
|
489
|
+
* strings on this view" even when the view is full of text.
|
|
490
|
+
*
|
|
491
|
+
* `snapshot()` is the UNION of both, deduped. The instance-level
|
|
492
|
+
* contribution accumulates for the i18n instance's lifetime (no per-
|
|
493
|
+
* component unmount signal), which is by-design: a stale superset is
|
|
494
|
+
* strictly better than a false empty.
|
|
495
|
+
*
|
|
496
|
+
* The published shape is intentionally tiny so any framework port of the
|
|
497
|
+
* i18n SDK can implement the same global without depending on feedback:
|
|
498
|
+
*
|
|
499
|
+
* globalThis.__verbumia_key_registry__ = {
|
|
500
|
+
* snapshot(): { namespace: string; key: string }[];
|
|
501
|
+
* isPopulated(): boolean;
|
|
502
|
+
* reset(): void;
|
|
503
|
+
* }
|
|
504
|
+
*/
|
|
505
|
+
interface DeclaredKey {
|
|
506
|
+
namespace: string;
|
|
507
|
+
key: string;
|
|
508
|
+
}
|
|
509
|
+
declare class KeyRegistry {
|
|
510
|
+
private _instances;
|
|
511
|
+
private _providers;
|
|
512
|
+
/** Replace an instance's contributed key set (per-render hook producer). */
|
|
513
|
+
_set(token: symbol, keys: Set<string>): void;
|
|
514
|
+
/** Append ONE id to a token's set, lazy-creating it. Used by the
|
|
515
|
+
* instance-level i18n.t wrap, which accumulates over the i18n
|
|
516
|
+
* instance's lifetime (no per-render reset semantics). Safe to call
|
|
517
|
+
* before `attach()` — the global publishes whenever a provider mounts. */
|
|
518
|
+
_track(token: symbol, id: string): void;
|
|
519
|
+
/** Drop an instance entirely (called on hook unmount or i18n stop). */
|
|
520
|
+
_delete(token: symbol): void;
|
|
521
|
+
/** Keys rendered by currently-mounted consumers. Stable insertion order. */
|
|
522
|
+
snapshot(): DeclaredKey[];
|
|
523
|
+
/** True when ANY producer has contributed ≥1 key. Cheap O(producers)
|
|
524
|
+
* check exposed for DEV-time integration asserts ("did my
|
|
525
|
+
* useTranslation imports end up wired to @sonenta/react-i18next?"). */
|
|
526
|
+
isPopulated(): boolean;
|
|
527
|
+
/** Escape hatch (router integrations / tests). Mount-tracking already
|
|
528
|
+
* handles navigation, so this is rarely needed. */
|
|
529
|
+
reset(): void;
|
|
530
|
+
/** Encode a resolved key into the internal id used by `_set`. */
|
|
531
|
+
encode(fullKey: string, defaultNamespace: string): string;
|
|
532
|
+
/** Provider mounted — publish the global (idempotent, ref-counted). */
|
|
533
|
+
attach(): void;
|
|
534
|
+
/** Provider unmounted — unpublish when the last one goes away. */
|
|
535
|
+
detach(): void;
|
|
536
|
+
}
|
|
537
|
+
/** Process-wide singleton — there is exactly one on-screen registry. */
|
|
538
|
+
declare const keyRegistry: KeyRegistry;
|
|
539
|
+
|
|
540
|
+
export { type AssetRef, DEFAULT_SURFACE_BREAKPOINTS, type DeclaredKey, type I18nInstance, type LanguageMeta, type Locale, type MissingHandlerMode, type MissingKeyEvent, type Namespace, type SonentaConfig, type SonentaPlugin, type SonentaPluginContext, SonentaProvider, type Surface, type SurfaceBreakpoints, Trans, type TranslationFunction, type TranslationOptions, type Transport, type SonentaConfig as VerbumiaConfig, type SonentaPlugin as VerbumiaPlugin, type SonentaPluginContext as VerbumiaPluginContext, SonentaProvider as VerbumiaProvider, defaultTransport, getI18n, getI18nSafe, keyRegistry, logTransport, surfaceForWidth, t, useTranslation };
|