@owlmeans/client-i18n 0.1.6 → 0.1.8
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
|
@@ -59,3 +59,20 @@ Returns a `t()` function for shared/common translations.
|
|
|
59
59
|
## Related Packages
|
|
60
60
|
|
|
61
61
|
- [`@owlmeans/i18n`](../i18n) — `addI18nApp`, `addI18n` to register translations before render
|
|
62
|
+
|
|
63
|
+
<!-- owlmeans:agent-guidance:start -->
|
|
64
|
+
## Agent guidance
|
|
65
|
+
|
|
66
|
+
This package ships embedded Claude Code skills and GitHub Copilot instructions under
|
|
67
|
+
`agent-meta/`. After installing your `@owlmeans/*` packages, run the OwlMeans
|
|
68
|
+
agent-skills installer to place them into your project's native locations
|
|
69
|
+
(`.claude/skills/` and `.github/instructions/`):
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
npx @owlmeans/agent-skills
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The embedded files are version-matched to this package release. Do not edit them
|
|
76
|
+
directly — they are regenerated on each publish. To contribute guidance edits,
|
|
77
|
+
open a PR against the source monorepo.
|
|
78
|
+
<!-- owlmeans:agent-guidance:end -->
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "How to use @owlmeans/client-i18n — React i18next wrapper with lazy bundle loading and language persistence. Use when setting up i18n in a React app or adding translation hooks."
|
|
3
|
+
applyTo: "**/*.ts, **/*.tsx"
|
|
4
|
+
---
|
|
5
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
6
|
+
|
|
7
|
+
# @owlmeans/client-i18n
|
|
8
|
+
|
|
9
|
+
**Layer:** Client (React)
|
|
10
|
+
**Version:** `"@owlmeans/client-i18n": "^0.1.8"`
|
|
11
|
+
|
|
12
|
+
## Key exports
|
|
13
|
+
|
|
14
|
+
| Export | Description |
|
|
15
|
+
|--------|-------------|
|
|
16
|
+
| `I18nContext` | Provider — wraps the app tree |
|
|
17
|
+
| `useI18nLib(resource, prefix?)` | Hook for library strings (ns=`'lib'`) |
|
|
18
|
+
| `useI18nApp(resource?, prefix?)` | Hook for app strings (ns=resource name) |
|
|
19
|
+
| `useI18n(resource, ns?, prefix?)` | Low-level explicit hook |
|
|
20
|
+
| `useLanguage()` | `[lng, setLng]` — read/switch active language |
|
|
21
|
+
| `composePrefix(parent?, child?)` | Dot-join for prefix segments |
|
|
22
|
+
| `I18nProps`, `I18nBaseProps` | Prop types for i18n overrides |
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { I18nContext } from '@owlmeans/client-i18n'
|
|
28
|
+
<I18nContext config={clientConfig}><App /></I18nContext>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Translation hooks
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// Library component
|
|
35
|
+
const t = useI18nLib('errors', 'form') // lib:errors.form.*
|
|
36
|
+
t('minLength')
|
|
37
|
+
|
|
38
|
+
// App component
|
|
39
|
+
const t = useI18nApp(undefined, 'home') // appName:appName.home.*
|
|
40
|
+
t('title')
|
|
41
|
+
|
|
42
|
+
// Language switcher
|
|
43
|
+
const [lng, setLng] = useLanguage()
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Key invariants
|
|
47
|
+
|
|
48
|
+
- Use `useI18nLib` in `@owlmeans/*` packages, `useI18nApp` in app/project packages.
|
|
49
|
+
- Never hardcode UI strings — always use a translation hook.
|
|
50
|
+
- Language is persisted in `localStorage` under `owlmeans-lng`.
|
|
51
|
+
|
|
52
|
+
## Depends On
|
|
53
|
+
|
|
54
|
+
`@owlmeans/i18n`, `@owlmeans/client-context`, `i18next`, `react-i18next`, `react` (peer)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"package": "@owlmeans/client-i18n",
|
|
4
|
+
"version": "0.1.8",
|
|
5
|
+
"generatedAt": "2026-06-11T16:30:27.171Z",
|
|
6
|
+
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
|
+
"entries": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "skill",
|
|
10
|
+
"name": "client-i18n",
|
|
11
|
+
"category": "package-specific",
|
|
12
|
+
"file": "skills/client-i18n/SKILL.md",
|
|
13
|
+
"canonicalPath": ".claude/skills/client-i18n/SKILL.md"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"kind": "instruction",
|
|
17
|
+
"name": "client-i18n",
|
|
18
|
+
"category": "package-specific",
|
|
19
|
+
"file": "instructions/client-i18n.instructions.md",
|
|
20
|
+
"canonicalPath": ".github/instructions/client-i18n.instructions.md"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: client-i18n
|
|
3
|
+
description: How to use @owlmeans/client-i18n — React i18n context built on i18next. Auto-invoked when setting up translation in a React app, using translation hooks, or working with language switching.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
7
|
+
|
|
8
|
+
# @owlmeans/client-i18n
|
|
9
|
+
|
|
10
|
+
**Layer:** Client (React)
|
|
11
|
+
**Install:** `"@owlmeans/client-i18n": "^0.1.8"` in `dependencies`
|
|
12
|
+
|
|
13
|
+
## Purpose
|
|
14
|
+
|
|
15
|
+
Wraps i18next + react-i18next, lazily loads registered bundles from `@owlmeans/i18n` storage into the i18next instance, and provides hooks for translating strings.
|
|
16
|
+
|
|
17
|
+
## Key Exports
|
|
18
|
+
|
|
19
|
+
| Export | Description |
|
|
20
|
+
|--------|-------------|
|
|
21
|
+
| `I18nContext` | Provider component — wraps the React tree with an i18next instance |
|
|
22
|
+
| `useI18nLib(resource, prefix?)` | Hook for library strings (ns=`'lib'`) |
|
|
23
|
+
| `useI18nApp(resource?, prefix?)` | Hook for app strings (ns=resource name; defaults to `context.cfg.service`) |
|
|
24
|
+
| `useI18n(resource, ns?, prefix?)` | Low-level hook with explicit ns — use when ns ≠ resource |
|
|
25
|
+
| `useLanguage()` | `[currentLng, setLng]` — read and switch the active language |
|
|
26
|
+
| `composePrefix(parent?, child?)` | Canonical dot-join for prefix chaining; never call manually in panel code — used internally |
|
|
27
|
+
| `I18nBaseProps` | `{ resource?, ns?, prefix?, suppress? }` |
|
|
28
|
+
| `I18nProps` | `{ i18n?: I18nBaseProps }` |
|
|
29
|
+
|
|
30
|
+
## Setup (app root)
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { I18nContext } from '@owlmeans/client-i18n'
|
|
34
|
+
|
|
35
|
+
function App() {
|
|
36
|
+
return (
|
|
37
|
+
<I18nContext config={clientConfig}>
|
|
38
|
+
<Routes />
|
|
39
|
+
</I18nContext>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`clientConfig.i18n` is optional; it defaults to `SUPPORTED_LNGS` and `'en'` fallback.
|
|
45
|
+
|
|
46
|
+
## Language persistence
|
|
47
|
+
|
|
48
|
+
The active language is persisted in `localStorage` under `owlmeans-lng` and restored on init.
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
function LangSwitch() {
|
|
52
|
+
const [lng, setLng] = useLanguage()
|
|
53
|
+
return (
|
|
54
|
+
<select value={lng} onChange={e => setLng(e.target.value)}>
|
|
55
|
+
{['en','pl','ru','be','uk','es','de'].map(l => (
|
|
56
|
+
<option key={l} value={l}>{l}</option>
|
|
57
|
+
))}
|
|
58
|
+
</select>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Hooks
|
|
64
|
+
|
|
65
|
+
### useI18nLib — library packages
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// In a React component inside a library package
|
|
69
|
+
const t = useI18nLib('errors') // loads lib:errors
|
|
70
|
+
const t = useI18nLib('errors', 'form') // keyPrefix = errors.form
|
|
71
|
+
t('minLength') // → lib:errors.form.minLength
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### useI18nApp — app-level / project packages
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const t = useI18nApp() // uses context.cfg.service as resource+ns
|
|
78
|
+
const t = useI18nApp('my-app', 'home-screen') // explicit resource + prefix
|
|
79
|
+
t('title') // → my-app:my-app.home-screen.title
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### useI18n — explicit resource + ns
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// When ns and resource differ (e.g. DID namespace)
|
|
86
|
+
const t = useI18n('wallet', 'did', 'createKey')
|
|
87
|
+
t('title') // → did:wallet.createKey.title
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Key resolution path
|
|
91
|
+
|
|
92
|
+
`useI18nLib('res', 'prefix')` → `t('key')`
|
|
93
|
+
→ i18next lookup: namespace=`lib`, keyPath=`res.prefix.key`
|
|
94
|
+
→ bundle was loaded as `{ res: jsonData }` into namespace `lib`
|
|
95
|
+
→ resolved value is `jsonData.prefix.key`
|
|
96
|
+
|
|
97
|
+
## App-level override of library strings
|
|
98
|
+
|
|
99
|
+
Import the library's i18n registration **and** register your own version at App tier:
|
|
100
|
+
```typescript
|
|
101
|
+
import '@owlmeans/error/i18n' // library en strings
|
|
102
|
+
import { addI18nApp } from '@owlmeans/i18n'
|
|
103
|
+
import myErrors from './i18n/en.json' // with { type: 'json' }
|
|
104
|
+
|
|
105
|
+
// App tier wins — these override the library's 'errors' strings
|
|
106
|
+
addI18nApp('en', 'errors', myErrors)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Depends On
|
|
110
|
+
|
|
111
|
+
`@owlmeans/i18n`, `@owlmeans/client-context`, `i18next`, `react-i18next`, `react` (peer)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/client-i18n",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"typescript": "^6.0.2"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@owlmeans/client": "^0.1.
|
|
41
|
-
"@owlmeans/client-context": "^0.1.
|
|
42
|
-
"@owlmeans/i18n": "^0.1.
|
|
40
|
+
"@owlmeans/client": "^0.1.8",
|
|
41
|
+
"@owlmeans/client-context": "^0.1.8",
|
|
42
|
+
"@owlmeans/i18n": "^0.1.8",
|
|
43
43
|
"i18next": "^23.15.1",
|
|
44
44
|
"react-i18next": "^15.0.2"
|
|
45
45
|
},
|