Skip to content

Commit 41986ac

Browse files
authored
Merge branch 'main' into migrate-tests
2 parents 99d5a62 + e6568be commit 41986ac

File tree

37 files changed

+1871
-187
lines changed

37 files changed

+1871
-187
lines changed

.changeset/ripe-forks-spend.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@modern-js/plugin-styled-components': patch
3+
---
4+
5+
fix: plugin-styled-components
6+
fix: 修复 styled-components 插件

packages/cli/builder/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"@rsbuild/plugin-sass": "1.4.0",
4242
"@rsbuild/plugin-source-build": "1.0.3",
4343
"@rsbuild/plugin-svgr": "1.2.2",
44-
"@rsbuild/plugin-type-check": "1.3.0",
44+
"@rsbuild/plugin-type-check": "1.3.1",
4545
"@rsbuild/plugin-typed-css-modules": "1.2.0",
4646
"@swc/core": "1.14.0",
4747
"@swc/helpers": "^0.5.17",

packages/cli/plugin-styled-components/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"name": "@modern-js/plugin-styled-components",
3-
"private": true,
43
"description": "A Modern.js plugin for styled-components.",
54
"license": "MIT",
65
"keywords": [

packages/cli/plugin-styled-components/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ export const styledComponentsPlugin = (
2828
});
2929

3030
api._internalRuntimePlugins(async ({ entrypoint, plugins }) => {
31+
const { metaName } = api.getAppContext();
32+
3133
plugins.push({
3234
name: 'styledComponents',
33-
path: '@modern-js/plugin-styled-components/runtime',
35+
path: `@${metaName}/plugin-styled-components/runtime`,
3436
config: {},
3537
});
3638
return { entrypoint, plugins };

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ interface UseModernI18nReturn {
2626

2727
/** Check if language is supported */
2828
isLanguageSupported: (lang: string) => boolean;
29+
30+
/** Indicates if translation resources for current language are ready to use */
31+
isResourcesReady: boolean;
2932
}
3033
```
3134

@@ -105,6 +108,37 @@ function handleLanguageChange(lang: string) {
105108
}
106109
```
107110

111+
### Resource Loading State
112+
113+
`isResourcesReady` indicates whether the translation resources for the current language are loaded and ready to use. This is particularly useful when using SDK backend to load resources dynamically.
114+
115+
```tsx
116+
import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
117+
118+
function MyComponent() {
119+
const { isResourcesReady } = useModernI18n();
120+
121+
if (!isResourcesReady) {
122+
return <div>Loading translation resources...</div>;
123+
}
124+
125+
return <div>Translation resources are ready</div>;
126+
}
127+
```
128+
129+
**When to use:**
130+
131+
- Display a loading state while resources are being loaded
132+
- Prevent rendering content that depends on translations before resources are ready
133+
- Handle resource loading errors gracefully
134+
135+
:::info
136+
`isResourcesReady` automatically checks:
137+
- If i18n instance is initialized
138+
- If any resources for the current language are currently loading (SDK backend only)
139+
- If all required namespaces for the current language are loaded in the store
140+
:::
141+
108142
## I18nLink Component
109143

110144
The `I18nLink` component is used to create links with language prefixes.

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

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,38 @@ function MyComponent() {
4949

5050
It's recommended to provide fallback options when resource loading fails:
5151

52+
### Check Resource Loading State
53+
54+
When using SDK backend or need to ensure resources are loaded, use `isResourcesReady` from `useModernI18n`:
55+
56+
```tsx
57+
import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
58+
import { useTranslation } from 'react-i18next';
59+
60+
function MyComponent() {
61+
const { isResourcesReady } = useModernI18n();
62+
const { t } = useTranslation();
63+
64+
// Check if resources are loaded and ready
65+
if (!isResourcesReady) {
66+
return <div>Loading translation resources...</div>;
67+
}
68+
69+
return <div>{t('content', { defaultValue: 'Default content' })}</div>;
70+
}
71+
```
72+
73+
### Alternative: Check i18next Initialization
74+
75+
For simpler cases, you can also check i18next initialization status:
76+
5277
```tsx
5378
import { useTranslation } from 'react-i18next';
5479

5580
function MyComponent() {
5681
const { t, i18n } = useTranslation();
5782

58-
// Check if resources are loaded
83+
// Check if i18n is initialized
5984
if (!i18n.isInitialized) {
6085
return <div>Loading...</div>;
6186
}
@@ -64,6 +89,10 @@ function MyComponent() {
6489
}
6590
```
6691

92+
:::tip
93+
`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+
:::
95+
6796
## Type Safety
6897

6998
Add type definitions for translation keys to improve development experience:
@@ -103,4 +132,3 @@ function MyComponent() {
103132
// return <div>{t('invalid')}</div>; // ❌ TypeScript error
104133
}
105134
```
106-

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

Lines changed: 140 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,23 @@ i18nPlugin({
8585

8686
`backend` is used to configure resource loading methods:
8787

88+
:::info
89+
**Auto-detection**: The plugin automatically detects and enables backend in the following scenarios:
90+
91+
1. **If you configure `loadPath` or `addPath`**: The backend will be automatically enabled (`enabled: true`) without checking for locales directory, since you've already specified the resource path.
92+
93+
2. **If you don't configure backend**: The plugin will automatically detect if a `locales` directory exists in:
94+
- Project root: `{projectRoot}/locales`
95+
- Config public directory: `{projectRoot}/config/public/locales`
96+
- Public directory configured via `server.publicDir`: `{projectRoot}/{publicDir}/locales`
97+
98+
If the directory exists and contains JSON files, the backend will be automatically enabled.
99+
100+
3. **If you explicitly set `enabled: false`**: No auto-detection will be performed, and the backend will remain disabled.
101+
102+
This automatic detection helps reduce unnecessary backend registration when locales directory doesn't exist, improving performance.
103+
:::
104+
88105
```ts
89106
interface BaseBackendOptions {
90107
/** Whether to enable backend resource loading */
@@ -96,10 +113,30 @@ interface BaseBackendOptions {
96113
/** Missing translation save path (optional) */
97114
addPath?: string;
98115

116+
/** Cache hit mode for chained backend (only effective when both `loadPath` and `sdk` are provided)
117+
*
118+
* - `'none'` (default, only when chained backend is not configured): If the first backend returns resources, stop and don't try the next backend
119+
* - `'refresh'`: Try to refresh the cache by loading from the next backend and update the cache
120+
* - `'refreshAndUpdateStore'` (default for chained backend): Try to refresh the cache by loading from the next backend,
121+
* update the cache and also update the i18next resource store. This allows FS/HTTP resources to be displayed first,
122+
* then SDK resources will update them asynchronously.
123+
*
124+
* @default 'refreshAndUpdateStore' when both loadPath and sdk are provided
125+
*/
126+
cacheHitMode?: 'none' | 'refresh' | 'refreshAndUpdateStore';
127+
99128
/** SDK loader function (custom backend)
100129
*
101130
* Note: In CLI configuration, can only be set to `true` or a string identifier to enable SDK mode.
102131
* The actual SDK function must be provided through `initOptions.backend.sdk` in runtime configuration (`modern.runtime.ts`).
132+
*
133+
* When both `loadPath` (or FS backend) and `sdk` are provided, the plugin will automatically use `i18next-chained-backend`
134+
* to chain multiple backends. The loading order will be:
135+
* 1. HTTP/FS backend (primary) - loads from `loadPath` or file system first for quick initial display
136+
* 2. SDK backend (update) - loads from the SDK function to update/refresh translations
137+
*
138+
* With `cacheHitMode: 'refreshAndUpdateStore'` (default), FS/HTTP resources will be displayed immediately,
139+
* then SDK resources will be loaded asynchronously to update the translations.
103140
*/
104141
sdk?: I18nSdkLoader | boolean | string;
105142
}
@@ -110,7 +147,11 @@ interface BackendOptions extends BaseBackendOptions {
110147
}
111148
```
112149

113-
**Example**:
150+
**Examples**:
151+
152+
**1. HTTP/FS backend only**:
153+
154+
You can explicitly enable backend:
114155

115156
```ts
116157
i18nPlugin({
@@ -121,6 +162,104 @@ i18nPlugin({
121162
});
122163
```
123164

165+
Or simply configure `loadPath` or `addPath`, and backend will be automatically enabled:
166+
167+
```ts
168+
i18nPlugin({
169+
backend: {
170+
// enabled will be automatically set to true
171+
loadPath: '/locales/{{lng}}/{{ns}}.json',
172+
},
173+
});
174+
```
175+
176+
**Auto-detection without configuration**:
177+
178+
If you don't configure backend at all, the plugin will automatically detect locales directory:
179+
180+
```ts
181+
i18nPlugin({
182+
// No backend config - plugin will auto-detect locales directory
183+
localeDetection: {
184+
languages: ['zh', 'en'],
185+
fallbackLanguage: 'en',
186+
},
187+
});
188+
```
189+
190+
If `locales` directory exists with JSON files, backend will be automatically enabled with default `loadPath: '/locales/{{lng}}/{{ns}}.json'`.
191+
192+
**2. Chained backend (recommended)**: Use both HTTP/FS backend and SDK backend
193+
194+
When `backend.enabled = true` and `sdk` is configured, if `loadPath` is not explicitly configured, the default `loadPath` will be used automatically and chained backend will be enabled:
195+
196+
```ts
197+
i18nPlugin({
198+
backend: {
199+
enabled: true,
200+
// When loadPath is not configured, default '/locales/{{lng}}/{{ns}}.json' will be used
201+
sdk: true, // SDK backend
202+
// cacheHitMode: 'refreshAndUpdateStore', // Default value, can be omitted
203+
},
204+
});
205+
```
206+
207+
You can also explicitly configure `loadPath`:
208+
209+
```ts
210+
i18nPlugin({
211+
backend: {
212+
enabled: true,
213+
loadPath: '/locales/{{lng}}/{{ns}}.json', // HTTP/FS backend
214+
sdk: true, // SDK backend
215+
},
216+
});
217+
```
218+
219+
Provide the SDK function in `modern.runtime.ts`:
220+
221+
```ts
222+
export default defineRuntimeConfig({
223+
i18n: {
224+
initOptions: {
225+
backend: {
226+
sdk: async options => {
227+
// SDK implementation
228+
if (options.lng && options.ns) {
229+
return await mySdk.getResource(options.lng, options.ns);
230+
}
231+
},
232+
},
233+
},
234+
},
235+
});
236+
```
237+
238+
When using chained backend, the system will:
239+
240+
1. First load resources from `/locales/{{lng}}/{{ns}}.json` and display immediately (quick initial display of basic translations)
241+
2. Then asynchronously load resources from SDK and update the i18next store (update/supplement translations)
242+
243+
This ensures users see page content quickly while the latest translation resources are loaded in the background.
244+
245+
**3. SDK backend only**:
246+
247+
If you need to disable HTTP/FS backend and use only SDK backend, you can explicitly set `loadPath: ''`:
248+
249+
```ts
250+
i18nPlugin({
251+
backend: {
252+
enabled: true,
253+
loadPath: '', // Explicitly disable HTTP/FS backend
254+
sdk: true, // Use SDK backend only
255+
},
256+
});
257+
```
258+
259+
:::warning
260+
When using SDK backend only, you must provide the actual SDK function in `modern.runtime.ts`, otherwise it will fallback to HTTP/FS backend.
261+
:::
262+
124263
### Multi-Entry Configuration
125264

126265
If the project has multiple entries, you can configure each entry separately:
@@ -279,4 +418,3 @@ export default defineRuntimeConfig({
279418
},
280419
});
281420
```
282-

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ export default defineConfig({
4141
backend: {
4242
enabled: true, // Enable backend resource loading
4343
// loadPath defaults to '/locales/{{lng}}/{{ns}}.json', usually no need to modify
44+
// Note: You can also omit 'enabled' and just configure 'loadPath' or 'addPath',
45+
// or omit backend config entirely to let the plugin auto-detect locales directory
4446
},
4547
}),
4648
],

0 commit comments

Comments
 (0)