astro-react-i18next 0.1.3 → 0.3.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/README.md +37 -18
- package/dist/index.d.ts +6 -1
- package/dist/index.js +48 -26
- package/dist/middleware-server.js +16 -4
- package/dist/middleware-static.js +3 -2
- package/dist/utils.d.ts +2 -5
- package/dist/utils.js +3 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,14 +39,16 @@ export default defineConfig({
|
|
|
39
39
|
|
|
40
40
|
The initialization function accepts an optional configuration object with the following options:
|
|
41
41
|
|
|
42
|
-
| Option | Type
|
|
43
|
-
| --------------------- |
|
|
44
|
-
| `defaultLocale` | `string`
|
|
45
|
-
| `locales` | `string[]`
|
|
46
|
-
| `defaultNamespace` | `string`
|
|
47
|
-
| `namespaces` | `string[]`
|
|
48
|
-
| `prefixDefaultLocale` | `boolean`
|
|
49
|
-
| `localesDir` | `string`
|
|
42
|
+
| Option | Type | Description | Default |
|
|
43
|
+
| --------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------- | ------------ |
|
|
44
|
+
| `defaultLocale` | `string` | The default locale to use when no locale is specified. | `"en-US"` |
|
|
45
|
+
| `locales` | `string[]` | An array of locales to support. | `["en-US"]` |
|
|
46
|
+
| `defaultNamespace` | `string` | The default namespace to use when no namespace is specified. | `"common"` |
|
|
47
|
+
| `namespaces` | `string[]` | An array of namespaces to support. | `["common"]` |
|
|
48
|
+
| `prefixDefaultLocale` | `boolean` | Whether to prefix the default locale with the locale code. | `false` |
|
|
49
|
+
| `localesDir` | `string` | The directory where the locale files are stored, relative to the public directory. | `"locales"` |
|
|
50
|
+
| `domains` | `{ domain: string; defaultLocale: string; }[]` | An array of domains for language selection. | `[]` |
|
|
51
|
+
| `reservedRoutes` | `string[]` | An array of routes excluded from locale handling. | `["/api"]` |
|
|
50
52
|
|
|
51
53
|
Here is an example of how to configure the integration:
|
|
52
54
|
|
|
@@ -62,8 +64,6 @@ export default defineConfig({
|
|
|
62
64
|
+ reactI18next({
|
|
63
65
|
+ defaultLocale: "en-US",
|
|
64
66
|
+ locales: ["en-US", "fr-FR", "zh-TW"],
|
|
65
|
-
+ defaultNamespace: "app",
|
|
66
|
-
+ namespaces: ["app"],
|
|
67
67
|
+ }),
|
|
68
68
|
],
|
|
69
69
|
});
|
|
@@ -83,8 +83,6 @@ export default defineConfig({
|
|
|
83
83
|
reactI18next({
|
|
84
84
|
defaultLocale: "en-US",
|
|
85
85
|
locales: ["en-US", "fr-FR", "zh-TW"],
|
|
86
|
-
defaultNamespace: "app",
|
|
87
|
-
namespaces: ["app"],
|
|
88
86
|
}),
|
|
89
87
|
],
|
|
90
88
|
+ output: "server",
|
|
@@ -189,12 +187,33 @@ The integration provides utility functions to help manage locales and translatio
|
|
|
189
187
|
|
|
190
188
|
All utility functions are available in the `astro-react-i18next/utils` module.
|
|
191
189
|
|
|
192
|
-
| Function | Description | Returns
|
|
193
|
-
| -------------------------------------------------- | -------------------------------------------------------- |
|
|
194
|
-
| `getLocaleConfig()` | Returns the locale configuration object. | `{ defaultLocale: string
|
|
195
|
-
| `getLocalizedPathname(pathname = "", locale = "")` | Returns the localized pathname for the specified locale. | string
|
|
196
|
-
| `buildStaticPaths()` | Generates static paths for each locale. | `{ params: { locale: string \| undefined; }; }[]`
|
|
197
|
-
| `changeLocale(nextLocale = "", shallow = true)` | Changes the current locale. |
|
|
190
|
+
| Function | Description | Returns |
|
|
191
|
+
| -------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
192
|
+
| `getLocaleConfig()` | Returns the locale configuration object. | `{ defaultLocale: string; locales: string[]; prefixDefaultLocale: boolean; domains: { domain: string; defaultLocale: string; }[]; reservedRoutes: string[]; }` |
|
|
193
|
+
| `getLocalizedPathname(pathname = "", locale = "")` | Returns the localized pathname for the specified locale. | `string` |
|
|
194
|
+
| `buildStaticPaths()` | Generates static paths for each locale. | `{ params: { locale: string \| undefined; }; }[]` |
|
|
195
|
+
| `changeLocale(nextLocale = "", shallow = true)` | Changes the current locale. | |
|
|
196
|
+
|
|
197
|
+
## Developing locally
|
|
198
|
+
|
|
199
|
+
Clone the repository:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
git clone https://github.com/jeremyxgo/astro-react-i18next.git
|
|
203
|
+
cd astro-react-i18next
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Build the package:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
npm run build
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Install the package in your project:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
npm install $(npm pack /path/to/astro-react-i18next | tail -1)
|
|
216
|
+
```
|
|
198
217
|
|
|
199
218
|
## License
|
|
200
219
|
|
package/dist/index.d.ts
CHANGED
|
@@ -6,13 +6,18 @@ interface AstroReactI18nextOptions {
|
|
|
6
6
|
namespaces?: string[];
|
|
7
7
|
prefixDefaultLocale?: boolean;
|
|
8
8
|
localesDir?: string;
|
|
9
|
+
domains?: {
|
|
10
|
+
domain: string;
|
|
11
|
+
defaultLocale: string;
|
|
12
|
+
}[];
|
|
13
|
+
reservedRoutes?: string[];
|
|
9
14
|
}
|
|
10
15
|
type MergedAstroReactI18nextOptions = {
|
|
11
16
|
[key in keyof AstroReactI18nextOptions]-?: AstroReactI18nextOptions[key];
|
|
12
17
|
};
|
|
13
18
|
declare module "i18next" {
|
|
14
19
|
interface InitOptions {
|
|
15
|
-
astroReactI18next: MergedAstroReactI18nextOptions
|
|
20
|
+
astroReactI18next: Pick<MergedAstroReactI18nextOptions, "defaultLocale" | "locales" | "prefixDefaultLocale" | "domains" | "reservedRoutes">;
|
|
16
21
|
}
|
|
17
22
|
}
|
|
18
23
|
export default function AstroReactI18nextIntegration(options?: AstroReactI18nextOptions): AstroIntegration;
|
package/dist/index.js
CHANGED
|
@@ -7,17 +7,15 @@ var DEFAULT_OPTIONS = {
|
|
|
7
7
|
defaultNamespace: "common",
|
|
8
8
|
namespaces: ["common"],
|
|
9
9
|
prefixDefaultLocale: false,
|
|
10
|
-
localesDir: "locales"
|
|
10
|
+
localesDir: "locales",
|
|
11
|
+
domains: [],
|
|
12
|
+
reservedRoutes: ["/api"]
|
|
11
13
|
};
|
|
12
14
|
function buildI18nextInitScript({
|
|
13
15
|
backendType,
|
|
14
16
|
basePath,
|
|
15
|
-
|
|
17
|
+
mergedOptions
|
|
16
18
|
}) {
|
|
17
|
-
const mergedOptions = {
|
|
18
|
-
...DEFAULT_OPTIONS,
|
|
19
|
-
...options
|
|
20
|
-
};
|
|
21
19
|
let imports = "";
|
|
22
20
|
let i18nextPlugins = "";
|
|
23
21
|
let i18nextOptions = "";
|
|
@@ -64,13 +62,47 @@ function buildI18nextInitScript({
|
|
|
64
62
|
escapeValue: false,
|
|
65
63
|
},
|
|
66
64
|
backend: {
|
|
67
|
-
loadPath: "${path.join(basePath, mergedOptions.localesDir)}/{{lng}}/{{ns}}.json",
|
|
65
|
+
loadPath: "${path.join(basePath, mergedOptions.localesDir || "")}/{{lng}}/{{ns}}.json",
|
|
68
66
|
},
|
|
69
|
-
astroReactI18next: ${JSON.stringify(
|
|
67
|
+
astroReactI18next: ${JSON.stringify({
|
|
68
|
+
defaultLocale: mergedOptions.defaultLocale,
|
|
69
|
+
locales: mergedOptions.locales,
|
|
70
|
+
prefixDefaultLocale: mergedOptions.prefixDefaultLocale,
|
|
71
|
+
domains: mergedOptions.domains,
|
|
72
|
+
reservedRoutes: mergedOptions.reservedRoutes
|
|
73
|
+
})},
|
|
70
74
|
${i18nextOptions}
|
|
71
75
|
});
|
|
72
76
|
`;
|
|
73
77
|
}
|
|
78
|
+
function buildLocaleRestorationScript(mergedOptions) {
|
|
79
|
+
return `
|
|
80
|
+
window.addEventListener("DOMContentLoaded", () => {
|
|
81
|
+
const defaultLocale = "${mergedOptions.defaultLocale}";
|
|
82
|
+
const locales = ${JSON.stringify(mergedOptions.locales)};
|
|
83
|
+
const reservedRoutes = ${JSON.stringify(mergedOptions.reservedRoutes)};
|
|
84
|
+
const pathname = window.location.pathname;
|
|
85
|
+
|
|
86
|
+
if (
|
|
87
|
+
reservedRoutes.some(
|
|
88
|
+
(route) =>
|
|
89
|
+
pathname === route ||
|
|
90
|
+
pathname.startsWith(route + "/"),
|
|
91
|
+
)
|
|
92
|
+
) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let detectedLocale = pathname.split("/")[1];
|
|
97
|
+
|
|
98
|
+
if (!locales.includes(detectedLocale)) {
|
|
99
|
+
detectedLocale = defaultLocale;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
i18n.changeLanguage(detectedLocale);
|
|
103
|
+
});
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
74
106
|
function AstroReactI18nextIntegration(options) {
|
|
75
107
|
const mergedOptions = {
|
|
76
108
|
...DEFAULT_OPTIONS,
|
|
@@ -85,39 +117,29 @@ function AstroReactI18nextIntegration(options) {
|
|
|
85
117
|
injectScript,
|
|
86
118
|
updateConfig
|
|
87
119
|
}) => {
|
|
88
|
-
const
|
|
89
|
-
window.addEventListener("DOMContentLoaded", () => {
|
|
90
|
-
const defaultLocale = "${mergedOptions.defaultLocale}";
|
|
91
|
-
const locales = ${JSON.stringify(mergedOptions.locales)};
|
|
92
|
-
let detectedLocale = window.location.pathname.split("/")[1];
|
|
93
|
-
|
|
94
|
-
if (!locales.includes(detectedLocale)) {
|
|
95
|
-
detectedLocale = defaultLocale;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
i18n.changeLanguage(detectedLocale);
|
|
99
|
-
});
|
|
100
|
-
`;
|
|
120
|
+
const middlewareEntrypoint = config.output === "server" ? `${INTEGRATION_NAME}/middleware/server` : `${INTEGRATION_NAME}/middleware/static`;
|
|
101
121
|
const clientI18nextInitScript = buildI18nextInitScript({
|
|
102
122
|
backendType: "http",
|
|
103
123
|
basePath: "/",
|
|
104
|
-
|
|
124
|
+
mergedOptions
|
|
105
125
|
});
|
|
106
126
|
const serverI18nextInitScript = buildI18nextInitScript({
|
|
107
127
|
backendType: "fs",
|
|
108
128
|
basePath: config.publicDir.pathname,
|
|
109
|
-
|
|
129
|
+
mergedOptions
|
|
110
130
|
});
|
|
111
|
-
const
|
|
131
|
+
const localeRestorationScript = buildLocaleRestorationScript(mergedOptions);
|
|
112
132
|
addMiddleware({
|
|
113
133
|
entrypoint: middlewareEntrypoint,
|
|
114
134
|
order: "post"
|
|
115
135
|
});
|
|
116
136
|
injectScript("page-ssr", serverI18nextInitScript);
|
|
117
137
|
injectScript("before-hydration", clientI18nextInitScript);
|
|
118
|
-
injectScript("before-hydration", clientLocaleRestorationScript);
|
|
119
138
|
injectScript("page", clientI18nextInitScript);
|
|
120
|
-
|
|
139
|
+
if (mergedOptions.domains.length === 0) {
|
|
140
|
+
injectScript("before-hydration", localeRestorationScript);
|
|
141
|
+
injectScript("page", localeRestorationScript);
|
|
142
|
+
}
|
|
121
143
|
updateConfig({
|
|
122
144
|
i18n: {
|
|
123
145
|
locales: mergedOptions.locales,
|
|
@@ -4,8 +4,9 @@ import i18n2 from "i18next";
|
|
|
4
4
|
// src/utils.ts
|
|
5
5
|
import i18n from "i18next";
|
|
6
6
|
function getLocaleConfig() {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
return JSON.parse(
|
|
8
|
+
JSON.stringify(i18n.options.astroReactI18next)
|
|
9
|
+
);
|
|
9
10
|
}
|
|
10
11
|
function getLocalizedPathname(pathname = "", locale = "") {
|
|
11
12
|
const { defaultLocale, locales, prefixDefaultLocale } = getLocaleConfig();
|
|
@@ -21,12 +22,23 @@ function getLocalizedPathname(pathname = "", locale = "") {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
// src/middleware-server.ts
|
|
25
|
+
var ASTRO_RESERVED_ROUTES = ["/_astro", "/_actions", "/_server-islands"];
|
|
24
26
|
async function onRequest(context, next) {
|
|
25
|
-
const { defaultLocale, locales } = getLocaleConfig();
|
|
27
|
+
const { defaultLocale, locales, domains, reservedRoutes } = getLocaleConfig();
|
|
28
|
+
if ([...ASTRO_RESERVED_ROUTES, ...reservedRoutes].some(
|
|
29
|
+
(route) => context.url.pathname === route || context.url.pathname.startsWith(route + "/")
|
|
30
|
+
)) {
|
|
31
|
+
return next();
|
|
32
|
+
}
|
|
33
|
+
const localesByDomain = Object.fromEntries(
|
|
34
|
+
domains.map((domain) => [domain.domain, domain.defaultLocale])
|
|
35
|
+
);
|
|
36
|
+
const localeFromDomain = localesByDomain[context.url.host];
|
|
26
37
|
const localeFromPathname = context.url.pathname.split("/")[1];
|
|
27
38
|
const localeFromCookie = context.cookies.get("i18next")?.value;
|
|
28
39
|
const localeFromHeader = context.preferredLocale;
|
|
29
40
|
const nextLocale = [
|
|
41
|
+
localeFromDomain,
|
|
30
42
|
localeFromPathname,
|
|
31
43
|
localeFromCookie,
|
|
32
44
|
localeFromHeader,
|
|
@@ -36,7 +48,7 @@ async function onRequest(context, next) {
|
|
|
36
48
|
context.cookies.set("i18next", nextLocale || "", { path: "/" });
|
|
37
49
|
const { hash, pathname, search } = context.url;
|
|
38
50
|
const nextPathname = getLocalizedPathname(pathname, nextLocale);
|
|
39
|
-
if (nextPathname !== pathname) {
|
|
51
|
+
if (nextPathname !== pathname && domains.length === 0) {
|
|
40
52
|
const nextUrl = nextPathname + search + hash;
|
|
41
53
|
return context.redirect(nextUrl);
|
|
42
54
|
}
|
|
@@ -4,8 +4,9 @@ import i18n2 from "i18next";
|
|
|
4
4
|
// src/utils.ts
|
|
5
5
|
import i18n from "i18next";
|
|
6
6
|
function getLocaleConfig() {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
return JSON.parse(
|
|
8
|
+
JSON.stringify(i18n.options.astroReactI18next)
|
|
9
|
+
);
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
// src/middleware-static.ts
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
locales: string[];
|
|
4
|
-
prefixDefaultLocale: boolean;
|
|
5
|
-
};
|
|
1
|
+
import i18n from "i18next";
|
|
2
|
+
export declare function getLocaleConfig(): typeof i18n.options.astroReactI18next;
|
|
6
3
|
export declare function getLocalizedPathname(pathname?: string, locale?: string): string;
|
|
7
4
|
export declare function buildStaticPaths(): {
|
|
8
5
|
params: {
|
package/dist/utils.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// src/utils.ts
|
|
2
2
|
import i18n from "i18next";
|
|
3
3
|
function getLocaleConfig() {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
return JSON.parse(
|
|
5
|
+
JSON.stringify(i18n.options.astroReactI18next)
|
|
6
|
+
);
|
|
6
7
|
}
|
|
7
8
|
function getLocalizedPathname(pathname = "", locale = "") {
|
|
8
9
|
const { defaultLocale, locales, prefixDefaultLocale } = getLocaleConfig();
|
package/package.json
CHANGED