@bleedingdev/modern-js-plugin-i18n 3.5.0-ultramodern.36 → 3.5.0-ultramodern.37
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/dist/cjs/cli/locales.js +15 -15
- package/dist/cjs/runtime/i18n/backend/defaults.node.js +7 -7
- package/dist/cjs/runtime/i18n/detection/cache.js +3 -2
- package/dist/cjs/runtime/i18n/instance.js +7 -7
- package/dist/cjs/runtime/utils.js +1 -9
- package/dist/cjs/server/redirectPolicy.js +14 -20
- package/dist/cjs/shared/detection.js +2 -104
- package/dist/cjs/shared/localisedUrls/index.js +16 -0
- package/dist/cjs/shared/localisedUrls/pathname.js +5 -2
- package/dist/cjs/shared/localisedUrls/redirect.js +95 -0
- package/dist/cjs/shared/localisedUrls/resolve.js +29 -32
- package/dist/cjs/shared/localisedUrls.js +15 -0
- package/dist/cjs/shared/utils.js +2 -8
- package/dist/esm/cli/locales.mjs +13 -13
- package/dist/esm/runtime/i18n/backend/defaults.node.mjs +5 -5
- package/dist/esm/runtime/i18n/detection/cache.mjs +3 -2
- package/dist/esm/runtime/i18n/instance.mjs +8 -5
- package/dist/esm/runtime/utils.mjs +2 -10
- package/dist/esm/server/index.mjs +2 -2
- package/dist/esm/server/redirectPolicy.mjs +15 -21
- package/dist/esm/shared/detection.mjs +1 -71
- package/dist/esm/shared/localisedUrls/index.mjs +2 -1
- package/dist/esm/shared/localisedUrls/pathname.mjs +1 -1
- package/dist/esm/shared/localisedUrls/redirect.mjs +48 -0
- package/dist/esm/shared/localisedUrls/resolve.mjs +29 -32
- package/dist/esm/shared/localisedUrls.mjs +1 -1
- package/dist/esm/shared/utils.mjs +1 -1
- package/dist/esm-node/cli/locales.mjs +13 -13
- package/dist/esm-node/runtime/i18n/backend/defaults.node.mjs +5 -5
- package/dist/esm-node/runtime/i18n/detection/cache.mjs +3 -2
- package/dist/esm-node/runtime/i18n/instance.mjs +8 -5
- package/dist/esm-node/runtime/utils.mjs +2 -10
- package/dist/esm-node/server/index.mjs +2 -2
- package/dist/esm-node/server/redirectPolicy.mjs +15 -21
- package/dist/esm-node/shared/detection.mjs +1 -71
- package/dist/esm-node/shared/localisedUrls/index.mjs +2 -1
- package/dist/esm-node/shared/localisedUrls/pathname.mjs +1 -1
- package/dist/esm-node/shared/localisedUrls/redirect.mjs +49 -0
- package/dist/esm-node/shared/localisedUrls/resolve.mjs +29 -32
- package/dist/esm-node/shared/localisedUrls.mjs +1 -1
- package/dist/esm-node/shared/utils.mjs +1 -1
- package/dist/types/cli/locales.d.ts +1 -1
- package/dist/types/runtime/context.d.ts +4 -3
- package/dist/types/runtime/contextHelpers.d.ts +2 -2
- package/dist/types/runtime/i18n/backend/middleware.common.d.ts +2 -1
- package/dist/types/runtime/i18n/detection/cache.d.ts +1 -1
- package/dist/types/runtime/i18n/detection/detector.d.ts +2 -2
- package/dist/types/runtime/i18n/detection/middleware.d.ts +4 -4
- package/dist/types/runtime/i18n/detection/middleware.node.d.ts +4 -4
- package/dist/types/runtime/i18n/detection/types.d.ts +8 -5
- package/dist/types/runtime/i18n/instance.d.ts +28 -26
- package/dist/types/runtime/i18n/utils.d.ts +14 -5
- package/dist/types/runtime/pluginSetup.d.ts +1 -1
- package/dist/types/runtime/providerComposition.d.ts +2 -1
- package/dist/types/runtime/routerAdapter.d.ts +7 -6
- package/dist/types/server/redirectPolicy.d.ts +14 -8
- package/dist/types/shared/detection.d.ts +1 -11
- package/dist/types/shared/localisedUrls/index.d.ts +3 -1
- package/dist/types/shared/localisedUrls/pathname.d.ts +1 -0
- package/dist/types/shared/localisedUrls/redirect.d.ts +11 -0
- package/dist/types/shared/localisedUrls/resolve.d.ts +2 -3
- package/dist/types/shared/localisedUrls.d.ts +2 -2
- package/dist/types/shared/utils.d.ts +0 -2
- package/package.json +16 -18
- package/src/cli/index.ts +2 -2
- package/src/cli/locales.ts +3 -3
- package/src/runtime/context.tsx +3 -3
- package/src/runtime/contextHelpers.ts +3 -3
- package/src/runtime/hooks.ts +10 -2
- package/src/runtime/i18n/backend/defaults.node.ts +2 -2
- package/src/runtime/i18n/backend/middleware.common.ts +5 -4
- package/src/runtime/i18n/detection/cache.ts +23 -9
- package/src/runtime/i18n/detection/detector.ts +15 -6
- package/src/runtime/i18n/detection/middleware.node.ts +26 -7
- package/src/runtime/i18n/detection/middleware.ts +15 -7
- package/src/runtime/i18n/detection/types.ts +13 -5
- package/src/runtime/i18n/instance.ts +56 -31
- package/src/runtime/i18n/utils.ts +18 -9
- package/src/runtime/pluginSetup.ts +1 -1
- package/src/runtime/providerComposition.tsx +1 -1
- package/src/runtime/routerAdapter.tsx +6 -6
- package/src/runtime/utils.ts +5 -29
- package/src/server/redirectPolicy.ts +51 -76
- package/src/shared/detection.ts +1 -1
- package/src/shared/localisedUrls/index.ts +12 -1
- package/src/shared/localisedUrls/pathname.ts +4 -1
- package/src/shared/localisedUrls/redirect.ts +91 -0
- package/src/shared/localisedUrls/resolve.ts +91 -74
- package/src/shared/localisedUrls.ts +6 -0
- package/src/shared/utils.ts +2 -2
- package/tests/redirectPolicy.test.ts +43 -0
|
@@ -28,41 +28,56 @@ var __webpack_require__ = {};
|
|
|
28
28
|
var __webpack_exports__ = {};
|
|
29
29
|
__webpack_require__.r(__webpack_exports__);
|
|
30
30
|
__webpack_require__.d(__webpack_exports__, {
|
|
31
|
+
DEFAULT_LOCALE_REDIRECT_SKIP_RULES: ()=>index_js_namespaceObject.DEFAULT_LOCALE_REDIRECT_SKIP_RULES,
|
|
31
32
|
applyLocalisedUrlsToRoutes: ()=>index_js_namespaceObject.applyLocalisedUrlsToRoutes,
|
|
32
33
|
buildPathFromPattern: ()=>index_js_namespaceObject.buildPathFromPattern,
|
|
33
34
|
canonicalTargetPathname: ()=>index_js_namespaceObject.canonicalTargetPathname,
|
|
35
|
+
isDefaultLocaleRedirectSkipPath: ()=>index_js_namespaceObject.isDefaultLocaleRedirectSkipPath,
|
|
34
36
|
localiseTargetPathname: ()=>index_js_namespaceObject.localiseTargetPathname,
|
|
35
37
|
matchPathPattern: ()=>index_js_namespaceObject.matchPathPattern,
|
|
38
|
+
matchesPathPrefix: ()=>index_js_namespaceObject.matchesPathPrefix,
|
|
36
39
|
normalisePathPattern: ()=>index_js_namespaceObject.normalisePathPattern,
|
|
37
40
|
normalisePathname: ()=>index_js_namespaceObject.normalisePathname,
|
|
38
41
|
resolveCanonicalLocalisedPath: ()=>index_js_namespaceObject.resolveCanonicalLocalisedPath,
|
|
39
42
|
resolveLocalisedPath: ()=>index_js_namespaceObject.resolveLocalisedPath,
|
|
40
43
|
resolveLocalisedUrlsConfig: ()=>index_js_namespaceObject.resolveLocalisedUrlsConfig,
|
|
44
|
+
shouldSkipLocaleRedirect: ()=>index_js_namespaceObject.shouldSkipLocaleRedirect,
|
|
45
|
+
stripLanguagePrefix: ()=>index_js_namespaceObject.stripLanguagePrefix,
|
|
41
46
|
validateLocalisedUrls: ()=>index_js_namespaceObject.validateLocalisedUrls
|
|
42
47
|
});
|
|
43
48
|
const index_js_namespaceObject = require("./localisedUrls/index.js");
|
|
49
|
+
exports.DEFAULT_LOCALE_REDIRECT_SKIP_RULES = __webpack_exports__.DEFAULT_LOCALE_REDIRECT_SKIP_RULES;
|
|
44
50
|
exports.applyLocalisedUrlsToRoutes = __webpack_exports__.applyLocalisedUrlsToRoutes;
|
|
45
51
|
exports.buildPathFromPattern = __webpack_exports__.buildPathFromPattern;
|
|
46
52
|
exports.canonicalTargetPathname = __webpack_exports__.canonicalTargetPathname;
|
|
53
|
+
exports.isDefaultLocaleRedirectSkipPath = __webpack_exports__.isDefaultLocaleRedirectSkipPath;
|
|
47
54
|
exports.localiseTargetPathname = __webpack_exports__.localiseTargetPathname;
|
|
48
55
|
exports.matchPathPattern = __webpack_exports__.matchPathPattern;
|
|
56
|
+
exports.matchesPathPrefix = __webpack_exports__.matchesPathPrefix;
|
|
49
57
|
exports.normalisePathPattern = __webpack_exports__.normalisePathPattern;
|
|
50
58
|
exports.normalisePathname = __webpack_exports__.normalisePathname;
|
|
51
59
|
exports.resolveCanonicalLocalisedPath = __webpack_exports__.resolveCanonicalLocalisedPath;
|
|
52
60
|
exports.resolveLocalisedPath = __webpack_exports__.resolveLocalisedPath;
|
|
53
61
|
exports.resolveLocalisedUrlsConfig = __webpack_exports__.resolveLocalisedUrlsConfig;
|
|
62
|
+
exports.shouldSkipLocaleRedirect = __webpack_exports__.shouldSkipLocaleRedirect;
|
|
63
|
+
exports.stripLanguagePrefix = __webpack_exports__.stripLanguagePrefix;
|
|
54
64
|
exports.validateLocalisedUrls = __webpack_exports__.validateLocalisedUrls;
|
|
55
65
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
66
|
+
"DEFAULT_LOCALE_REDIRECT_SKIP_RULES",
|
|
56
67
|
"applyLocalisedUrlsToRoutes",
|
|
57
68
|
"buildPathFromPattern",
|
|
58
69
|
"canonicalTargetPathname",
|
|
70
|
+
"isDefaultLocaleRedirectSkipPath",
|
|
59
71
|
"localiseTargetPathname",
|
|
60
72
|
"matchPathPattern",
|
|
73
|
+
"matchesPathPrefix",
|
|
61
74
|
"normalisePathPattern",
|
|
62
75
|
"normalisePathname",
|
|
63
76
|
"resolveCanonicalLocalisedPath",
|
|
64
77
|
"resolveLocalisedPath",
|
|
65
78
|
"resolveLocalisedUrlsConfig",
|
|
79
|
+
"shouldSkipLocaleRedirect",
|
|
80
|
+
"stripLanguagePrefix",
|
|
66
81
|
"validateLocalisedUrls"
|
|
67
82
|
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
68
83
|
Object.defineProperty(exports, '__esModule', {
|
package/dist/cjs/shared/utils.js
CHANGED
|
@@ -63,19 +63,13 @@ function getBackendOptions(entryName, backend) {
|
|
|
63
63
|
}
|
|
64
64
|
__webpack_require__.d(__webpack_exports__, {
|
|
65
65
|
getBackendOptions: ()=>getBackendOptions,
|
|
66
|
-
|
|
67
|
-
getLocaleDetectionOptions: ()=>getLocaleDetectionOptions,
|
|
68
|
-
removeEntryConfigKey: ()=>removeEntryConfigKey
|
|
66
|
+
getLocaleDetectionOptions: ()=>getLocaleDetectionOptions
|
|
69
67
|
});
|
|
70
68
|
exports.getBackendOptions = __webpack_exports__.getBackendOptions;
|
|
71
|
-
exports.getEntryConfig = __webpack_exports__.getEntryConfig;
|
|
72
69
|
exports.getLocaleDetectionOptions = __webpack_exports__.getLocaleDetectionOptions;
|
|
73
|
-
exports.removeEntryConfigKey = __webpack_exports__.removeEntryConfigKey;
|
|
74
70
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
75
71
|
"getBackendOptions",
|
|
76
|
-
"
|
|
77
|
-
"getLocaleDetectionOptions",
|
|
78
|
-
"removeEntryConfigKey"
|
|
72
|
+
"getLocaleDetectionOptions"
|
|
79
73
|
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
80
74
|
Object.defineProperty(exports, '__esModule', {
|
|
81
75
|
value: true
|
package/dist/esm/cli/locales.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import node_fs from "node:fs";
|
|
2
|
+
import node_path from "node:path";
|
|
1
3
|
import { getPublicDirRoutePrefixes, normalizePublicDir, normalizePublicDirPath } from "@modern-js/server-core";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import path from "path";
|
|
4
4
|
const LOCALES_RESOURCE_PATTERN = '{{lng}}/{{ns}}.json';
|
|
5
5
|
function hasJsonFiles(dirPath) {
|
|
6
6
|
try {
|
|
7
|
-
if (!
|
|
8
|
-
const entries =
|
|
7
|
+
if (!node_fs.existsSync(dirPath) || !node_fs.statSync(dirPath).isDirectory()) return false;
|
|
8
|
+
const entries = node_fs.readdirSync(dirPath);
|
|
9
9
|
for (const entry of entries){
|
|
10
|
-
const entryPath =
|
|
11
|
-
const stat =
|
|
10
|
+
const entryPath = node_path.join(dirPath, entry);
|
|
11
|
+
const stat = node_fs.statSync(entryPath);
|
|
12
12
|
if (stat.isFile() && entry.endsWith('.json')) return true;
|
|
13
13
|
if (stat.isDirectory() && hasJsonFiles(entryPath)) return true;
|
|
14
14
|
}
|
|
@@ -18,7 +18,7 @@ function hasJsonFiles(dirPath) {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
function toPosixPath(filePath) {
|
|
21
|
-
return filePath.split(
|
|
21
|
+
return filePath.split(node_path.sep).join(node_path.posix.sep);
|
|
22
22
|
}
|
|
23
23
|
function getPublicDirOutputPath(publicDir) {
|
|
24
24
|
return normalizePublicDirPath(publicDir);
|
|
@@ -45,20 +45,20 @@ function detectLocalesDirectory(appDirectory, normalizedConfig) {
|
|
|
45
45
|
const publicDirPrefixes = getPublicDirRoutePrefixes(normalizedConfig?.server?.publicDir);
|
|
46
46
|
for(let index = 0; index < publicDirs.length; index++){
|
|
47
47
|
const publicDir = publicDirs[index];
|
|
48
|
-
if (
|
|
49
|
-
const publicDirPath =
|
|
48
|
+
if (node_path.isAbsolute(publicDir)) continue;
|
|
49
|
+
const publicDirPath = node_path.join(appDirectory, publicDir);
|
|
50
50
|
const publicDirPrefix = publicDirPrefixes[index] || `/${normalizePublicDirPath(publicDir)}`;
|
|
51
51
|
const publicDirOutputPath = getPublicDirOutputPath(publicDir);
|
|
52
|
-
if ('locales' ===
|
|
53
|
-
const localesPath =
|
|
52
|
+
if ('locales' === node_path.basename(normalizePublicDirPath(publicDir)) && hasJsonFiles(publicDirPath)) return buildDetectedLocalesDirectory(publicDirPrefix, `./${publicDirOutputPath}`);
|
|
53
|
+
const localesPath = node_path.join(publicDirPath, 'locales');
|
|
54
54
|
if (hasJsonFiles(localesPath)) return buildDetectedLocalesDirectory(`${publicDirPrefix}/locales`, `./${publicDirOutputPath}/locales`);
|
|
55
55
|
}
|
|
56
|
-
const configPublicPath =
|
|
56
|
+
const configPublicPath = node_path.join(appDirectory, 'config', 'public', 'locales');
|
|
57
57
|
if (hasJsonFiles(configPublicPath)) return buildDetectedLocalesDirectory('/locales', './public/locales', [
|
|
58
58
|
'./config/public/locales',
|
|
59
59
|
'./public/locales'
|
|
60
60
|
]);
|
|
61
|
-
const rootLocalesPath =
|
|
61
|
+
const rootLocalesPath = node_path.join(appDirectory, 'locales');
|
|
62
62
|
if (hasJsonFiles(rootLocalesPath)) return buildDetectedLocalesDirectory('/locales', './locales');
|
|
63
63
|
}
|
|
64
64
|
function applyDetectedBackendPaths(backendOptions, detectedLocales) {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import node_fs from "node:fs";
|
|
2
|
+
import node_path from "node:path";
|
|
3
3
|
const CONVENTIONAL_LOCALES_DIRS = [
|
|
4
4
|
'./locales',
|
|
5
5
|
'./config/public/locales'
|
|
6
6
|
];
|
|
7
7
|
const isDirectory = (dirPath)=>{
|
|
8
8
|
try {
|
|
9
|
-
return
|
|
9
|
+
return node_fs.statSync(dirPath).isDirectory();
|
|
10
10
|
} catch {
|
|
11
11
|
return false;
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
const resolveDefaultLocalesDir = (cwd = process.cwd())=>{
|
|
15
|
-
for (const dir of CONVENTIONAL_LOCALES_DIRS)if (isDirectory(
|
|
15
|
+
for (const dir of CONVENTIONAL_LOCALES_DIRS)if (isDirectory(node_path.resolve(cwd, dir))) return dir;
|
|
16
16
|
return CONVENTIONAL_LOCALES_DIRS[0];
|
|
17
17
|
};
|
|
18
18
|
const DEFAULT_I18NEXT_BACKEND_OPTIONS = {
|
|
@@ -38,7 +38,7 @@ function getResourceBasePath(resourcePath) {
|
|
|
38
38
|
}
|
|
39
39
|
function pathExists(resourcePath) {
|
|
40
40
|
try {
|
|
41
|
-
return
|
|
41
|
+
return node_fs.existsSync(getResourceBasePath(resourcePath));
|
|
42
42
|
} catch {
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
@@ -21,9 +21,10 @@ const stableStringify = (value)=>{
|
|
|
21
21
|
if (null == value) return JSON.stringify(value);
|
|
22
22
|
if ('object' != typeof value) return JSON.stringify(value);
|
|
23
23
|
if (Array.isArray(value)) return `[${value.map((item)=>stableStringify(item)).join(',')}]`;
|
|
24
|
-
const
|
|
24
|
+
const record = value;
|
|
25
|
+
const sortedKeys = Object.keys(record).sort();
|
|
25
26
|
const sortedEntries = sortedKeys.map((key)=>{
|
|
26
|
-
const stringifiedValue = stableStringify(
|
|
27
|
+
const stringifiedValue = stableStringify(record[key]);
|
|
27
28
|
return `${JSON.stringify(key)}:${stringifiedValue}`;
|
|
28
29
|
});
|
|
29
30
|
return `{${sortedEntries.join(',')}}`;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
function isI18nWrapperInstance(obj) {
|
|
2
2
|
if (!obj || 'object' != typeof obj) return false;
|
|
3
|
-
|
|
4
|
-
if (!
|
|
5
|
-
|
|
3
|
+
const candidate = obj;
|
|
4
|
+
if (!candidate.i18nInstance || 'object' != typeof candidate.i18nInstance) return false;
|
|
5
|
+
const wrapper = candidate.i18nInstance;
|
|
6
|
+
if (!wrapper.instance) return false;
|
|
7
|
+
if ('function' != typeof candidate.init || 'function' != typeof candidate.use) return false;
|
|
6
8
|
return true;
|
|
7
9
|
}
|
|
8
10
|
function getI18nWrapperI18nextInstance(wrapperInstance) {
|
|
@@ -19,7 +21,8 @@ function getActualI18nextInstance(instance) {
|
|
|
19
21
|
function isI18nInstance(obj) {
|
|
20
22
|
if (!obj || 'object' != typeof obj) return false;
|
|
21
23
|
if (isI18nWrapperInstance(obj)) return true;
|
|
22
|
-
|
|
24
|
+
const candidate = obj;
|
|
25
|
+
return 'function' == typeof candidate.init && 'function' == typeof candidate.use;
|
|
23
26
|
}
|
|
24
27
|
async function tryImportI18next() {
|
|
25
28
|
try {
|
|
@@ -56,4 +59,4 @@ async function getI18nInstance(userInstance) {
|
|
|
56
59
|
if (i18nextInstance) return i18nextInstance;
|
|
57
60
|
throw new Error('No i18n instance found');
|
|
58
61
|
}
|
|
59
|
-
export { getActualI18nextInstance, getI18nInstance,
|
|
62
|
+
export { getActualI18nextInstance, getI18nInstance, getI18nextInstanceForProvider, isI18nInstance, isI18nWrapperInstance };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isBrowser } from "@modern-js/runtime";
|
|
2
2
|
import { getGlobalBasename } from "@modern-js/runtime/context";
|
|
3
|
-
import { localiseTargetPathname } from "../shared/localisedUrls.mjs";
|
|
3
|
+
import { localiseTargetPathname, shouldSkipLocaleRedirect } from "../shared/localisedUrls.mjs";
|
|
4
4
|
const getPathname = (context)=>{
|
|
5
5
|
if (isBrowser()) return window.location.pathname;
|
|
6
6
|
return context.ssrContext?.request?.pathname || '/';
|
|
@@ -51,13 +51,5 @@ const detectLanguageFromPath = (pathname, languages, localePathRedirect)=>{
|
|
|
51
51
|
detected: false
|
|
52
52
|
};
|
|
53
53
|
};
|
|
54
|
-
const shouldIgnoreRedirect = (pathname, languages, ignoreRedirectRoutes)=>
|
|
55
|
-
if (!ignoreRedirectRoutes) return false;
|
|
56
|
-
const segments = pathname.split('/').filter(Boolean);
|
|
57
|
-
let pathWithoutLang = pathname;
|
|
58
|
-
if (segments.length > 0 && languages.includes(segments[0])) pathWithoutLang = `/${segments.slice(1).join('/')}`;
|
|
59
|
-
const normalizedPath = pathWithoutLang.startsWith('/') ? pathWithoutLang : `/${pathWithoutLang}`;
|
|
60
|
-
if ('function' == typeof ignoreRedirectRoutes) return ignoreRedirectRoutes(normalizedPath);
|
|
61
|
-
return ignoreRedirectRoutes.some((pattern)=>normalizedPath === pattern || normalizedPath.startsWith(`${pattern}/`));
|
|
62
|
-
};
|
|
54
|
+
const shouldIgnoreRedirect = (pathname, languages, ignoreRedirectRoutes)=>shouldSkipLocaleRedirect(pathname, languages, ignoreRedirectRoutes);
|
|
63
55
|
export { buildLocalizedUrl, detectLanguageFromPath, getEntryPath, getLanguageFromPath, getPathname, shouldIgnoreRedirect, splitUrlTarget };
|
|
@@ -3,8 +3,8 @@ import { getLocaleDetectionOptions } from "../shared/utils.mjs";
|
|
|
3
3
|
import { collectApiPrefixes, matchesApiPrefix } from "./apiPrefix.mjs";
|
|
4
4
|
import { convertToHonoLanguageDetectorOptions } from "./detectorOptions.mjs";
|
|
5
5
|
import { buildLocalizedUrl, createLocaleRedirectResponse, getLanguageFromPath, isStaticResourceRequest, shouldIgnoreRedirect } from "./redirectPolicy.mjs";
|
|
6
|
-
import * as
|
|
7
|
-
const { languageDetector: languageDetector } =
|
|
6
|
+
import * as __rspack_external__modern_js_server_core_hono_0af3baa7 from "@modern-js/server-core/hono";
|
|
7
|
+
const { languageDetector: languageDetector } = __rspack_external__modern_js_server_core_hono_0af3baa7;
|
|
8
8
|
const i18nServerPlugin = (options)=>({
|
|
9
9
|
name: '@modern-js/plugin-i18n/server',
|
|
10
10
|
setup: (api)=>{
|
|
@@ -1,31 +1,25 @@
|
|
|
1
|
-
import { localiseTargetPathname } from "../shared/localisedUrls.mjs";
|
|
2
|
-
const
|
|
3
|
-
if (!ignoreRedirectRoutes) return false;
|
|
1
|
+
import { isDefaultLocaleRedirectSkipPath, localiseTargetPathname, matchesPathPrefix, shouldSkipLocaleRedirect, stripLanguagePrefix } from "../shared/localisedUrls.mjs";
|
|
2
|
+
const stripUrlPathPrefix = (pathname, urlPath)=>{
|
|
4
3
|
const basePath = urlPath.replace('/*', '');
|
|
4
|
+
if (!basePath || '/' === basePath) return pathname;
|
|
5
5
|
const remainingPath = pathname.startsWith(basePath) ? pathname.slice(basePath.length) : pathname;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
return remainingPath || '/';
|
|
7
|
+
};
|
|
8
|
+
const shouldIgnoreRedirect = (pathname, urlPath, ignoreRedirectRoutes)=>{
|
|
9
|
+
const remainingPath = stripUrlPathPrefix(pathname, urlPath);
|
|
10
|
+
return shouldSkipLocaleRedirect(remainingPath, [], ignoreRedirectRoutes);
|
|
9
11
|
};
|
|
10
12
|
const isStaticResourceRequest = (pathname, staticRoutePrefixes, languages = [])=>{
|
|
11
|
-
if (
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (standardStaticPrefixes.some((prefix)=>pathname.startsWith(prefix))) return true;
|
|
17
|
-
const pathSegments = pathname.split('/').filter(Boolean);
|
|
18
|
-
if (pathSegments.length > 0 && languages.includes(pathSegments[0])) {
|
|
19
|
-
const pathWithoutLang = '/' + pathSegments.slice(1).join('/');
|
|
20
|
-
if (standardStaticPrefixes.some((prefix)=>pathWithoutLang.startsWith(prefix)) || staticRoutePrefixes.some((prefix)=>pathWithoutLang.startsWith(`${prefix}/`) || pathWithoutLang === prefix)) return true;
|
|
21
|
-
}
|
|
22
|
-
return false;
|
|
13
|
+
if (isDefaultLocaleRedirectSkipPath(pathname, languages)) return true;
|
|
14
|
+
const matchesStaticRoutePrefix = (targetPathname)=>staticRoutePrefixes.some((prefix)=>matchesPathPrefix(targetPathname, prefix));
|
|
15
|
+
if (matchesStaticRoutePrefix(pathname)) return true;
|
|
16
|
+
const pathWithoutLanguage = stripLanguagePrefix(pathname, languages);
|
|
17
|
+
return pathWithoutLanguage !== pathname && matchesStaticRoutePrefix(pathWithoutLanguage);
|
|
23
18
|
};
|
|
24
19
|
const getLanguageFromPath = (req, urlPath, languages)=>{
|
|
25
20
|
const url = new URL(req.url, `http://${req.header().host}`);
|
|
26
21
|
const pathname = url.pathname;
|
|
27
|
-
const
|
|
28
|
-
const remainingPath = pathname.startsWith(basePath) ? pathname.slice(basePath.length) : pathname;
|
|
22
|
+
const remainingPath = stripUrlPathPrefix(pathname, urlPath);
|
|
29
23
|
const segments = remainingPath.split('/').filter(Boolean);
|
|
30
24
|
const firstSegment = segments[0];
|
|
31
25
|
if (languages.includes(firstSegment)) return firstSegment;
|
|
@@ -35,7 +29,7 @@ const buildLocalizedUrl = (req, urlPath, language, languages, localisedUrls)=>{
|
|
|
35
29
|
const url = new URL(req.url);
|
|
36
30
|
const pathname = url.pathname;
|
|
37
31
|
const basePath = urlPath.replace('/*', '');
|
|
38
|
-
const remainingPath = pathname
|
|
32
|
+
const remainingPath = stripUrlPathPrefix(pathname, urlPath);
|
|
39
33
|
const newPathname = localiseTargetPathname(remainingPath, language, languages, localisedUrls);
|
|
40
34
|
const suffix = `${url.search}${url.hash}`;
|
|
41
35
|
const localizedUrl = '/' === basePath ? newPathname + suffix : basePath + newPathname + suffix;
|
|
@@ -1,71 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
function detectLanguageFromRequest(req, languages, detectionOptions) {
|
|
3
|
-
try {
|
|
4
|
-
const mergedDetection = detectionOptions ? mergeDetectionOptions(detectionOptions) : DEFAULT_I18NEXT_DETECTION_OPTIONS;
|
|
5
|
-
const order = (mergedDetection.order || []).filter((item)=>![
|
|
6
|
-
'path',
|
|
7
|
-
'localStorage',
|
|
8
|
-
'navigator',
|
|
9
|
-
'htmlTag',
|
|
10
|
-
'subdomain'
|
|
11
|
-
].includes(item));
|
|
12
|
-
const detectionOrder = order.length > 0 ? order : [
|
|
13
|
-
'querystring',
|
|
14
|
-
'cookie',
|
|
15
|
-
'header'
|
|
16
|
-
];
|
|
17
|
-
const getHeader = (name)=>{
|
|
18
|
-
req.headers, Headers;
|
|
19
|
-
return req.headers.get(name);
|
|
20
|
-
};
|
|
21
|
-
for (const method of detectionOrder){
|
|
22
|
-
let detectedLang = null;
|
|
23
|
-
switch(method){
|
|
24
|
-
case 'querystring':
|
|
25
|
-
{
|
|
26
|
-
const lookupKey = mergedDetection.lookupQuerystring || DEFAULT_I18NEXT_DETECTION_OPTIONS.lookupQuerystring || 'lng';
|
|
27
|
-
const host = getHeader('host') || 'localhost';
|
|
28
|
-
const url = new URL(req.url, `http://${host}`);
|
|
29
|
-
detectedLang = url.searchParams.get(lookupKey);
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
case 'cookie':
|
|
33
|
-
{
|
|
34
|
-
const lookupKey = mergedDetection.lookupCookie || DEFAULT_I18NEXT_DETECTION_OPTIONS.lookupCookie || 'i18next';
|
|
35
|
-
const cookieHeader = getHeader('Cookie');
|
|
36
|
-
if (cookieHeader) {
|
|
37
|
-
const cookies = cookieHeader.split(';').reduce((acc, item)=>{
|
|
38
|
-
const [key, value] = item.trim().split('=');
|
|
39
|
-
if (key && value) acc[key] = value;
|
|
40
|
-
return acc;
|
|
41
|
-
}, {});
|
|
42
|
-
detectedLang = cookies[lookupKey] || null;
|
|
43
|
-
}
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
case 'header':
|
|
47
|
-
{
|
|
48
|
-
const lookupKey = mergedDetection.lookupHeader || DEFAULT_I18NEXT_DETECTION_OPTIONS.lookupHeader || 'accept-language';
|
|
49
|
-
const acceptLanguage = getHeader(lookupKey);
|
|
50
|
-
if (acceptLanguage) {
|
|
51
|
-
const languagesList = acceptLanguage.split(',').map((lang)=>{
|
|
52
|
-
const [code, q] = lang.trim().split(';');
|
|
53
|
-
return {
|
|
54
|
-
code: code.split('-')[0],
|
|
55
|
-
quality: q ? parseFloat(q.split('=')[1]) : 1.0
|
|
56
|
-
};
|
|
57
|
-
}).sort((a, b)=>b.quality - a.quality);
|
|
58
|
-
for (const lang of languagesList)if (0 === languages.length || languages.includes(lang.code)) {
|
|
59
|
-
detectedLang = lang.code;
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
break;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (detectedLang && (0 === languages.length || languages.includes(detectedLang))) return detectedLang;
|
|
67
|
-
}
|
|
68
|
-
} catch (error) {}
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
export { detectLanguageFromRequest };
|
|
1
|
+
import "../runtime/i18n/detection/config.mjs";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { resolveLocalisedUrlsConfig } from "./config.mjs";
|
|
2
2
|
export { normalisePathPattern, normalisePathname } from "./normalise.mjs";
|
|
3
|
-
export { canonicalTargetPathname, localiseTargetPathname } from "./pathname.mjs";
|
|
3
|
+
export { canonicalTargetPathname, localiseTargetPathname, stripLanguagePrefix } from "./pathname.mjs";
|
|
4
4
|
export { buildPathFromPattern, matchPathPattern } from "./patterns.mjs";
|
|
5
|
+
export { DEFAULT_LOCALE_REDIRECT_SKIP_RULES, isDefaultLocaleRedirectSkipPath, matchesPathPrefix, shouldSkipLocaleRedirect } from "./redirect.mjs";
|
|
5
6
|
export { resolveCanonicalLocalisedPath, resolveLocalisedPath } from "./resolve.mjs";
|
|
6
7
|
export { applyLocalisedUrlsToRoutes, validateLocalisedUrls } from "./routes.mjs";
|
|
@@ -21,4 +21,4 @@ const canonicalTargetPathname = (pathname, languages, localisedUrls)=>{
|
|
|
21
21
|
const localisedUrlsConfig = resolveLocalisedUrlsConfig(localisedUrls);
|
|
22
22
|
return localisedUrlsConfig.enabled ? resolveCanonicalLocalisedPath(pathWithoutLanguage, languages, localisedUrlsConfig.map) : pathWithoutLanguage;
|
|
23
23
|
};
|
|
24
|
-
export { canonicalTargetPathname, localiseTargetPathname };
|
|
24
|
+
export { canonicalTargetPathname, localiseTargetPathname, stripLanguagePrefix };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { normalisePathname } from "./normalise.mjs";
|
|
2
|
+
import { stripLanguagePrefix } from "./pathname.mjs";
|
|
3
|
+
const DEFAULT_LOCALE_REDIRECT_SKIP_RULES = [
|
|
4
|
+
{
|
|
5
|
+
type: 'exact',
|
|
6
|
+
path: '/mf-manifest.json'
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
type: 'exact',
|
|
10
|
+
path: '/mf-stats.json'
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
type: 'exact',
|
|
14
|
+
path: '/remoteEntry.js'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: 'prefix',
|
|
18
|
+
path: '/static/'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: 'prefix',
|
|
22
|
+
path: '/upload/'
|
|
23
|
+
}
|
|
24
|
+
];
|
|
25
|
+
const stripTrailingSlash = (pathname)=>pathname.length > 1 ? pathname.replace(/\/+$/, '') : pathname;
|
|
26
|
+
const matchesPathPrefix = (pathname, prefix)=>{
|
|
27
|
+
const normalizedPathname = normalisePathname(pathname);
|
|
28
|
+
const normalizedPrefix = stripTrailingSlash(normalisePathname(prefix));
|
|
29
|
+
return normalizedPathname === normalizedPrefix || normalizedPathname.startsWith(`${normalizedPrefix}/`);
|
|
30
|
+
};
|
|
31
|
+
const matchesSkipRule = (pathname, rule)=>{
|
|
32
|
+
if ('exact' === rule.type) return normalisePathname(pathname) === normalisePathname(rule.path);
|
|
33
|
+
return matchesPathPrefix(pathname, rule.path);
|
|
34
|
+
};
|
|
35
|
+
const isDefaultLocaleRedirectSkipPath = (pathname, languages = [])=>{
|
|
36
|
+
const normalizedPathname = normalisePathname(pathname);
|
|
37
|
+
const pathWithoutLanguage = stripLanguagePrefix(normalizedPathname, languages);
|
|
38
|
+
return DEFAULT_LOCALE_REDIRECT_SKIP_RULES.some((rule)=>matchesSkipRule(pathWithoutLanguage, rule));
|
|
39
|
+
};
|
|
40
|
+
const shouldSkipLocaleRedirect = (pathname, languages = [], ignoreRedirectRoutes)=>{
|
|
41
|
+
const normalizedPathname = normalisePathname(pathname);
|
|
42
|
+
const pathWithoutLanguage = stripLanguagePrefix(normalizedPathname, languages);
|
|
43
|
+
if (isDefaultLocaleRedirectSkipPath(pathWithoutLanguage)) return true;
|
|
44
|
+
if (!ignoreRedirectRoutes) return false;
|
|
45
|
+
if ('function' == typeof ignoreRedirectRoutes) return ignoreRedirectRoutes(pathWithoutLanguage);
|
|
46
|
+
return ignoreRedirectRoutes.some((pattern)=>matchesPathPrefix(pathWithoutLanguage, pattern));
|
|
47
|
+
};
|
|
48
|
+
export { DEFAULT_LOCALE_REDIRECT_SKIP_RULES, isDefaultLocaleRedirectSkipPath, matchesPathPrefix, shouldSkipLocaleRedirect };
|
|
@@ -1,50 +1,47 @@
|
|
|
1
1
|
import { normalisePathname } from "./normalise.mjs";
|
|
2
2
|
import { buildPathFromPattern, matchPathPattern, sortPatternsBySpecificity } from "./patterns.mjs";
|
|
3
|
-
const
|
|
4
|
-
const normalizedPathname = normalisePathname(pathname);
|
|
5
|
-
const canonicalCandidates = sortPatternsBySpecificity(Object.entries(localisedUrls).map(([canonicalPattern, localisedUrlEntry])=>({
|
|
3
|
+
const getCanonicalCandidates = (localisedUrls)=>sortPatternsBySpecificity(Object.entries(localisedUrls).map(([canonicalPattern, localisedUrlEntry])=>({
|
|
6
4
|
pattern: canonicalPattern,
|
|
7
5
|
canonicalPattern,
|
|
8
6
|
localisedUrlEntry
|
|
9
7
|
})));
|
|
10
|
-
|
|
11
|
-
const targetPattern = localisedUrlEntry[targetLanguage];
|
|
12
|
-
if (!targetPattern) continue;
|
|
13
|
-
const params = matchPathPattern(normalizedPathname, canonicalPattern);
|
|
14
|
-
if (params) return buildPathFromPattern(targetPattern, params);
|
|
15
|
-
}
|
|
16
|
-
const localisedCandidates = sortPatternsBySpecificity(Object.values(localisedUrls).flatMap((localisedUrlEntry)=>{
|
|
17
|
-
const targetPattern = localisedUrlEntry[targetLanguage];
|
|
18
|
-
if (!targetPattern) return [];
|
|
19
|
-
return languages.map((language)=>localisedUrlEntry[language]).filter((sourcePattern)=>Boolean(sourcePattern)).map((sourcePattern)=>({
|
|
20
|
-
pattern: sourcePattern,
|
|
21
|
-
sourcePattern,
|
|
22
|
-
targetPattern
|
|
23
|
-
}));
|
|
24
|
-
}));
|
|
25
|
-
for (const { sourcePattern, targetPattern } of localisedCandidates){
|
|
26
|
-
const params = matchPathPattern(normalizedPathname, sourcePattern);
|
|
27
|
-
if (params) return buildPathFromPattern(targetPattern, params);
|
|
28
|
-
}
|
|
29
|
-
return normalizedPathname;
|
|
30
|
-
};
|
|
31
|
-
const resolveCanonicalLocalisedPath = (pathname, languages, localisedUrls)=>{
|
|
8
|
+
const resolveLocalisedUrlPath = (pathname, languages, localisedUrls, options)=>{
|
|
32
9
|
const normalizedPathname = normalisePathname(pathname);
|
|
33
|
-
const canonicalCandidates =
|
|
34
|
-
pattern: canonicalPattern,
|
|
35
|
-
canonicalPattern,
|
|
36
|
-
localisedUrlEntry
|
|
37
|
-
})));
|
|
10
|
+
const canonicalCandidates = getCanonicalCandidates(localisedUrls);
|
|
38
11
|
for (const { canonicalPattern, localisedUrlEntry } of canonicalCandidates){
|
|
12
|
+
const targetPattern = 'localised' === options.mode ? localisedUrlEntry[options.targetLanguage] : canonicalPattern;
|
|
13
|
+
if (!targetPattern) continue;
|
|
39
14
|
const canonicalParams = matchPathPattern(normalizedPathname, canonicalPattern);
|
|
40
|
-
if (canonicalParams) return buildPathFromPattern(
|
|
41
|
-
for (const language of languages){
|
|
15
|
+
if (canonicalParams) return buildPathFromPattern(targetPattern, canonicalParams);
|
|
16
|
+
if ('canonical' === options.mode) for (const language of languages){
|
|
42
17
|
const sourcePattern = localisedUrlEntry[language];
|
|
43
18
|
if (!sourcePattern) continue;
|
|
44
19
|
const params = matchPathPattern(normalizedPathname, sourcePattern);
|
|
45
20
|
if (params) return buildPathFromPattern(canonicalPattern, params);
|
|
46
21
|
}
|
|
47
22
|
}
|
|
23
|
+
if ('localised' === options.mode) {
|
|
24
|
+
const localisedCandidates = sortPatternsBySpecificity(Object.values(localisedUrls).flatMap((localisedUrlEntry)=>{
|
|
25
|
+
const targetPattern = localisedUrlEntry[options.targetLanguage];
|
|
26
|
+
if (!targetPattern) return [];
|
|
27
|
+
return languages.map((language)=>localisedUrlEntry[language]).filter((sourcePattern)=>Boolean(sourcePattern)).map((sourcePattern)=>({
|
|
28
|
+
pattern: sourcePattern,
|
|
29
|
+
sourcePattern,
|
|
30
|
+
targetPattern
|
|
31
|
+
}));
|
|
32
|
+
}));
|
|
33
|
+
for (const { sourcePattern, targetPattern } of localisedCandidates){
|
|
34
|
+
const params = matchPathPattern(normalizedPathname, sourcePattern);
|
|
35
|
+
if (params) return buildPathFromPattern(targetPattern, params);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
48
38
|
return normalizedPathname;
|
|
49
39
|
};
|
|
40
|
+
const resolveLocalisedPath = (pathname, targetLanguage, languages, localisedUrls)=>resolveLocalisedUrlPath(pathname, languages, localisedUrls, {
|
|
41
|
+
mode: 'localised',
|
|
42
|
+
targetLanguage
|
|
43
|
+
});
|
|
44
|
+
const resolveCanonicalLocalisedPath = (pathname, languages, localisedUrls)=>resolveLocalisedUrlPath(pathname, languages, localisedUrls, {
|
|
45
|
+
mode: 'canonical'
|
|
46
|
+
});
|
|
50
47
|
export { resolveCanonicalLocalisedPath, resolveLocalisedPath };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { applyLocalisedUrlsToRoutes, buildPathFromPattern, canonicalTargetPathname, localiseTargetPathname, matchPathPattern, normalisePathPattern, normalisePathname, resolveCanonicalLocalisedPath, resolveLocalisedPath, resolveLocalisedUrlsConfig, validateLocalisedUrls } from "./localisedUrls/index.mjs";
|
|
1
|
+
export { DEFAULT_LOCALE_REDIRECT_SKIP_RULES, applyLocalisedUrlsToRoutes, buildPathFromPattern, canonicalTargetPathname, isDefaultLocaleRedirectSkipPath, localiseTargetPathname, matchPathPattern, matchesPathPrefix, normalisePathPattern, normalisePathname, resolveCanonicalLocalisedPath, resolveLocalisedPath, resolveLocalisedUrlsConfig, shouldSkipLocaleRedirect, stripLanguagePrefix, validateLocalisedUrls } from "./localisedUrls/index.mjs";
|
|
@@ -32,4 +32,4 @@ function getBackendOptions(entryName, backend) {
|
|
|
32
32
|
if ('backendOptionsByEntry' in fullConfig) return removeEntryConfigKey(fullConfig, 'backendOptionsByEntry');
|
|
33
33
|
return backend;
|
|
34
34
|
}
|
|
35
|
-
export { getBackendOptions,
|
|
35
|
+
export { getBackendOptions, getLocaleDetectionOptions };
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
+
import node_fs from "node:fs";
|
|
3
|
+
import node_path from "node:path";
|
|
2
4
|
import { getPublicDirRoutePrefixes, normalizePublicDir, normalizePublicDirPath } from "@modern-js/server-core";
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import path from "path";
|
|
5
5
|
const LOCALES_RESOURCE_PATTERN = '{{lng}}/{{ns}}.json';
|
|
6
6
|
function hasJsonFiles(dirPath) {
|
|
7
7
|
try {
|
|
8
|
-
if (!
|
|
9
|
-
const entries =
|
|
8
|
+
if (!node_fs.existsSync(dirPath) || !node_fs.statSync(dirPath).isDirectory()) return false;
|
|
9
|
+
const entries = node_fs.readdirSync(dirPath);
|
|
10
10
|
for (const entry of entries){
|
|
11
|
-
const entryPath =
|
|
12
|
-
const stat =
|
|
11
|
+
const entryPath = node_path.join(dirPath, entry);
|
|
12
|
+
const stat = node_fs.statSync(entryPath);
|
|
13
13
|
if (stat.isFile() && entry.endsWith('.json')) return true;
|
|
14
14
|
if (stat.isDirectory() && hasJsonFiles(entryPath)) return true;
|
|
15
15
|
}
|
|
@@ -19,7 +19,7 @@ function hasJsonFiles(dirPath) {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
function toPosixPath(filePath) {
|
|
22
|
-
return filePath.split(
|
|
22
|
+
return filePath.split(node_path.sep).join(node_path.posix.sep);
|
|
23
23
|
}
|
|
24
24
|
function getPublicDirOutputPath(publicDir) {
|
|
25
25
|
return normalizePublicDirPath(publicDir);
|
|
@@ -46,20 +46,20 @@ function detectLocalesDirectory(appDirectory, normalizedConfig) {
|
|
|
46
46
|
const publicDirPrefixes = getPublicDirRoutePrefixes(normalizedConfig?.server?.publicDir);
|
|
47
47
|
for(let index = 0; index < publicDirs.length; index++){
|
|
48
48
|
const publicDir = publicDirs[index];
|
|
49
|
-
if (
|
|
50
|
-
const publicDirPath =
|
|
49
|
+
if (node_path.isAbsolute(publicDir)) continue;
|
|
50
|
+
const publicDirPath = node_path.join(appDirectory, publicDir);
|
|
51
51
|
const publicDirPrefix = publicDirPrefixes[index] || `/${normalizePublicDirPath(publicDir)}`;
|
|
52
52
|
const publicDirOutputPath = getPublicDirOutputPath(publicDir);
|
|
53
|
-
if ('locales' ===
|
|
54
|
-
const localesPath =
|
|
53
|
+
if ('locales' === node_path.basename(normalizePublicDirPath(publicDir)) && hasJsonFiles(publicDirPath)) return buildDetectedLocalesDirectory(publicDirPrefix, `./${publicDirOutputPath}`);
|
|
54
|
+
const localesPath = node_path.join(publicDirPath, 'locales');
|
|
55
55
|
if (hasJsonFiles(localesPath)) return buildDetectedLocalesDirectory(`${publicDirPrefix}/locales`, `./${publicDirOutputPath}/locales`);
|
|
56
56
|
}
|
|
57
|
-
const configPublicPath =
|
|
57
|
+
const configPublicPath = node_path.join(appDirectory, 'config', 'public', 'locales');
|
|
58
58
|
if (hasJsonFiles(configPublicPath)) return buildDetectedLocalesDirectory('/locales', './public/locales', [
|
|
59
59
|
'./config/public/locales',
|
|
60
60
|
'./public/locales'
|
|
61
61
|
]);
|
|
62
|
-
const rootLocalesPath =
|
|
62
|
+
const rootLocalesPath = node_path.join(appDirectory, 'locales');
|
|
63
63
|
if (hasJsonFiles(rootLocalesPath)) return buildDetectedLocalesDirectory('/locales', './locales');
|
|
64
64
|
}
|
|
65
65
|
function applyDetectedBackendPaths(backendOptions, detectedLocales) {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import node_fs from "node:fs";
|
|
3
|
+
import node_path from "node:path";
|
|
4
4
|
const CONVENTIONAL_LOCALES_DIRS = [
|
|
5
5
|
'./locales',
|
|
6
6
|
'./config/public/locales'
|
|
7
7
|
];
|
|
8
8
|
const isDirectory = (dirPath)=>{
|
|
9
9
|
try {
|
|
10
|
-
return
|
|
10
|
+
return node_fs.statSync(dirPath).isDirectory();
|
|
11
11
|
} catch {
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
const resolveDefaultLocalesDir = (cwd = process.cwd())=>{
|
|
16
|
-
for (const dir of CONVENTIONAL_LOCALES_DIRS)if (isDirectory(
|
|
16
|
+
for (const dir of CONVENTIONAL_LOCALES_DIRS)if (isDirectory(node_path.resolve(cwd, dir))) return dir;
|
|
17
17
|
return CONVENTIONAL_LOCALES_DIRS[0];
|
|
18
18
|
};
|
|
19
19
|
const DEFAULT_I18NEXT_BACKEND_OPTIONS = {
|
|
@@ -39,7 +39,7 @@ function getResourceBasePath(resourcePath) {
|
|
|
39
39
|
}
|
|
40
40
|
function pathExists(resourcePath) {
|
|
41
41
|
try {
|
|
42
|
-
return
|
|
42
|
+
return node_fs.existsSync(getResourceBasePath(resourcePath));
|
|
43
43
|
} catch {
|
|
44
44
|
return false;
|
|
45
45
|
}
|