Skip to content

Commit 56063cd

Browse files
authored
docs: update i18n docs (#7947)
1 parent 70b864a commit 56063cd

File tree

14 files changed

+367
-53
lines changed

14 files changed

+367
-53
lines changed

packages/document/docs/en/guides/advanced-features/international/api.mdx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,8 @@ interface UseModernI18nReturn {
3838
import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
3939

4040
function LanguageSwitcher() {
41-
const {
42-
language,
43-
changeLanguage,
44-
supportedLanguages,
45-
isLanguageSupported,
46-
} = useModernI18n();
41+
const { language, changeLanguage, supportedLanguages, isLanguageSupported } =
42+
useModernI18n();
4743

4844
return (
4945
<div>
@@ -90,6 +86,7 @@ await changeLanguage('zh');
9086

9187
:::info
9288
`changeLanguage` is an async function that returns a Promise.
89+
9390
:::
9491

9592
### Language Support Check
@@ -134,9 +131,11 @@ function MyComponent() {
134131

135132
:::info
136133
`isResourcesReady` automatically checks:
134+
137135
- If i18n instance is initialized
138136
- If any resources for the current language are currently loading (SDK backend only)
139137
- If all required namespaces for the current language are loaded in the store
138+
140139
:::
141140

142141
## I18nLink Component
@@ -267,14 +266,27 @@ interface I18nInitOptions {
267266

268267
```ts
269268
interface LanguageDetectorOptions {
269+
/** Detection order */
270270
order?: string[];
271+
/** Query parameter key name, default 'lng' */
271272
lookupQuerystring?: string;
273+
/** Cookie key name, default 'i18next' */
272274
lookupCookie?: string;
275+
/** LocalStorage key name, default 'i18nextLng' (browser only) */
276+
lookupLocalStorage?: string;
277+
/** SessionStorage key name (browser only) */
273278
lookupSession?: string;
279+
/** Starting index in path for language detection, default 0 */
274280
lookupFromPathIndex?: number;
281+
/** Cache method, can be false or string array (e.g., ['cookie', 'localStorage']) */
275282
caches?: boolean | string[];
283+
/** Cookie expiration time (minutes) */
284+
cookieMinutes?: number;
285+
/** Cookie expiration date (Date object, takes precedence over cookieMinutes) */
276286
cookieExpirationDate?: Date;
287+
/** Cookie domain */
277288
cookieDomain?: string;
289+
/** Request header key name, default 'accept-language' */
278290
lookupHeader?: string;
279291
}
280292
```
@@ -289,3 +301,7 @@ type Resources = {
289301
};
290302
```
291303

304+
:::info
305+
The namespace value can be a string (for simple key-value pairs) or an object (for nested translation structures).
306+
307+
:::

packages/document/docs/en/guides/advanced-features/international/best-practices.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ function MyComponent() {
9191

9292
:::tip
9393
`isResourcesReady` is more accurate for SDK backend scenarios as it checks if all required resources are actually loaded, not just if the instance is initialized.
94+
9495
:::
9596

9697
## Type Safety

packages/document/docs/en/guides/advanced-features/international/configuration.mdx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ interface BaseLocaleDetectionOptions {
5555

5656
/** Custom detection configuration */
5757
detection?: LanguageDetectorOptions;
58+
59+
/** Routes to ignore automatic redirection (array of path patterns or function)
60+
*
61+
* Can be a string array (path patterns) or a function to determine if redirection should be ignored.
62+
* Supports exact match and prefix match (e.g., '/api' will match '/api' and '/api/users').
63+
*
64+
* @example
65+
* // String array
66+
* ignoreRedirectRoutes: ['/api', '/admin']
67+
*
68+
* // Function
69+
* ignoreRedirectRoutes: (pathname) => pathname.startsWith('/api')
70+
*/
71+
ignoreRedirectRoutes?: string[] | ((pathname: string) => boolean);
5872
}
5973

6074
interface LocaleDetectionOptions extends BaseLocaleDetectionOptions {

packages/document/docs/en/guides/advanced-features/international/locale-detection.mdx

Lines changed: 94 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,25 +133,34 @@ i18nPlugin({
133133

134134
## Detection Priority
135135

136-
When multiple detection methods are enabled, the detection priority follows the order configured in `detection.order`:
136+
The plugin's language detection follows the following priority order (from highest to lowest):
137137

138-
1. **Path Detection** (if `localePathRedirect` is `true`)
139-
2. **i18next Detector** (following the order configured in `order`)
140-
3. **Fallback Language** (`fallbackLanguage`)
138+
1. **SSR Data** (highest priority): Read language from `window._SSR_DATA` set during server-side rendering, applicable to both SSR and CSR projects
139+
2. **Path Detection**: If `localePathRedirect` is `true`, detect language prefix from URL path
140+
3. **i18next Detector**: Execute detection according to the order configured in `detection.order` (Cookie, LocalStorage, query parameters, request headers, etc.)
141+
4. **User Configured Language**: Use the language configured in `initOptions.lng`
142+
5. **Fallback Language**: Use `fallbackLanguage` as the final fallback
143+
144+
:::info
145+
SSR data detection has the highest priority to ensure the client uses the language detected during server-side rendering, avoiding language flickering issues caused by client-side re-detection.
146+
:::
141147

142148
**Example**:
143149

144150
```ts
145-
// Configured detection order
151+
// Configured detection order (only affects priority within i18next detector)
146152
detection: {
147153
order: ['path', 'cookie', 'querystring', 'header'],
148154
}
149155

150156
// Actual detection flow:
151-
// 1. First check URL path (if localePathRedirect is enabled)
152-
// 2. Then check Cookie
153-
// 3. Then check query parameters
154-
// 4. Then check request headers
157+
// 1. First check SSR data (window._SSR_DATA)
158+
// 2. Then check URL path (if localePathRedirect is enabled)
159+
// 3. Then check i18next detector according to order:
160+
// - Cookie
161+
// - Query parameters
162+
// - Request headers
163+
// 4. Then use initOptions.lng (if configured)
155164
// 5. Finally use fallbackLanguage
156165
```
157166

@@ -172,7 +181,7 @@ Specifies the order of language detection, optional values:
172181
- `subdomain`: Detect from subdomain
173182

174183
:::warning
175-
`path` detection requires `localePathRedirect` to be `true`. `localStorage`, `navigator`, and `htmlTag` are only available in browser environments.
184+
`path` detection requires `localePathRedirect` to be `true`. `localStorage`, `sessionStorage`, `navigator`, and `htmlTag` are only available in browser environments.
176185
:::
177186

178187
### caches (Cache Method)
@@ -184,11 +193,84 @@ Specifies where the detected language should be cached, optional values:
184193
- `['localStorage']`: Cache to LocalStorage (browser only)
185194
- `['cookie', 'localStorage']`: Cache to both Cookie and LocalStorage
186195

187-
### lookupQuerystring, lookupCookie, lookupHeader
196+
### lookupQuerystring, lookupCookie, lookupLocalStorage, lookupSession, lookupHeader
188197

189-
Specifies the key name used when reading language from query parameters, cookies, or request headers:
198+
Specifies the key name used when reading language from query parameters, cookies, LocalStorage, SessionStorage, or request headers:
190199

191200
- `lookupQuerystring`: Default `'lng'`, e.g., `?lng=en`
192201
- `lookupCookie`: Default `'i18next'`
202+
- `lookupLocalStorage`: Default `'i18nextLng'` (browser only)
203+
- `lookupSession`: SessionStorage key name (browser only)
193204
- `lookupHeader`: Default `'accept-language'`
194205

206+
### lookupFromPathIndex
207+
208+
Specifies which position in the URL path to start detecting language (when `'path'` is included in `order`):
209+
210+
- `lookupFromPathIndex`: Path segment index, defaults to `0` (first path segment)
211+
212+
**Example**:
213+
214+
```ts
215+
// URL: /api/v1/en/users
216+
// If lookupFromPathIndex = 2, detection starts from the third path segment ('en')
217+
detection: {
218+
order: ['path'],
219+
lookupFromPathIndex: 2,
220+
}
221+
```
222+
223+
### cookieMinutes, cookieExpirationDate
224+
225+
Controls Cookie expiration time:
226+
227+
- `cookieMinutes`: Cookie expiration time (minutes), default `525600` (1 year)
228+
- `cookieExpirationDate`: Cookie expiration date (Date object), takes precedence over `cookieMinutes`
229+
230+
**Example**:
231+
232+
```ts
233+
detection: {
234+
cookieMinutes: 60 * 24 * 7, // Expires in 7 days
235+
// or
236+
cookieExpirationDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // Expires in 7 days
237+
}
238+
```
239+
240+
### ignoreRedirectRoutes
241+
242+
Specifies which routes should ignore automatic language redirection. This is very useful for API routes, static resources, and other paths that don't need language prefixes.
243+
244+
**Configuration**:
245+
246+
```ts
247+
i18nPlugin({
248+
localeDetection: {
249+
localePathRedirect: true,
250+
languages: ['zh', 'en'],
251+
fallbackLanguage: 'en',
252+
// String array: supports exact match and prefix match
253+
ignoreRedirectRoutes: ['/api', '/admin', '/static'],
254+
// Or use function for more flexible judgment
255+
ignoreRedirectRoutes: pathname => {
256+
return pathname.startsWith('/api') || pathname.startsWith('/admin');
257+
},
258+
},
259+
});
260+
```
261+
262+
**Matching Rules**:
263+
264+
- String array: Supports exact match (`'/api'`) and prefix match (`'/api'` will match `/api` and `/api/users`)
265+
- Function: Receives pathname (with language prefix removed), returns `true` to indicate ignoring redirection
266+
267+
**Example**:
268+
269+
```ts
270+
// Ignore all API routes and static resources
271+
ignoreRedirectRoutes: ['/api', '/static', '/assets'];
272+
273+
// Use function to ignore all paths starting with /api
274+
ignoreRedirectRoutes: pathname => pathname.startsWith('/api');
275+
```
276+

packages/document/docs/en/guides/advanced-features/international/quick-start.mdx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ pnpm add @modern-js/plugin-i18n i18next react-i18next
1616

1717
:::info
1818
`i18next` and `react-i18next` are peer dependencies and need to be installed manually.
19+
1920
:::
2021

2122
## Basic Configuration
2223

23-
### 1. Configure Plugin in `modern.config.ts`
24+
### Configure Plugin in `modern.config.ts`
2425

2526
```ts
2627
import { appTools, defineConfig } from '@modern-js/app-tools';
@@ -51,9 +52,10 @@ export default defineConfig({
5152

5253
:::info
5354
`server.publicDir` is a required configuration used to specify the actual location of resource files. Even when using the default `loadPath`, this configuration is still required.
55+
5456
:::
5557

56-
### 2. Create Language Resource Files
58+
### Create Language Resource Files
5759

5860
Create a `locales` folder in the project root and organize resource files by language:
5961

@@ -85,7 +87,7 @@ locales/
8587
}
8688
```
8789

88-
### 3. Use in Components
90+
### Use in Components
8991

9092
```tsx
9193
import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
@@ -122,4 +124,3 @@ export default App;
122124
- Learn detailed [Configuration](./configuration) instructions
123125
- Learn about multiple [Locale Detection](./locale-detection) methods
124126
- Check [Resource Loading](./resource-loading) configuration options
125-

packages/document/docs/en/guides/advanced-features/international/resource-loading.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ i18nPlugin({
125125

126126
:::warning
127127
The `loadPath` configuration is used for both HTTP backend (frontend) and file system backend (server-side). If configured as an absolute path starting with `/` (e.g., `/locales/{{lng}}/{{ns}}.json`), the file system backend will automatically convert it to a relative path (`./locales/{{lng}}/{{ns}}.json`). Therefore, it's recommended to use absolute paths in the configuration, which can meet both frontend and backend requirements.
128+
128129
:::
129130

130131
## SDK Backend

packages/document/docs/en/guides/advanced-features/international/routing.mdx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,34 @@ i18nPlugin({
1818
localePathRedirect: true,
1919
languages: ['zh', 'en'],
2020
fallbackLanguage: 'en',
21+
// Optional: ignore automatic redirection for certain routes
22+
ignoreRedirectRoutes: ['/api', '/admin'],
2123
},
2224
});
2325
```
2426

27+
### Ignore Redirection Routes
28+
29+
Some routes (such as API routes, static resources, etc.) don't need language prefixes. You can use the `ignoreRedirectRoutes` configuration to ignore automatic redirection for these routes:
30+
31+
```ts
32+
i18nPlugin({
33+
localeDetection: {
34+
localePathRedirect: true,
35+
languages: ['zh', 'en'],
36+
fallbackLanguage: 'en',
37+
// String array: supports exact match and prefix match
38+
ignoreRedirectRoutes: ['/api', '/admin', '/static'],
39+
// Or use function for more flexible judgment
40+
ignoreRedirectRoutes: pathname => {
41+
return pathname.startsWith('/api') || pathname.startsWith('/admin');
42+
},
43+
},
44+
});
45+
```
46+
47+
For more details, please refer to the `ignoreRedirectRoutes` configuration in the [Locale Detection documentation](./locale-detection#ignoreredirectroutes).
48+
2549
## Route Configuration
2650

2751
After enabling path redirection, you need to add `:lang` dynamic parameter to the route configuration.
@@ -115,6 +139,7 @@ function App() {
115139

116140
:::info
117141
Convention-based routing will automatically generate corresponding routes based on the file structure. It's recommended to use convention-based routing. Only use custom routing when special route control is needed.
142+
118143
:::
119144

120145
## I18nLink Component
@@ -185,4 +210,3 @@ interface I18nLinkProps {
185210
Contact
186211
</I18nLink>
187212
```
188-

0 commit comments

Comments
 (0)