@orderly.network/i18n 2.12.0 → 2.12.1
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 +27 -314
- package/bin/cli.js +92 -37
- package/dist/{constant-D_rlt5w0.d.mts → constant-DkvDyddr.d.mts} +12 -40
- package/dist/{constant-D_rlt5w0.d.ts → constant-DkvDyddr.d.ts} +12 -40
- package/dist/constant.d.mts +1 -1
- package/dist/constant.d.ts +1 -1
- package/dist/constant.js.map +1 -1
- package/dist/constant.mjs.map +1 -1
- package/dist/index.d.mts +84 -20
- package/dist/index.d.ts +84 -20
- package/dist/index.js +138 -107
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +129 -106
- package/dist/index.mjs.map +1 -1
- package/dist/locale.csv +7 -105
- package/dist/locales/de.json +7 -37
- package/dist/locales/en.json +7 -37
- package/dist/locales/es.json +7 -37
- package/dist/locales/fr.json +7 -37
- package/dist/locales/id.json +7 -37
- package/dist/locales/it.json +7 -37
- package/dist/locales/ja.json +7 -37
- package/dist/locales/ko.json +7 -37
- package/dist/locales/nl.json +7 -37
- package/dist/locales/pl.json +7 -37
- package/dist/locales/pt.json +7 -37
- package/dist/locales/ru.json +7 -37
- package/dist/locales/tc.json +7 -37
- package/dist/locales/tr.json +7 -37
- package/dist/locales/uk.json +7 -37
- package/dist/locales/vi.json +7 -37
- package/dist/locales/zh.json +7 -37
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +25 -50
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +25 -50
- package/dist/utils.mjs.map +1 -1
- package/docs/guide/AGENTS.md +109 -0
- package/docs/guide/cli.md +133 -0
- package/docs/guide/examples.md +455 -0
- package/docs/guide/exports.md +14 -0
- package/docs/guide/integration.md +223 -0
- package/docs/guide/utils.md +14 -0
- package/package.json +13 -11
- package/{script → scripts}/copyLocales.js +1 -1
- package/scripts/filterLocaleKeys.js +127 -0
- package/{script → scripts}/generateCsv.js +3 -3
- package/{script → scripts}/utils.js +20 -14
- /package/{script → scripts}/csv2json.js +0 -0
- /package/{script → scripts}/diffCsv.js +0 -0
- /package/{script → scripts}/fillJson.js +0 -0
- /package/{script → scripts}/generateEnJson.js +0 -0
- /package/{script → scripts}/generateMissingKeys.js +0 -0
- /package/{script → scripts}/json-csv-converter.js +0 -0
- /package/{script → scripts}/json2csv.js +0 -0
- /package/{script → scripts}/mergeJson.js +0 -0
- /package/{script → scripts}/separateJson.js +0 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
**Prerequisite:** Read [Integration guide](./integration.md) first—especially [§1 Wrap Your App with LocaleProvider](./integration.md#1-wrap-your-app-with-localeprovider) (props and behavior) and [§4 Integrate external resources](./integration.md#4-integrate-external-resources) (`registerResources` and external bundles)—so these recipes align with how the package loads data.
|
|
4
|
+
|
|
5
|
+
Pick a section by goal:
|
|
6
|
+
|
|
7
|
+
| Goal | Section |
|
|
8
|
+
| --------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
9
|
+
| Vite + `import.meta.glob`, merge SDK base + extend JSON | [Async resources (Vite)](#async-resources-vite) |
|
|
10
|
+
| Next.js (webpack) + explicit per-locale `import()` for SDK JSON | [Async resources (Next.js and webpack)](#async-resources-nextjs-and-webpack) |
|
|
11
|
+
| JSON under `public/`, load via HTTP `backend.loadPath` | [HTTP backend](#http-backend) |
|
|
12
|
+
| Static `Resources` map (sync imports) | [Sync resources](#sync-resources) |
|
|
13
|
+
| Subset of locales in the picker | [Custom languages](#custom-languages) |
|
|
14
|
+
| Locale in the URL (e.g. `/en/...`) when switching language | [onLanguageChanged (URL sync)](#onlanguagechanged-url-sync) |
|
|
15
|
+
|
|
16
|
+
**Recommendations:** Prefer **`AsyncResources`** with Vite **`import.meta.glob`** or Next.js **explicit base imports**; use **`backend.loadPath`** when serving JSON from `public/`. On Next/webpack, do **not** rely on `import.meta.glob`—see [Async resources (Next.js and webpack)](#async-resources-nextjs-and-webpack).
|
|
17
|
+
|
|
18
|
+
## Table of Contents
|
|
19
|
+
|
|
20
|
+
- **Locale loading**
|
|
21
|
+
- [Async resources (Vite)](#async-resources-vite)
|
|
22
|
+
- [Async resources (Next.js and webpack)](#async-resources-nextjs-and-webpack)
|
|
23
|
+
- [HTTP backend](#http-backend)
|
|
24
|
+
- [Sync resources](#sync-resources)
|
|
25
|
+
- [Custom languages](#custom-languages)
|
|
26
|
+
- [onLanguageChanged (URL sync)](#onlanguagechanged-url-sync)
|
|
27
|
+
|
|
28
|
+
## Async resources (Vite)
|
|
29
|
+
|
|
30
|
+
_Bundled SDK + extend JSON. Pass an `AsyncResources` loader to `LocaleProvider`._
|
|
31
|
+
|
|
32
|
+
Use this pattern when you use **Vite** (or a compatible bundler with `import.meta.glob`). Glob patterns **must be string literals** so the bundler can analyze them at build time—do not build paths from variables or template concatenation.
|
|
33
|
+
|
|
34
|
+
- **Base SDK strings:** glob `node_modules/@orderly.network/i18n/dist/locales/*.json` (path may differ slightly depending on your install layout).
|
|
35
|
+
- **Extend keys:** glob your app’s locale files (example: `./locales/*.json`—adjust the relative path to match your project).
|
|
36
|
+
- For **`en`**, return your imported extend file only: the English base is already registered by the package, so you avoid an extra base fetch.
|
|
37
|
+
- For other locales, `Promise.all` base + extend and merge. **`importLocaleJsonModule`** normalizes each module’s `default` export.
|
|
38
|
+
|
|
39
|
+
**Reference implementation:** WOOFi-dex `src/components/orderlyProvider/orderlyLocaleProvider.tsx` (same merge and `en` optimization; glob keys must match your file locations).
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { FC, ReactNode } from "react";
|
|
43
|
+
import {
|
|
44
|
+
AsyncResources,
|
|
45
|
+
LocaleProvider,
|
|
46
|
+
LocaleCode,
|
|
47
|
+
importLocaleJsonModule,
|
|
48
|
+
type LocaleJsonModule,
|
|
49
|
+
LocaleEnum,
|
|
50
|
+
} from "@orderly.network/i18n";
|
|
51
|
+
import { WalletConnectorProvider } from "@orderly.network/wallet-connector";
|
|
52
|
+
import { OrderlyAppProvider } from "@orderly.network/react-app";
|
|
53
|
+
import extendEnLocale from "./locales/en.json";
|
|
54
|
+
|
|
55
|
+
// Glob patterns must be static string literals (Vite resolves them at build time).
|
|
56
|
+
const baseLoaders = import.meta.glob<LocaleJsonModule>(
|
|
57
|
+
"/node_modules/@orderly.network/i18n/dist/locales/*.json",
|
|
58
|
+
);
|
|
59
|
+
// Adjust this glob to where your app stores extend locale JSON (e.g. "../../locales/*.json").
|
|
60
|
+
const extendLoaders = import.meta.glob<LocaleJsonModule>("./locales/*.json");
|
|
61
|
+
|
|
62
|
+
async function loadBase(lang: LocaleCode): Promise<Record<string, string>> {
|
|
63
|
+
const key = `/node_modules/@orderly.network/i18n/dist/locales/${lang}.json`;
|
|
64
|
+
return importLocaleJsonModule(baseLoaders[key]);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function loadExtend(lang: LocaleCode): Promise<Record<string, string>> {
|
|
68
|
+
const key = `./locales/${lang}.json`;
|
|
69
|
+
return importLocaleJsonModule(extendLoaders[key]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const resources: AsyncResources = async (lang: LocaleCode, _ns: string) => {
|
|
73
|
+
if (lang === LocaleEnum.en) {
|
|
74
|
+
return extendEnLocale as Record<string, string>;
|
|
75
|
+
}
|
|
76
|
+
const [base, extend] = await Promise.all([loadBase(lang), loadExtend(lang)]);
|
|
77
|
+
return { ...base, ...extend };
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const OrderlyProvider: FC<{ children: ReactNode }> = (props) => {
|
|
81
|
+
return (
|
|
82
|
+
<LocaleProvider resources={resources}>
|
|
83
|
+
<WalletConnectorProvider>
|
|
84
|
+
<OrderlyAppProvider
|
|
85
|
+
brokerId="orderly"
|
|
86
|
+
brokerName="Orderly"
|
|
87
|
+
networkId="testnet"
|
|
88
|
+
>
|
|
89
|
+
{props.children}
|
|
90
|
+
</OrderlyAppProvider>
|
|
91
|
+
</WalletConnectorProvider>
|
|
92
|
+
</LocaleProvider>
|
|
93
|
+
);
|
|
94
|
+
};
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Async resources (Next.js and webpack)
|
|
98
|
+
|
|
99
|
+
_Bundled SDK + extend JSON with webpack-friendly static imports. Pass an `AsyncResources` loader to `LocaleProvider`._
|
|
100
|
+
|
|
101
|
+
Use this pattern in **Next.js** when you bundle with **webpack** (default production build). Next.js does not provide Vite’s **`import.meta.glob`**. A dynamic import such as ``import(`@orderly.network/i18n/locales/${lang}.json`)`` is also a poor fit: webpack must resolve **statically analyzable** subpaths under the package **`exports`** map, so the reliable approach is a **`Record<LocaleEnum, () => import(...)>`** with one explicit import per SDK locale. App extend files can still use a dynamic import from your app alias (e.g. ``import(`@/locales/${lang}.json`)``) because those paths live in your project tree.
|
|
102
|
+
|
|
103
|
+
- **Client component:** In the **App Router**, put the provider in a file with **`"use client"`** at the top when **`LocaleProvider`** runs on the client.
|
|
104
|
+
- **Base SDK strings:** import from **`@orderly.network/i18n/locales/<locale>.json`** (published subpaths; add an entry for **every** `LocaleEnum` value you support).
|
|
105
|
+
- **Extend keys:** import or dynamic-import your app’s JSON (example: `@/locales/<lang>.json`—match your `tsconfig` paths).
|
|
106
|
+
- For **`en`**, return your imported extend file only (English base is built into the package).
|
|
107
|
+
- For other locales, `Promise.all` base + extend and merge. **`importLocaleJsonModule`** normalizes each module’s `default` export.
|
|
108
|
+
|
|
109
|
+
**Reference implementation:** `sdk-demo/src/components/orderlyProvider/OrderlyLocaleProvider.tsx` in the Orderly SDK template demo (same merge logic and full `Record<LocaleEnum, …>` base loaders; compare with [`orderly-js-sdk-nextjs-template` / `components/orderlyProvider`](https://github.com/OrderlyNetwork/orderly-js-sdk-nextjs-template/tree/main/components/orderlyProvider) for app wiring).
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
"use client";
|
|
113
|
+
|
|
114
|
+
import React, { FC, ReactNode } from "react";
|
|
115
|
+
import {
|
|
116
|
+
AsyncResources,
|
|
117
|
+
importLocaleJsonModule,
|
|
118
|
+
LocaleCode,
|
|
119
|
+
LocaleEnum,
|
|
120
|
+
LocaleProvider,
|
|
121
|
+
} from "@orderly.network/i18n";
|
|
122
|
+
import type { LocaleJsonModule } from "@orderly.network/i18n";
|
|
123
|
+
import { OrderlyAppProvider } from "@orderly.network/react-app";
|
|
124
|
+
import { WalletConnectorProvider } from "@orderly.network/wallet-connector";
|
|
125
|
+
import extendEnLocale from "@/locales/en.json";
|
|
126
|
+
|
|
127
|
+
type LocaleJsonLoader = () => Promise<LocaleJsonModule>;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* One explicit import per locale so webpack can resolve @orderly.network/i18n/locales/*.json
|
|
131
|
+
* through package exports. Include every `LocaleEnum` value your app can switch to.
|
|
132
|
+
*/
|
|
133
|
+
const baseLocaleLoaders: Record<LocaleEnum, LocaleJsonLoader> = {
|
|
134
|
+
[LocaleEnum.de]: () => import("@orderly.network/i18n/locales/de.json"),
|
|
135
|
+
[LocaleEnum.en]: () => import("@orderly.network/i18n/locales/en.json"),
|
|
136
|
+
[LocaleEnum.es]: () => import("@orderly.network/i18n/locales/es.json"),
|
|
137
|
+
[LocaleEnum.fr]: () => import("@orderly.network/i18n/locales/fr.json"),
|
|
138
|
+
[LocaleEnum.id]: () => import("@orderly.network/i18n/locales/id.json"),
|
|
139
|
+
[LocaleEnum.it]: () => import("@orderly.network/i18n/locales/it.json"),
|
|
140
|
+
[LocaleEnum.ja]: () => import("@orderly.network/i18n/locales/ja.json"),
|
|
141
|
+
[LocaleEnum.ko]: () => import("@orderly.network/i18n/locales/ko.json"),
|
|
142
|
+
[LocaleEnum.nl]: () => import("@orderly.network/i18n/locales/nl.json"),
|
|
143
|
+
[LocaleEnum.pl]: () => import("@orderly.network/i18n/locales/pl.json"),
|
|
144
|
+
[LocaleEnum.pt]: () => import("@orderly.network/i18n/locales/pt.json"),
|
|
145
|
+
[LocaleEnum.ru]: () => import("@orderly.network/i18n/locales/ru.json"),
|
|
146
|
+
[LocaleEnum.tc]: () => import("@orderly.network/i18n/locales/tc.json"),
|
|
147
|
+
[LocaleEnum.tr]: () => import("@orderly.network/i18n/locales/tr.json"),
|
|
148
|
+
[LocaleEnum.uk]: () => import("@orderly.network/i18n/locales/uk.json"),
|
|
149
|
+
[LocaleEnum.vi]: () => import("@orderly.network/i18n/locales/vi.json"),
|
|
150
|
+
[LocaleEnum.zh]: () => import("@orderly.network/i18n/locales/zh.json"),
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
async function loadBase(lang: LocaleCode): Promise<Record<string, string>> {
|
|
154
|
+
const loader = baseLocaleLoaders[lang as LocaleEnum];
|
|
155
|
+
return importLocaleJsonModule(loader);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function loadExtend(lang: LocaleCode): Promise<Record<string, string>> {
|
|
159
|
+
return importLocaleJsonModule(() => import(`@/locales/${lang}.json`));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const resources: AsyncResources = async (lang: LocaleCode, _ns: string) => {
|
|
163
|
+
if (lang === LocaleEnum.en) {
|
|
164
|
+
return extendEnLocale as Record<string, string>;
|
|
165
|
+
}
|
|
166
|
+
const [base, extend] = await Promise.all([loadBase(lang), loadExtend(lang)]);
|
|
167
|
+
return { ...base, ...extend };
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const OrderlyProvider: FC<{ children: ReactNode }> = (props) => {
|
|
171
|
+
return (
|
|
172
|
+
<LocaleProvider resources={resources}>
|
|
173
|
+
<WalletConnectorProvider>
|
|
174
|
+
<OrderlyAppProvider
|
|
175
|
+
brokerId="orderly"
|
|
176
|
+
brokerName="Orderly"
|
|
177
|
+
networkId="testnet"
|
|
178
|
+
>
|
|
179
|
+
{props.children}
|
|
180
|
+
</OrderlyAppProvider>
|
|
181
|
+
</WalletConnectorProvider>
|
|
182
|
+
</LocaleProvider>
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## HTTP backend
|
|
188
|
+
|
|
189
|
+
_Locales under `public/` (or any URL your `loadPath` returns)._
|
|
190
|
+
|
|
191
|
+
### How HTTP loading works
|
|
192
|
+
|
|
193
|
+
`backend.loadPath` only returns URL(s). The internal `Backend` **`fetch`es** those URLs at runtime. **`@orderly.network/i18n` does not install or copy** `dist/locales` into your app’s `public/` folder — you must **provide files** at those paths yourself.
|
|
194
|
+
|
|
195
|
+
### Getting built-in JSON into `public/`
|
|
196
|
+
|
|
197
|
+
**Manual:** Copy from `node_modules/@orderly.network/i18n/dist/locales` (exact path depends on your install layout) into e.g. **`public/locales/`**. Put your app **extend** JSON under e.g. **`public/locales/extend/`** (same layout as `loadPath` below).
|
|
198
|
+
|
|
199
|
+
**Automate:** Use an npm script (e.g. `copyLocales`) and optionally a **Husky** hook (`pre-commit`, `postinstall`, or `prepare`) to run a small script that copies `dist/locales` → `public/locales`. The script below only covers **SDK** bundles; **extend** files usually stay in your repo and are committed or generated separately.
|
|
200
|
+
|
|
201
|
+
**CDN:** If `loadPath` points to a CDN, upload or deploy those JSON files there yourself — same idea: static URLs, not automatic sync from the package.
|
|
202
|
+
|
|
203
|
+
### Optional copy script (ESM)
|
|
204
|
+
|
|
205
|
+
Adjust `path.resolve` segments if your script lives in `scripts/` or in a monorepo package (paths differ from a single-package app). Add **`fs-extra`** as a dev dependency.
|
|
206
|
+
|
|
207
|
+
```js
|
|
208
|
+
import fs from "fs-extra";
|
|
209
|
+
import path from "path";
|
|
210
|
+
import { fileURLToPath } from "url";
|
|
211
|
+
|
|
212
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
213
|
+
|
|
214
|
+
async function copyLocales() {
|
|
215
|
+
await fs.copy(
|
|
216
|
+
path.resolve(
|
|
217
|
+
__dirname,
|
|
218
|
+
"../node_modules/@orderly.network/i18n/dist/locales",
|
|
219
|
+
),
|
|
220
|
+
path.resolve(__dirname, "../public/locales"),
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
copyLocales();
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Wire it from **`package.json`**: `"scripts": { "copyLocales": "node ./scripts/copy-locales.mjs" }` (path as you prefer).
|
|
228
|
+
|
|
229
|
+
### Husky example (reference)
|
|
230
|
+
|
|
231
|
+
Example **`.husky/pre-commit`** hook:
|
|
232
|
+
|
|
233
|
+
```text
|
|
234
|
+
npm run copyLocales
|
|
235
|
+
git add public/locales/*.json
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`copyLocales` runs your copy script; `git add` stages updated JSON so the commit includes them (adjust `glob` if you also version `public/locales/extend/`).
|
|
239
|
+
|
|
240
|
+
### `LocaleProvider` + `loadPath`
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { FC, ReactNode } from "react";
|
|
244
|
+
import { WalletConnectorProvider } from "@orderly.network/wallet-connector";
|
|
245
|
+
import { OrderlyAppProvider } from "@orderly.network/react-app";
|
|
246
|
+
import { LocaleProvider, LocaleEnum, LocaleCode } from "@orderly.network/i18n";
|
|
247
|
+
|
|
248
|
+
const OrderlyProvider: FC<{ children: ReactNode }> = (props) => {
|
|
249
|
+
// Requires public/locales/*.json and public/locales/extend/*.json (see sections above)
|
|
250
|
+
const loadPath = (lang: LocaleCode, _ns: string) => {
|
|
251
|
+
if (lang === LocaleEnum.en) {
|
|
252
|
+
// because en is built-in, we need to load the en extend only
|
|
253
|
+
return `/locales/extend/${lang}.json`;
|
|
254
|
+
}
|
|
255
|
+
return [`/locales/${lang}.json`, `/locales/extend/${lang}.json`];
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
return (
|
|
259
|
+
<LocaleProvider backend={{ loadPath }}>
|
|
260
|
+
<WalletConnectorProvider>
|
|
261
|
+
<OrderlyAppProvider
|
|
262
|
+
brokerId="orderly"
|
|
263
|
+
brokerName="Orderly"
|
|
264
|
+
networkId="testnet"
|
|
265
|
+
>
|
|
266
|
+
{props.children}
|
|
267
|
+
</OrderlyAppProvider>
|
|
268
|
+
</WalletConnectorProvider>
|
|
269
|
+
</LocaleProvider>
|
|
270
|
+
);
|
|
271
|
+
};
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Sync resources
|
|
275
|
+
|
|
276
|
+
_Imported JSON maps. Pass a static `Resources` map to `LocaleProvider`._
|
|
277
|
+
|
|
278
|
+
Use this when you bundle locale JSON (e.g. import from `@orderly.network/i18n/locales/*`) and do not need async loading.
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
import { FC, ReactNode } from "react";
|
|
282
|
+
import { WalletConnectorProvider } from "@orderly.network/wallet-connector";
|
|
283
|
+
import { OrderlyAppProvider } from "@orderly.network/react-app";
|
|
284
|
+
import { LocaleProvider, Resources } from "@orderly.network/i18n";
|
|
285
|
+
import zh from "@orderly.network/i18n/locales/zh.json";
|
|
286
|
+
import ja from "@orderly.network/i18n/locales/ja.json";
|
|
287
|
+
import ko from "@orderly.network/i18n/locales/ko.json";
|
|
288
|
+
|
|
289
|
+
// extend or override English translations
|
|
290
|
+
const extendEn = {
|
|
291
|
+
"extend.trading": "Trading",
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// extend or override chinese translations
|
|
295
|
+
const extendZh = {
|
|
296
|
+
"extend.trading": "交易",
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// extend or override japanese translations
|
|
300
|
+
const extendJa = {
|
|
301
|
+
"extend.trading": "取引",
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
// extend or override korean translations
|
|
305
|
+
const extendKo = {
|
|
306
|
+
"extend.trading": "거래",
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
// define language resources
|
|
310
|
+
const resources: Resources = {
|
|
311
|
+
en: extendEn,
|
|
312
|
+
zh: {
|
|
313
|
+
...zh,
|
|
314
|
+
...extendZh,
|
|
315
|
+
},
|
|
316
|
+
ja: {
|
|
317
|
+
...ja,
|
|
318
|
+
...extendJa,
|
|
319
|
+
},
|
|
320
|
+
ko: {
|
|
321
|
+
...ko,
|
|
322
|
+
...extendKo,
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
const OrderlyProvider: FC<{ children: ReactNode }> = (props) => {
|
|
327
|
+
return (
|
|
328
|
+
<LocaleProvider resources={resources}>
|
|
329
|
+
<WalletConnectorProvider>
|
|
330
|
+
<OrderlyAppProvider
|
|
331
|
+
brokerId="orderly"
|
|
332
|
+
brokerName="Orderly"
|
|
333
|
+
networkId="testnet"
|
|
334
|
+
>
|
|
335
|
+
{props.children}
|
|
336
|
+
</OrderlyAppProvider>
|
|
337
|
+
</WalletConnectorProvider>
|
|
338
|
+
</LocaleProvider>
|
|
339
|
+
);
|
|
340
|
+
};
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Custom languages
|
|
344
|
+
|
|
345
|
+
_Subset of locales in the picker._
|
|
346
|
+
|
|
347
|
+
You can restrict the language list and provide only the locales you need via `languages` and `resources`. **`en`** strings are built into the package, so you do not need an `en` entry in `resources` unless you add extend keys; you can still list **`LocaleEnum.en`** in `languages` so the picker includes English.
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
import { FC, ReactNode } from "react";
|
|
351
|
+
import { WalletConnectorProvider } from "@orderly.network/wallet-connector";
|
|
352
|
+
import { OrderlyAppProvider } from "@orderly.network/react-app";
|
|
353
|
+
import {
|
|
354
|
+
LocaleProvider,
|
|
355
|
+
Resources,
|
|
356
|
+
LocaleEnum,
|
|
357
|
+
Language,
|
|
358
|
+
} from "@orderly.network/i18n";
|
|
359
|
+
|
|
360
|
+
// japanese locale
|
|
361
|
+
const ja = {
|
|
362
|
+
"extend.ja": "日本語",
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
// korean locale
|
|
366
|
+
const ko = {
|
|
367
|
+
"extend.ko": "한국어",
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
// define language resources
|
|
371
|
+
const resources: Resources = {
|
|
372
|
+
ja,
|
|
373
|
+
ko,
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// custom languages
|
|
377
|
+
const languages: Language[] = [
|
|
378
|
+
{ localCode: LocaleEnum.en, displayName: "English" },
|
|
379
|
+
{ localCode: LocaleEnum.ja, displayName: "日本語" },
|
|
380
|
+
{ localCode: LocaleEnum.ko, displayName: "한국어" },
|
|
381
|
+
];
|
|
382
|
+
|
|
383
|
+
const OrderlyProvider: FC<{ children: ReactNode }> = (props) => {
|
|
384
|
+
return (
|
|
385
|
+
<LocaleProvider resources={resources} languages={languages}>
|
|
386
|
+
<WalletConnectorProvider>
|
|
387
|
+
<OrderlyAppProvider
|
|
388
|
+
brokerId="orderly"
|
|
389
|
+
brokerName="Orderly"
|
|
390
|
+
networkId="testnet"
|
|
391
|
+
>
|
|
392
|
+
{props.children}
|
|
393
|
+
</OrderlyAppProvider>
|
|
394
|
+
</WalletConnectorProvider>
|
|
395
|
+
</LocaleProvider>
|
|
396
|
+
);
|
|
397
|
+
};
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## onLanguageChanged (URL sync)
|
|
401
|
+
|
|
402
|
+
_Keep the browser URL aligned with locale-prefixed routes when the user switches language (e.g. `/en/trade` → `/zh/trade`)._
|
|
403
|
+
|
|
404
|
+
Import **`LocaleCode`** and **`removeLangPrefix`** from `@orderly.network/i18n` and pass the callback to **`LocaleProvider`** as **`onLanguageChanged`**. Strip the current locale segment from the pathname, then use **`history.replaceState`** to set the path to `/${lang}${path}`.
|
|
405
|
+
|
|
406
|
+
The example below matches [HTTP backend](#http-backend): the same **`loadPath`** (see that section for copying files under `public/`) and nested providers; **`onLanguageChanged`** adds URL sync on top.
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import { FC, ReactNode } from "react";
|
|
410
|
+
import { WalletConnectorProvider } from "@orderly.network/wallet-connector";
|
|
411
|
+
import { OrderlyAppProvider } from "@orderly.network/react-app";
|
|
412
|
+
import { LocaleProvider, LocaleEnum, LocaleCode, removeLangPrefix } from "@orderly.network/i18n";
|
|
413
|
+
|
|
414
|
+
const OrderlyProvider: FC<{ children: ReactNode }> = (props) => {
|
|
415
|
+
const onLanguageChanged = async (lang: LocaleCode) => {
|
|
416
|
+
const path = removeLangPrefix(window.location.pathname);
|
|
417
|
+
window.history.replaceState({}, "", `/${lang}${path}`);
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
// Please copy built-in locale files (@orderly.network/i18n/locales) to your public/locales
|
|
421
|
+
// and copy your extend locale files to public/locales/extend
|
|
422
|
+
const loadPath = (lang: LocaleCode, _ns: string) => {
|
|
423
|
+
if (lang === LocaleEnum.en) {
|
|
424
|
+
// because en is built-in, we need to load the en extend only
|
|
425
|
+
return `/locales/extend/${lang}.json`;
|
|
426
|
+
}
|
|
427
|
+
return [`/locales/${lang}.json`, `/locales/extend/${lang}.json`];
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
return (
|
|
431
|
+
<LocaleProvider
|
|
432
|
+
onLanguageChanged={onLanguageChanged}
|
|
433
|
+
backend={{ loadPath }}
|
|
434
|
+
>
|
|
435
|
+
<WalletConnectorProvider>
|
|
436
|
+
<OrderlyAppProvider
|
|
437
|
+
brokerId="orderly"
|
|
438
|
+
brokerName="Orderly"
|
|
439
|
+
networkId="testnet"
|
|
440
|
+
>
|
|
441
|
+
{props.children}
|
|
442
|
+
</OrderlyAppProvider>
|
|
443
|
+
</WalletConnectorProvider>
|
|
444
|
+
</LocaleProvider>
|
|
445
|
+
);
|
|
446
|
+
};
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Combining with async resources:** For **`AsyncResources`** and **`import.meta.glob`**, see [Async resources (Vite)](#async-resources-vite). For **`AsyncResources`** on webpack, see [Async resources (Next.js and webpack)](#async-resources-nextjs-and-webpack).
|
|
450
|
+
|
|
451
|
+
**Next.js App Router:** Prefer **`usePathname()`** from `next/navigation` (or your router’s path API) instead of **`window.location.pathname`** when stripping the locale inside **`onLanguageChanged`**. You may sync **`i18n`** with **`getLocalePathFromPathname`** when the URL locale changes.
|
|
452
|
+
|
|
453
|
+
**Framework routers:** **`history.replaceState`** updates the URL but does not always trigger the same lifecycle as your framework’s client navigation (e.g. Next.js `router`). If the framework exposes locale-aware navigation (**`router.push`**, **`Link`**, etc.), prefer that for in-app changes so router state stays consistent.
|
|
454
|
+
|
|
455
|
+
See also: [Integration guide](./integration.md) ([§1](./integration.md#1-wrap-your-app-with-localeprovider) · [§4](./integration.md#4-integrate-external-resources)) · [CLI](./cli.md)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Package exports
|
|
2
|
+
|
|
3
|
+
| Export | Description |
|
|
4
|
+
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
5
|
+
| `@orderly.network/i18n` | Main entry: `LocaleProvider`, `ExternalLocaleProvider`, `LanguageProvider`, `registerDefaultResource`, `registerResources`, `Backend`, `importLocaleJsonModule`, `i18n`, `createI18nInstance`, hooks, `en` (baseline messages), re-exports from `react-i18next` / `i18next` (`createInstance`), and types |
|
|
6
|
+
| `@orderly.network/i18n/locales/`\* | Built-in locale JSON files |
|
|
7
|
+
| `@orderly.network/i18n/constant` | Constants (e.g. `LocaleEnum`, `defaultLanguages`, `defaultNS`) |
|
|
8
|
+
| `@orderly.network/i18n/utils` | Utility functions (see [Utils](./utils.md)) |
|
|
9
|
+
|
|
10
|
+
**Hooks:** `useTranslation`, `useLocaleCode`, and `useRegisterExternalResources` are exported from the main entry; use them like react-i18next. **`useLanguageContext`** exposes the language list and `onLanguageBeforeChanged` / `onLanguageChanged` from the language context.
|
|
11
|
+
|
|
12
|
+
The default i18n namespace is **`translation`** (`defaultNS`).
|
|
13
|
+
|
|
14
|
+
See also: [Integration guide](./integration.md) · [Examples](./examples.md)
|