@owlmeans/i18n 0.1.18-rc.2 → 0.1.18-rc.20

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
@@ -11,7 +11,7 @@ Multi-level translation resource registration for OwlMeans applications.
11
11
  ## Installation
12
12
 
13
13
  ```bash
14
- bun add @owlmeans/i18n
14
+ bun add @owlmeans/i18n@^0.1.18-rc.19
15
15
  ```
16
16
 
17
17
  ## Usage
@@ -62,7 +62,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
62
62
  your project's skill store (`.agents/skills/`):
63
63
 
64
64
  ```sh
65
- npx @owlmeans/agent-skills
65
+ npx @owlmeans/agent-skills@^0.1.18-rc.24
66
66
  ```
67
67
 
68
68
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/i18n",
4
- "version": "0.1.18-rc.0",
5
- "generatedAt": "2026-08-16T22:20:50.497Z",
4
+ "version": "0.1.18-rc.20",
5
+ "generatedAt": "2026-09-15T12:59:01.020Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -8,7 +8,7 @@ user-invocable: false
8
8
  # @owlmeans/i18n
9
9
 
10
10
  **Layer:** Core (no runtime deps)
11
- **Install:** `"@owlmeans/i18n": "^0.1.18-rc.0"` in `dependencies`
11
+ **Install:** `"@owlmeans/i18n": "^0.1.18-rc.20"` in `dependencies`
12
12
 
13
13
  ## Purpose
14
14
 
@@ -21,11 +21,27 @@ Global registration store that packages write into at import time. React clients
21
21
  | `addI18nLib(lng, resource, data, opts?)` | Register library-owned strings (ns defaults to `'lib'`) |
22
22
  | `addI18nApp(lng, resource, data, opts?)` | Register app-owned strings (ns defaults to resource name) |
23
23
  | `initI18nResource(lng, resource, ns?)` | Drain a registered bundle for a language (called by client-i18n) |
24
- | `SUPPORTED_LNGS` | `['en','pl','ru','be','uk','es','de']` — the canonical language set |
24
+ | `SUPPORTED_LNGS` / `SupportedLng` | `['en','pl','ru','be','uk','es','de']` — the canonical language set, and its union type |
25
25
  | `DEFAULT_LNG` | `'en'` |
26
26
  | `LIB_NAMESPACE` | `'lib'` |
27
+ | `DEFAULT_NAMESPACE` | `'translation'` — i18next's own default namespace, used whenever a lookup names none and `I18nConfig.defaultNs` is unset |
27
28
  | `I18nTier` | `Library \| App` — enum used internally |
28
29
  | `I18nConfig` | `{ defaultLng?, defaultNs?, fallbackLng?, supportedLngs? }` |
30
+ | `I18nResourceOptions` | `{ ns?, priority? }` — the `opts` every `add*` takes |
31
+ | `MAX_PRIORITY` | `Number.MAX_SAFE_INTEGER` — the value substituted for an unset `priority`, which is what makes an unset one sort last |
32
+
33
+ `opts` also accepts a bare string, which is read as `ns`: `addI18nLib('en', 'wallet', walletEn, 'did')`.
34
+
35
+ ## Subpath Exports
36
+
37
+ - `./utils` — the store itself: `_OwlMeansI18nStorage` (`{ data }`, keyed ns → resource → language),
38
+ `ensureStructure(lng, resource, ns?)` which creates and returns one slot, and `tierCost`, the
39
+ `I18nTier` → number map the sort is written against.
40
+
41
+ Reach for `./utils` only to work around the drain-once rule below: assigning
42
+ `_OwlMeansI18nStorage.data = {}` empties every slot including its `lngInitialized` marks, so a
43
+ suite can register and drain the same resource repeatedly. This package's own tests do exactly
44
+ that between cases. Application and library code registers through `addI18nLib` / `addI18nApp`.
29
45
 
30
46
  ## Tiers
31
47
 
@@ -34,7 +50,30 @@ Global registration store that packages write into at import time. React clients
34
50
  | Library | `addI18nLib` | `'lib'` | Any `@owlmeans/*` package |
35
51
  | App | `addI18nApp` | resource name | Project-specific app / shared project package |
36
52
 
37
- App-tier strings deep-merge **over** Library-tier strings for the same keys at resolution time — this is the override mechanism.
53
+ App-tier strings deep-merge **over** Library-tier strings at resolution time — but only for the
54
+ same **(ns, resource, language)** slot, because that triple is the address the store is keyed on
55
+ and the only thing `initI18nResource` drains. The default namespaces differ (`'lib'` for
56
+ `addI18nLib`, the resource name for `addI18nApp`), so overriding a library bundle means saying so:
57
+
58
+ ```typescript
59
+ import { addI18nApp, LIB_NAMESPACE } from '@owlmeans/i18n'
60
+
61
+ addI18nApp('en', 'errors', myErrors, { ns: LIB_NAMESPACE })
62
+ ```
63
+
64
+ Without `{ ns: LIB_NAMESPACE }` the app bundle lands in namespace `errors` while the library's sits
65
+ in `lib`. Nothing errors, nothing merges, and the library strings keep rendering.
66
+
67
+ Within one tier the order is `priority`, ascending, and every bundle is merged over the one before
68
+ it — so the **last** applied wins. A registration that states no `priority` sorts last and
69
+ therefore beats every one that states a number: `priority` lowers a bundle in the stack rather than
70
+ raising it. Leave it unset unless one library must lose to another.
71
+
72
+ **A bundle only reaches i18next if it was registered before the first draw for its language.**
73
+ `initI18nResource` marks the (ns, resource, language) slot drained and answers `null` for every
74
+ later call, so an `import '@owlmeans/<pkg>'` evaluated after a screen has rendered adds nothing a
75
+ component can read. Register at module load — a side-effect import at the top of the entry file,
76
+ which is what re-exporting `./i18n.js` from `src/index.ts` achieves.
38
77
 
39
78
  ## Per-package pattern
40
79
 
@@ -28,7 +28,7 @@ The **resource name** is a stable identifier for the registering package, e.g. `
28
28
 
29
29
  ## Compound prefix keys
30
30
 
31
- A key like `t('title')` resolves to `namespace : resource.prefix.key`. The prefix is composed by joining segments with `.` via `composePrefix` (never by hand-concatenating strings).
31
+ A key like `t('title')` resolves to `namespace : resource.prefix.key`. The prefix is composed by joining segments with `.` via `composePrefix` — exported from `@owlmeans/client-i18n` (and re-exported by `@owlmeans/web-panel` and `@owlmeans/mui-panel`), never by hand-concatenating strings.
32
32
 
33
33
  Example chain:
34
34
  ```
@@ -44,31 +44,59 @@ t('title')
44
44
 
45
45
  ## Context-based prefix switching
46
46
 
47
- Use `PanelContext` (from `@owlmeans/client-panel`) to inject `resource`, `ns`, or `prefix` into a React sub-tree. Child components that call `usePanelI18n()` or `useFormI18n()` automatically pick up the context value.
47
+ Use `PanelContext` (from `@owlmeans/client-panel`) to inject `resource`, `ns` or `prefix` into a
48
+ React sub-tree. Child components that call `usePanelI18n()` pick those three up, and a nested
49
+ `PanelContext` inherits the outer one field by field.
48
50
 
49
51
  ```tsx
50
- // Override the active namespace/resource for a sub-tree
51
- <PanelContext resource="wl-manager" ns="lib" prefix="wl-dns">
52
- <DnsForm /> {/* DnsForm calls usePanelI18n() — gets ns='lib', resource='wl-manager', prefix='wl-dns' */}
52
+ // Read a library's own bundle from inside an app sub-tree
53
+ <PanelContext resource="payment" ns="lib" prefix="plan">
54
+ <Text name="label.monthly" /> {/* usePanelI18n() → lib:payment.plan.label.monthly */}
53
55
  </PanelContext>
54
56
  ```
55
57
 
56
- Use `i18n` props on individual components to override just one level:
58
+ `suppress` is **not** one of them. `TPanelContext` accepts it because it spreads `I18nBaseProps`,
59
+ but `usePanelI18n` reads only `prefix`, `resource` and `ns`, so a `<PanelContext suppress>` changes
60
+ nothing for any child. Suppression is per component, from that component's own `i18n` prop — which
61
+ is what `Button` and `ActionCtrl` check before translating a label.
62
+
63
+ **Form fields sit in a different context.** `useFormI18n` reads the form context that `FormContext`
64
+ publishes from the enclosing `Form`'s own `i18n` and `name` props; it never touches `PanelContext`.
65
+ So wrapping a form or a field in `<PanelContext …>` changes nothing for any field — redirect a
66
+ field by naming the enclosing `Form` or by giving that `Form` an `i18n` prop.
67
+
68
+ Use the `i18n` prop on an individual component to override just one level. It is declared by the
69
+ components whose props extend `I18nProps` — `Block`, `Text`, `Link`, `Status`, `Button` and `Form`
70
+ in both panel families:
57
71
  ```tsx
58
- <StatusLabel i18n={{ prefix: 'my-status' }} />
72
+ <Status i18n={{ prefix: 'my-status' }} />
59
73
  ```
60
74
 
75
+ Not every component carrying copy has it, and the two that lack it read different contexts.
76
+ `TextInput` — props extend `FormFieldProps` (`name`, `def`) and add `label`, `placeholder`, `hint`,
77
+ `type` and `disableAutocomplete` — resolves `<name>.label`, `<name>.placeholder` and `<name>.hint`
78
+ through `useFormI18n` when the matching prop is `true`, and renders the prop's own string when it
79
+ is given one; redirect it through the enclosing `Form`. `ButtonSelector` — `SelectorProps` is `name`,
80
+ `current`, `options` and `onSelect` — renders one `Button` per option labelled `<name>.<option>`,
81
+ and `Button` resolves through `usePanelI18n` with the app `buttons` and `lib:client-panel.buttons`
82
+ fallbacks; a surrounding `PanelContext` is what redirects it.
83
+
61
84
  ## App-level override of library strings
62
85
 
63
- App-tier registrations deep-merge over Library-tier for the same `(ns, resource)`:
86
+ App-tier registrations deep-merge over Library-tier for the same `(ns, resource)` — and the
87
+ namespace has to be said out loud, because `addI18nApp` defaults it to the **resource** name while
88
+ the library's bundle sits in `lib`:
64
89
  ```typescript
65
- import '@owlmeans/error' // Library tier: lib:errors.*
66
- import { addI18nApp } from '@owlmeans/i18n'
90
+ import '@owlmeans/error' // Library tier: lib:errors.*
91
+ import { addI18nApp, LIB_NAMESPACE } from '@owlmeans/i18n'
67
92
  import myErrors from './i18n/en.json'
68
93
 
69
- addI18nApp('en', 'errors', myErrors) // App tier wins for matching keys
94
+ addI18nApp('en', 'errors', myErrors, { ns: LIB_NAMESPACE }) // App tier wins for matching keys
70
95
  ```
71
96
 
97
+ Drop `{ ns: LIB_NAMESPACE }` and the app bundle lands in namespace `errors` while `useI18nLib('errors')`
98
+ reads `lib`. Nothing errors and the library strings keep rendering.
99
+
72
100
  ## Per-package checklist
73
101
 
74
102
  When adding translatable strings to any package:
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=advertise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advertise.d.ts","sourceRoot":"","sources":["../src/advertise.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import { apiConfigPlugin } from '@owlmeans/api-config';
2
+ apiConfigPlugin({
3
+ allow: {
4
+ i18n: {
5
+ defaultLng: true,
6
+ defaultNs: true,
7
+ fallbackLng: true,
8
+ supportedLngs: true,
9
+ },
10
+ },
11
+ });
12
+ //# sourceMappingURL=advertise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advertise.js","sourceRoot":"","sources":["../src/advertise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEtD,eAAe,CAAC;IACd,KAAK,EAAE;QACL,IAAI,EAAE;YACJ,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE,IAAI;SACpB;KACF;CACF,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/i18n",
3
- "version": "0.1.18-rc.2",
3
+ "version": "0.1.18-rc.20",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {