@vireocodedev/localization 0.2.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 +179 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 vireocodedev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# @vireocodedev/localization
|
|
2
|
+
|
|
3
|
+
Framework-free localization resources and tooling shared by the Starter
|
|
4
|
+
packages. It is the single owner of the `platform`, `queryengine`, and `history`
|
|
5
|
+
i18next namespaces.
|
|
6
|
+
|
|
7
|
+
The package owns translation resources, namespace constants, resource
|
|
8
|
+
factories, imperative registration, deep-merge utilities, and locale-neutral
|
|
9
|
+
number formatting. It deliberately does not own React hooks, providers,
|
|
10
|
+
i18next initialization, locale detection, persistence, or application locale
|
|
11
|
+
policy.
|
|
12
|
+
|
|
13
|
+
The package has no React dependency and is safe to load in Node and Web Workers.
|
|
14
|
+
React consumers import namespace hooks from
|
|
15
|
+
`@vireocodedev/ui/react-i18next`.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @vireocodedev/localization i18next
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The package is published publicly on npm; installation requires no registry
|
|
24
|
+
authentication.
|
|
25
|
+
|
|
26
|
+
`i18next` is the only peer dependency. The package runs against the consuming
|
|
27
|
+
application's instance and never bundles its own copy.
|
|
28
|
+
|
|
29
|
+
TypeScript declarations are verified from the packed artifact with TypeScript
|
|
30
|
+
6, `moduleResolution: "Bundler"`, and `skipLibCheck: false`. Relative source
|
|
31
|
+
maps with embedded source content are published intentionally for debugging.
|
|
32
|
+
|
|
33
|
+
## Primary workflow
|
|
34
|
+
|
|
35
|
+
Create every Starter namespace for the locales your app supports, add the
|
|
36
|
+
application's own namespace, then pass the combined resources to an app-owned
|
|
37
|
+
i18next instance:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { createStarterResources } from "@vireocodedev/localization";
|
|
41
|
+
import { createInstance } from "i18next";
|
|
42
|
+
|
|
43
|
+
const locales = ["en", "hr"] as const;
|
|
44
|
+
const starterResources = createStarterResources({ locales });
|
|
45
|
+
const resources = {
|
|
46
|
+
en: { app: { home: { title: "Overview" } }, ...starterResources.en },
|
|
47
|
+
hr: { app: { home: { title: "Pregled" } }, ...starterResources.hr },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const i18next = createInstance();
|
|
51
|
+
await i18next.init({
|
|
52
|
+
defaultNS: "app",
|
|
53
|
+
initAsync: false,
|
|
54
|
+
lng: "hr",
|
|
55
|
+
fallbackLng: "en",
|
|
56
|
+
resources,
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Locales not shipped by Starter are seeded from English by default. Partial
|
|
61
|
+
overrides are deeply merged, so untranslated keys retain the seed value. Set
|
|
62
|
+
`seedFrom: "hr"` to use Croatian as the seed instead.
|
|
63
|
+
|
|
64
|
+
Every generated locale owns an isolated resource tree. Mutating one result does
|
|
65
|
+
not mutate the shipped base resources or another locale.
|
|
66
|
+
|
|
67
|
+
## Registering resources after initialization
|
|
68
|
+
|
|
69
|
+
Use `registerStarterResources` when an initialized instance needs the resources
|
|
70
|
+
later in its lifecycle:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { registerStarterResources } from "@vireocodedev/localization";
|
|
74
|
+
|
|
75
|
+
registerStarterResources(i18next, {
|
|
76
|
+
locales: ["en", "hr"],
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The function registers every Starter namespace. Per-namespace factories remain
|
|
81
|
+
available when a consumer intentionally needs only one namespace.
|
|
82
|
+
|
|
83
|
+
## React consumption
|
|
84
|
+
|
|
85
|
+
React adapters belong to Starter UI. In a React application, install
|
|
86
|
+
`initReactI18next` on the same app-owned instance **before its single call to
|
|
87
|
+
`init`**, then expose that instance through `I18nextProvider`; Starter UI's
|
|
88
|
+
hooks read that provider:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import type { PropsWithChildren } from "react";
|
|
92
|
+
import { I18nextProvider, initReactI18next } from "react-i18next";
|
|
93
|
+
import { usePlatformTranslation } from "@vireocodedev/ui/react-i18next";
|
|
94
|
+
|
|
95
|
+
const reactI18next = createInstance();
|
|
96
|
+
void reactI18next.use(initReactI18next).init({
|
|
97
|
+
defaultNS: "app",
|
|
98
|
+
fallbackLng: "en",
|
|
99
|
+
initAsync: false,
|
|
100
|
+
lng: "en",
|
|
101
|
+
resources,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export function AppLocalizationProvider({ children }: PropsWithChildren) {
|
|
105
|
+
return <I18nextProvider i18n={reactI18next}>{children}</I18nextProvider>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function SaveButton() {
|
|
109
|
+
const { t } = usePlatformTranslation();
|
|
110
|
+
return <button>{t("common.save")}</button>;
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`useQueryEngineTranslation` and `useHistoryTranslation` are available from the
|
|
115
|
+
same UI subpath. This package itself remains usable without React.
|
|
116
|
+
|
|
117
|
+
## Type safety
|
|
118
|
+
|
|
119
|
+
Augment i18next with the exported namespace resource types for strict keys and
|
|
120
|
+
autocomplete:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import type { HistoryResources, PlatformResources, QueryEngineResources } from "@vireocodedev/localization";
|
|
124
|
+
|
|
125
|
+
declare module "i18next" {
|
|
126
|
+
interface CustomTypeOptions {
|
|
127
|
+
resources: {
|
|
128
|
+
platform: PlatformResources;
|
|
129
|
+
queryengine: QueryEngineResources;
|
|
130
|
+
history: HistoryResources;
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Public API
|
|
137
|
+
|
|
138
|
+
| Export | Purpose |
|
|
139
|
+
| --------------------------------------------------------------------------- | ------------------------------------------------------------------- |
|
|
140
|
+
| `createStarterResources` | Build every Starter namespace for requested locales. |
|
|
141
|
+
| `registerStarterResources` | Register every namespace on a caller-owned i18next instance. |
|
|
142
|
+
| `createPlatformResources` | Build only the `platform` namespace. |
|
|
143
|
+
| `createQueryEngineResources` | Build only the `queryengine` namespace. |
|
|
144
|
+
| `createHistoryResources` | Build only the `history` namespace. |
|
|
145
|
+
| `STARTER_TRANSLATION_NAMESPACES`, `STARTER_BASE_LOCALES` | Shipped namespace and locale contracts. |
|
|
146
|
+
| `*_TRANSLATION_NAMESPACE`, `*_BASE_LOCALES` | Per-namespace constants. |
|
|
147
|
+
| `platformBaseResources`, `queryEngineBaseResources`, `historyBaseResources` | Shipped resource maps. |
|
|
148
|
+
| `createNamespaceResources` | Build a complete custom namespace from shipped seeds and overrides. |
|
|
149
|
+
| `deepMerge` | Immutable, prototype-safe merge used by resource factories. |
|
|
150
|
+
| `formatIntlNumber` | Format a number with caller-owned locale and fallback policy. |
|
|
151
|
+
| Resource/configuration utility types | Type namespace shapes, overrides, and custom factories. |
|
|
152
|
+
|
|
153
|
+
## Failure and versioning policy
|
|
154
|
+
|
|
155
|
+
Resource factories reject blank namespaces, empty locale sets, blank or
|
|
156
|
+
duplicate locale identifiers, missing seed locales, and overrides targeting a
|
|
157
|
+
locale that was not requested. Prototype-mutating override keys are ignored.
|
|
158
|
+
|
|
159
|
+
Translation keys and base locales are versioned contracts:
|
|
160
|
+
|
|
161
|
+
- adding a key, namespace, or locale is a minor release;
|
|
162
|
+
- renaming/removing a key or dropping a base locale is breaking;
|
|
163
|
+
- changing a shipped translation value is reviewed as user-visible behavior.
|
|
164
|
+
|
|
165
|
+
Explicit contract tests guard namespace keys and locale parity.
|
|
166
|
+
|
|
167
|
+
## Live documentation
|
|
168
|
+
|
|
169
|
+
The shared Vireo Starter Storybook contains the package's executable primary
|
|
170
|
+
workflow, late-registration path, custom-namespace toolkit, number formatting,
|
|
171
|
+
and failure semantics. Every displayed example imports this package through its
|
|
172
|
+
published entry point, is typechecked with the package, and executes from the
|
|
173
|
+
same source shown to readers.
|
|
174
|
+
|
|
175
|
+
## Scripts
|
|
176
|
+
|
|
177
|
+
- `npm run build` — build the ESM runtime and bundled declarations.
|
|
178
|
+
- `npm run typecheck` — typecheck source and tests without emitting.
|
|
179
|
+
- `npm run test` — run behavior, workflow, resource-contract, and architecture tests.
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vireocodedev/localization",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Foundation i18n toolkit and shared platform translations for the vireocodedev starter product.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/vireocodedev/starter.git",
|
|
11
|
+
"directory": "packages/localization"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"i18n",
|
|
15
|
+
"i18next",
|
|
16
|
+
"localization",
|
|
17
|
+
"starter"
|
|
18
|
+
],
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"module": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "vite build",
|
|
33
|
+
"dev": "vite build --watch --mode watch",
|
|
34
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
35
|
+
"test": "vitest run"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"i18next": ">=26 <27"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"i18next": "^26.4.0",
|
|
42
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
43
|
+
"vite": "^8.2.2",
|
|
44
|
+
"vite-plugin-dts": "^5.0.3",
|
|
45
|
+
"vitest": "^4.1.11"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public",
|
|
49
|
+
"provenance": true,
|
|
50
|
+
"registry": "https://registry.npmjs.org"
|
|
51
|
+
}
|
|
52
|
+
}
|