@modern-js/plugin-i18n 3.3.0 → 3.5.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.
@@ -1,14 +1,5 @@
1
1
  "use strict";
2
2
  var __webpack_require__ = {};
3
- (()=>{
4
- __webpack_require__.n = (module)=>{
5
- var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
- __webpack_require__.d(getter, {
7
- a: getter
8
- });
9
- return getter;
10
- };
11
- })();
12
3
  (()=>{
13
4
  __webpack_require__.d = (exports1, getters, values)=>{
14
5
  var define = (defs, kind)=>{
@@ -40,43 +31,10 @@ __webpack_require__.d(__webpack_exports__, {
40
31
  default: ()=>cli,
41
32
  i18nPlugin: ()=>i18nPlugin
42
33
  });
43
- const external_fs_namespaceObject = require("fs");
44
- var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
45
- const external_path_namespaceObject = require("path");
46
- var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
47
34
  const server_core_namespaceObject = require("@modern-js/server-core");
48
35
  const utils_js_namespaceObject = require("../shared/utils.js");
36
+ const external_locales_js_namespaceObject = require("./locales.js");
49
37
  require("../runtime/types.js");
50
- function hasJsonFiles(dirPath) {
51
- try {
52
- if (!external_fs_default().existsSync(dirPath) || !external_fs_default().statSync(dirPath).isDirectory()) return false;
53
- const entries = external_fs_default().readdirSync(dirPath);
54
- for (const entry of entries){
55
- const entryPath = external_path_default().join(dirPath, entry);
56
- const stat = external_fs_default().statSync(entryPath);
57
- if (stat.isFile() && entry.endsWith('.json')) return true;
58
- if (stat.isDirectory()) {
59
- if (hasJsonFiles(entryPath)) return true;
60
- }
61
- }
62
- return false;
63
- } catch {
64
- return false;
65
- }
66
- }
67
- function detectLocalesDirectory(appDirectory, normalizedConfig) {
68
- const rootLocalesPath = external_path_default().join(appDirectory, 'locales');
69
- if (hasJsonFiles(rootLocalesPath)) return true;
70
- const configPublicPath = external_path_default().join(appDirectory, 'config', 'public', 'locales');
71
- if (hasJsonFiles(configPublicPath)) return true;
72
- const publicDir = normalizedConfig?.server?.publicDir;
73
- if (publicDir) {
74
- const publicDirPath = Array.isArray(publicDir) ? publicDir[0] : publicDir;
75
- const localesPath = external_path_default().isAbsolute(publicDirPath) ? external_path_default().join(publicDirPath, 'locales') : external_path_default().join(appDirectory, publicDirPath, 'locales');
76
- if (hasJsonFiles(localesPath)) return true;
77
- }
78
- return false;
79
- }
80
38
  const i18nPlugin = (options = {})=>({
81
39
  name: '@modern-js/plugin-i18n',
82
40
  setup: (api)=>{
@@ -86,26 +44,16 @@ const i18nPlugin = (options = {})=>({
86
44
  let backendOptions;
87
45
  const { appDirectory } = api.getAppContext();
88
46
  const normalizedConfig = api.getNormalizedConfig();
47
+ const detectedLocales = (0, external_locales_js_namespaceObject.detectLocalesDirectory)(appDirectory, normalizedConfig);
89
48
  if (backend) {
90
49
  const entryBackendOptions = (0, utils_js_namespaceObject.getBackendOptions)(entrypoint.entryName, backend);
91
- if (entryBackendOptions?.enabled === false) backendOptions = entryBackendOptions;
92
- else if (entryBackendOptions?.loadPath || entryBackendOptions?.addPath) backendOptions = {
50
+ backendOptions = entryBackendOptions?.enabled === false ? entryBackendOptions : detectedLocales ? (0, external_locales_js_namespaceObject.applyDetectedBackendPaths)(entryBackendOptions, detectedLocales) : entryBackendOptions?.loadPath || entryBackendOptions?.addPath ? {
93
51
  ...entryBackendOptions,
94
52
  enabled: true
95
- };
96
- else if (entryBackendOptions?.enabled !== true) {
97
- const hasLocales = detectLocalesDirectory(appDirectory, normalizedConfig);
98
- backendOptions = hasLocales ? {
99
- ...entryBackendOptions,
100
- enabled: true
101
- } : entryBackendOptions;
102
- } else backendOptions = entryBackendOptions;
103
- } else {
104
- const hasLocales = detectLocalesDirectory(appDirectory, normalizedConfig);
105
- if (hasLocales) backendOptions = (0, utils_js_namespaceObject.getBackendOptions)(entrypoint.entryName, {
106
- enabled: true
107
- });
108
- }
53
+ } : entryBackendOptions;
54
+ } else if (detectedLocales) backendOptions = (0, external_locales_js_namespaceObject.applyDetectedBackendPaths)((0, utils_js_namespaceObject.getBackendOptions)(entrypoint.entryName, {
55
+ enabled: true
56
+ }), detectedLocales);
109
57
  const { metaName } = api.getAppContext();
110
58
  let extendedConfig = restOptions;
111
59
  if (transformRuntimeConfig) extendedConfig = transformRuntimeConfig(restOptions, entrypoint);
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
12
+ (()=>{
13
+ __webpack_require__.d = (exports1, getters, values)=>{
14
+ var define = (defs, kind)=>{
15
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
16
+ enumerable: true,
17
+ [kind]: defs[key]
18
+ });
19
+ };
20
+ define(getters, "get");
21
+ define(values, "value");
22
+ };
23
+ })();
24
+ (()=>{
25
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
26
+ })();
27
+ (()=>{
28
+ __webpack_require__.r = (exports1)=>{
29
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
30
+ value: 'Module'
31
+ });
32
+ Object.defineProperty(exports1, '__esModule', {
33
+ value: true
34
+ });
35
+ };
36
+ })();
37
+ var __webpack_exports__ = {};
38
+ __webpack_require__.r(__webpack_exports__);
39
+ __webpack_require__.d(__webpack_exports__, {
40
+ applyDetectedBackendPaths: ()=>applyDetectedBackendPaths,
41
+ detectLocalesDirectory: ()=>detectLocalesDirectory
42
+ });
43
+ const external_fs_namespaceObject = require("fs");
44
+ var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
45
+ const external_path_namespaceObject = require("path");
46
+ var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
47
+ const server_core_namespaceObject = require("@modern-js/server-core");
48
+ const LOCALES_RESOURCE_PATTERN = '{{lng}}/{{ns}}.json';
49
+ function hasJsonFiles(dirPath) {
50
+ try {
51
+ if (!external_fs_default().existsSync(dirPath) || !external_fs_default().statSync(dirPath).isDirectory()) return false;
52
+ const entries = external_fs_default().readdirSync(dirPath);
53
+ for (const entry of entries){
54
+ const entryPath = external_path_default().join(dirPath, entry);
55
+ const stat = external_fs_default().statSync(entryPath);
56
+ if (stat.isFile() && entry.endsWith('.json')) return true;
57
+ if (stat.isDirectory() && hasJsonFiles(entryPath)) return true;
58
+ }
59
+ return false;
60
+ } catch {
61
+ return false;
62
+ }
63
+ }
64
+ function toPosixPath(filePath) {
65
+ return filePath.split(external_path_default().sep).join(external_path_default().posix.sep);
66
+ }
67
+ function getPublicDirOutputPath(publicDir) {
68
+ return (0, server_core_namespaceObject.normalizePublicDirPath)(publicDir);
69
+ }
70
+ function buildDetectedLocalesDirectory(clientBasePath, serverBasePath, serverBasePathCandidates = [
71
+ serverBasePath
72
+ ]) {
73
+ const normalizedClientBasePath = clientBasePath.startsWith('/') ? clientBasePath : `/${clientBasePath}`;
74
+ const normalizedServerBasePath = toPosixPath(serverBasePath).replace(/\/$/, '');
75
+ const normalizedServerBasePathCandidates = Array.from(new Set(serverBasePathCandidates.map((candidate)=>toPosixPath(candidate).replace(/\/$/, ''))));
76
+ const serverLoadPaths = normalizedServerBasePathCandidates.map((candidate)=>`${candidate}/${LOCALES_RESOURCE_PATTERN}`);
77
+ const serverAddPaths = normalizedServerBasePathCandidates.map((candidate)=>`${candidate}/${LOCALES_RESOURCE_PATTERN}`);
78
+ return {
79
+ loadPath: `${normalizedClientBasePath}/${LOCALES_RESOURCE_PATTERN}`,
80
+ addPath: `${normalizedClientBasePath}/${LOCALES_RESOURCE_PATTERN}`,
81
+ serverLoadPath: `${normalizedServerBasePath}/${LOCALES_RESOURCE_PATTERN}`,
82
+ serverAddPath: `${normalizedServerBasePath}/${LOCALES_RESOURCE_PATTERN}`,
83
+ serverLoadPaths,
84
+ serverAddPaths
85
+ };
86
+ }
87
+ function detectLocalesDirectory(appDirectory, normalizedConfig) {
88
+ const publicDirs = (0, server_core_namespaceObject.normalizePublicDir)(normalizedConfig?.server?.publicDir);
89
+ const publicDirPrefixes = (0, server_core_namespaceObject.getPublicDirRoutePrefixes)(normalizedConfig?.server?.publicDir);
90
+ for(let index = 0; index < publicDirs.length; index++){
91
+ const publicDir = publicDirs[index];
92
+ if (external_path_default().isAbsolute(publicDir)) continue;
93
+ const publicDirPath = external_path_default().join(appDirectory, publicDir);
94
+ const publicDirPrefix = publicDirPrefixes[index] || `/${(0, server_core_namespaceObject.normalizePublicDirPath)(publicDir)}`;
95
+ const publicDirOutputPath = getPublicDirOutputPath(publicDir);
96
+ if ('locales' === external_path_default().basename((0, server_core_namespaceObject.normalizePublicDirPath)(publicDir)) && hasJsonFiles(publicDirPath)) return buildDetectedLocalesDirectory(publicDirPrefix, `./${publicDirOutputPath}`);
97
+ const localesPath = external_path_default().join(publicDirPath, 'locales');
98
+ if (hasJsonFiles(localesPath)) return buildDetectedLocalesDirectory(`${publicDirPrefix}/locales`, `./${publicDirOutputPath}/locales`);
99
+ }
100
+ const configPublicPath = external_path_default().join(appDirectory, 'config', 'public', 'locales');
101
+ if (hasJsonFiles(configPublicPath)) return buildDetectedLocalesDirectory('/locales', './public/locales', [
102
+ './config/public/locales',
103
+ './public/locales'
104
+ ]);
105
+ const rootLocalesPath = external_path_default().join(appDirectory, 'locales');
106
+ if (hasJsonFiles(rootLocalesPath)) return buildDetectedLocalesDirectory('/locales', './locales');
107
+ }
108
+ function applyDetectedBackendPaths(backendOptions, detectedLocales) {
109
+ if (!detectedLocales) return backendOptions;
110
+ const backendWithDetectedPaths = {
111
+ ...backendOptions,
112
+ enabled: true,
113
+ loadPath: backendOptions.loadPath ?? detectedLocales.loadPath,
114
+ addPath: backendOptions.addPath ?? detectedLocales.addPath,
115
+ serverLoadPath: backendOptions.serverLoadPath ?? detectedLocales.serverLoadPath,
116
+ serverLoadPaths: backendOptions.serverLoadPath || backendOptions.serverLoadPaths ? backendOptions.serverLoadPaths : detectedLocales.serverLoadPaths,
117
+ serverAddPath: backendOptions.serverAddPath ?? detectedLocales.serverAddPath,
118
+ serverAddPaths: backendOptions.serverAddPath || backendOptions.serverAddPaths ? backendOptions.serverAddPaths : detectedLocales.serverAddPaths,
119
+ _detectedLoadPath: detectedLocales.loadPath,
120
+ _detectedAddPath: detectedLocales.addPath
121
+ };
122
+ return backendWithDetectedPaths;
123
+ }
124
+ exports.applyDetectedBackendPaths = __webpack_exports__.applyDetectedBackendPaths;
125
+ exports.detectLocalesDirectory = __webpack_exports__.detectLocalesDirectory;
126
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
127
+ "applyDetectedBackendPaths",
128
+ "detectLocalesDirectory"
129
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
130
+ Object.defineProperty(exports, '__esModule', {
131
+ value: true
132
+ });
@@ -32,8 +32,6 @@ const DEFAULT_I18NEXT_BACKEND_OPTIONS = {
32
32
  addPath: '/locales/{{lng}}/{{ns}}.json'
33
33
  };
34
34
  function convertPath(path) {
35
- if (!path) return path;
36
- if (path.startsWith('/')) return `${window.__assetPrefix__ || ''}${path}`;
37
35
  return path;
38
36
  }
39
37
  function convertBackendOptions(options) {
@@ -41,6 +39,12 @@ function convertBackendOptions(options) {
41
39
  const converted = {
42
40
  ...options
43
41
  };
42
+ delete converted.serverLoadPath;
43
+ delete converted.serverAddPath;
44
+ delete converted.serverLoadPaths;
45
+ delete converted.serverAddPaths;
46
+ delete converted._detectedLoadPath;
47
+ delete converted._detectedAddPath;
44
48
  if (converted.loadPath) converted.loadPath = convertPath(converted.loadPath);
45
49
  if (converted.addPath) converted.addPath = convertPath(converted.addPath);
46
50
  return converted;
@@ -1,5 +1,14 @@
1
1
  "use strict";
2
2
  var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
3
12
  (()=>{
4
13
  __webpack_require__.d = (exports1, getters, values)=>{
5
14
  var define = (defs, kind)=>{
@@ -27,6 +36,12 @@ var __webpack_require__ = {};
27
36
  })();
28
37
  var __webpack_exports__ = {};
29
38
  __webpack_require__.r(__webpack_exports__);
39
+ __webpack_require__.d(__webpack_exports__, {
40
+ DEFAULT_I18NEXT_BACKEND_OPTIONS: ()=>DEFAULT_I18NEXT_BACKEND_OPTIONS,
41
+ convertBackendOptions: ()=>convertBackendOptions
42
+ });
43
+ const external_fs_namespaceObject = require("fs");
44
+ var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
30
45
  const DEFAULT_I18NEXT_BACKEND_OPTIONS = {
31
46
  loadPath: './locales/{{lng}}/{{ns}}.json',
32
47
  addPath: './locales/{{lng}}/{{ns}}.json'
@@ -36,20 +51,45 @@ function convertPath(path) {
36
51
  if (path.startsWith('/')) return `.${path}`;
37
52
  return path;
38
53
  }
54
+ function shouldUseServerPath(currentPath, detectedPath) {
55
+ return !detectedPath || currentPath === detectedPath;
56
+ }
57
+ function getResourceBasePath(resourcePath) {
58
+ const markerIndex = resourcePath.indexOf('{{lng}}');
59
+ if (markerIndex < 0) return resourcePath;
60
+ return resourcePath.slice(0, markerIndex).replace(/[\\/]+$/, '');
61
+ }
62
+ function pathExists(resourcePath) {
63
+ try {
64
+ return external_fs_default().existsSync(getResourceBasePath(resourcePath));
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+ function getServerPath(pathCandidates, fallbackPath) {
70
+ const candidates = Array.from(new Set([
71
+ ...pathCandidates || [],
72
+ fallbackPath
73
+ ].filter(Boolean)));
74
+ return candidates.find(pathExists) || candidates[0];
75
+ }
39
76
  function convertBackendOptions(options) {
40
77
  if (!options) return options;
41
78
  const converted = {
42
79
  ...options
43
80
  };
44
- if (converted.loadPath) converted.loadPath = convertPath(converted.loadPath);
45
- if (converted.addPath) converted.addPath = convertPath(converted.addPath);
81
+ if ((converted.serverLoadPath || converted.serverLoadPaths) && shouldUseServerPath(converted.loadPath, converted._detectedLoadPath)) converted.loadPath = getServerPath(converted.serverLoadPaths, converted.serverLoadPath);
82
+ else if (converted.loadPath) converted.loadPath = convertPath(converted.loadPath);
83
+ if ((converted.serverAddPath || converted.serverAddPaths) && shouldUseServerPath(converted.addPath, converted._detectedAddPath)) converted.addPath = getServerPath(converted.serverAddPaths, converted.serverAddPath);
84
+ else if (converted.addPath) converted.addPath = convertPath(converted.addPath);
85
+ delete converted.serverLoadPath;
86
+ delete converted.serverAddPath;
87
+ delete converted.serverLoadPaths;
88
+ delete converted.serverAddPaths;
89
+ delete converted._detectedLoadPath;
90
+ delete converted._detectedAddPath;
46
91
  return converted;
47
92
  }
48
- __webpack_require__.d(__webpack_exports__, {
49
- convertBackendOptions: ()=>convertBackendOptions
50
- }, {
51
- DEFAULT_I18NEXT_BACKEND_OPTIONS: DEFAULT_I18NEXT_BACKEND_OPTIONS
52
- });
53
93
  exports.DEFAULT_I18NEXT_BACKEND_OPTIONS = __webpack_exports__.DEFAULT_I18NEXT_BACKEND_OPTIONS;
54
94
  exports.convertBackendOptions = __webpack_exports__.convertBackendOptions;
55
95
  for(var __rspack_i in __webpack_exports__)if (-1 === [
@@ -1,38 +1,7 @@
1
- import fs from "fs";
2
- import path from "path";
3
1
  import { getPublicDirRoutePrefixes } from "@modern-js/server-core";
4
2
  import { getBackendOptions, getLocaleDetectionOptions } from "../shared/utils.mjs";
3
+ import { applyDetectedBackendPaths, detectLocalesDirectory } from "./locales.mjs";
5
4
  import "../runtime/types.mjs";
6
- function hasJsonFiles(dirPath) {
7
- try {
8
- if (!fs.existsSync(dirPath) || !fs.statSync(dirPath).isDirectory()) return false;
9
- const entries = fs.readdirSync(dirPath);
10
- for (const entry of entries){
11
- const entryPath = path.join(dirPath, entry);
12
- const stat = fs.statSync(entryPath);
13
- if (stat.isFile() && entry.endsWith('.json')) return true;
14
- if (stat.isDirectory()) {
15
- if (hasJsonFiles(entryPath)) return true;
16
- }
17
- }
18
- return false;
19
- } catch {
20
- return false;
21
- }
22
- }
23
- function detectLocalesDirectory(appDirectory, normalizedConfig) {
24
- const rootLocalesPath = path.join(appDirectory, 'locales');
25
- if (hasJsonFiles(rootLocalesPath)) return true;
26
- const configPublicPath = path.join(appDirectory, 'config', 'public', 'locales');
27
- if (hasJsonFiles(configPublicPath)) return true;
28
- const publicDir = normalizedConfig?.server?.publicDir;
29
- if (publicDir) {
30
- const publicDirPath = Array.isArray(publicDir) ? publicDir[0] : publicDir;
31
- const localesPath = path.isAbsolute(publicDirPath) ? path.join(publicDirPath, 'locales') : path.join(appDirectory, publicDirPath, 'locales');
32
- if (hasJsonFiles(localesPath)) return true;
33
- }
34
- return false;
35
- }
36
5
  const i18nPlugin = (options = {})=>({
37
6
  name: '@modern-js/plugin-i18n',
38
7
  setup: (api)=>{
@@ -42,26 +11,16 @@ const i18nPlugin = (options = {})=>({
42
11
  let backendOptions;
43
12
  const { appDirectory } = api.getAppContext();
44
13
  const normalizedConfig = api.getNormalizedConfig();
14
+ const detectedLocales = detectLocalesDirectory(appDirectory, normalizedConfig);
45
15
  if (backend) {
46
16
  const entryBackendOptions = getBackendOptions(entrypoint.entryName, backend);
47
- if (entryBackendOptions?.enabled === false) backendOptions = entryBackendOptions;
48
- else if (entryBackendOptions?.loadPath || entryBackendOptions?.addPath) backendOptions = {
17
+ backendOptions = entryBackendOptions?.enabled === false ? entryBackendOptions : detectedLocales ? applyDetectedBackendPaths(entryBackendOptions, detectedLocales) : entryBackendOptions?.loadPath || entryBackendOptions?.addPath ? {
49
18
  ...entryBackendOptions,
50
19
  enabled: true
51
- };
52
- else if (entryBackendOptions?.enabled !== true) {
53
- const hasLocales = detectLocalesDirectory(appDirectory, normalizedConfig);
54
- backendOptions = hasLocales ? {
55
- ...entryBackendOptions,
56
- enabled: true
57
- } : entryBackendOptions;
58
- } else backendOptions = entryBackendOptions;
59
- } else {
60
- const hasLocales = detectLocalesDirectory(appDirectory, normalizedConfig);
61
- if (hasLocales) backendOptions = getBackendOptions(entrypoint.entryName, {
62
- enabled: true
63
- });
64
- }
20
+ } : entryBackendOptions;
21
+ } else if (detectedLocales) backendOptions = applyDetectedBackendPaths(getBackendOptions(entrypoint.entryName, {
22
+ enabled: true
23
+ }), detectedLocales);
65
24
  const { metaName } = api.getAppContext();
66
25
  let extendedConfig = restOptions;
67
26
  if (transformRuntimeConfig) extendedConfig = transformRuntimeConfig(restOptions, entrypoint);
@@ -0,0 +1,80 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { getPublicDirRoutePrefixes, normalizePublicDir, normalizePublicDirPath } from "@modern-js/server-core";
4
+ const LOCALES_RESOURCE_PATTERN = '{{lng}}/{{ns}}.json';
5
+ function hasJsonFiles(dirPath) {
6
+ try {
7
+ if (!fs.existsSync(dirPath) || !fs.statSync(dirPath).isDirectory()) return false;
8
+ const entries = fs.readdirSync(dirPath);
9
+ for (const entry of entries){
10
+ const entryPath = path.join(dirPath, entry);
11
+ const stat = fs.statSync(entryPath);
12
+ if (stat.isFile() && entry.endsWith('.json')) return true;
13
+ if (stat.isDirectory() && hasJsonFiles(entryPath)) return true;
14
+ }
15
+ return false;
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+ function toPosixPath(filePath) {
21
+ return filePath.split(path.sep).join(path.posix.sep);
22
+ }
23
+ function getPublicDirOutputPath(publicDir) {
24
+ return normalizePublicDirPath(publicDir);
25
+ }
26
+ function buildDetectedLocalesDirectory(clientBasePath, serverBasePath, serverBasePathCandidates = [
27
+ serverBasePath
28
+ ]) {
29
+ const normalizedClientBasePath = clientBasePath.startsWith('/') ? clientBasePath : `/${clientBasePath}`;
30
+ const normalizedServerBasePath = toPosixPath(serverBasePath).replace(/\/$/, '');
31
+ const normalizedServerBasePathCandidates = Array.from(new Set(serverBasePathCandidates.map((candidate)=>toPosixPath(candidate).replace(/\/$/, ''))));
32
+ const serverLoadPaths = normalizedServerBasePathCandidates.map((candidate)=>`${candidate}/${LOCALES_RESOURCE_PATTERN}`);
33
+ const serverAddPaths = normalizedServerBasePathCandidates.map((candidate)=>`${candidate}/${LOCALES_RESOURCE_PATTERN}`);
34
+ return {
35
+ loadPath: `${normalizedClientBasePath}/${LOCALES_RESOURCE_PATTERN}`,
36
+ addPath: `${normalizedClientBasePath}/${LOCALES_RESOURCE_PATTERN}`,
37
+ serverLoadPath: `${normalizedServerBasePath}/${LOCALES_RESOURCE_PATTERN}`,
38
+ serverAddPath: `${normalizedServerBasePath}/${LOCALES_RESOURCE_PATTERN}`,
39
+ serverLoadPaths,
40
+ serverAddPaths
41
+ };
42
+ }
43
+ function detectLocalesDirectory(appDirectory, normalizedConfig) {
44
+ const publicDirs = normalizePublicDir(normalizedConfig?.server?.publicDir);
45
+ const publicDirPrefixes = getPublicDirRoutePrefixes(normalizedConfig?.server?.publicDir);
46
+ for(let index = 0; index < publicDirs.length; index++){
47
+ const publicDir = publicDirs[index];
48
+ if (path.isAbsolute(publicDir)) continue;
49
+ const publicDirPath = path.join(appDirectory, publicDir);
50
+ const publicDirPrefix = publicDirPrefixes[index] || `/${normalizePublicDirPath(publicDir)}`;
51
+ const publicDirOutputPath = getPublicDirOutputPath(publicDir);
52
+ if ('locales' === path.basename(normalizePublicDirPath(publicDir)) && hasJsonFiles(publicDirPath)) return buildDetectedLocalesDirectory(publicDirPrefix, `./${publicDirOutputPath}`);
53
+ const localesPath = path.join(publicDirPath, 'locales');
54
+ if (hasJsonFiles(localesPath)) return buildDetectedLocalesDirectory(`${publicDirPrefix}/locales`, `./${publicDirOutputPath}/locales`);
55
+ }
56
+ const configPublicPath = path.join(appDirectory, 'config', 'public', 'locales');
57
+ if (hasJsonFiles(configPublicPath)) return buildDetectedLocalesDirectory('/locales', './public/locales', [
58
+ './config/public/locales',
59
+ './public/locales'
60
+ ]);
61
+ const rootLocalesPath = path.join(appDirectory, 'locales');
62
+ if (hasJsonFiles(rootLocalesPath)) return buildDetectedLocalesDirectory('/locales', './locales');
63
+ }
64
+ function applyDetectedBackendPaths(backendOptions, detectedLocales) {
65
+ if (!detectedLocales) return backendOptions;
66
+ const backendWithDetectedPaths = {
67
+ ...backendOptions,
68
+ enabled: true,
69
+ loadPath: backendOptions.loadPath ?? detectedLocales.loadPath,
70
+ addPath: backendOptions.addPath ?? detectedLocales.addPath,
71
+ serverLoadPath: backendOptions.serverLoadPath ?? detectedLocales.serverLoadPath,
72
+ serverLoadPaths: backendOptions.serverLoadPath || backendOptions.serverLoadPaths ? backendOptions.serverLoadPaths : detectedLocales.serverLoadPaths,
73
+ serverAddPath: backendOptions.serverAddPath ?? detectedLocales.serverAddPath,
74
+ serverAddPaths: backendOptions.serverAddPath || backendOptions.serverAddPaths ? backendOptions.serverAddPaths : detectedLocales.serverAddPaths,
75
+ _detectedLoadPath: detectedLocales.loadPath,
76
+ _detectedAddPath: detectedLocales.addPath
77
+ };
78
+ return backendWithDetectedPaths;
79
+ }
80
+ export { applyDetectedBackendPaths, detectLocalesDirectory };
@@ -3,8 +3,6 @@ const DEFAULT_I18NEXT_BACKEND_OPTIONS = {
3
3
  addPath: '/locales/{{lng}}/{{ns}}.json'
4
4
  };
5
5
  function convertPath(path) {
6
- if (!path) return path;
7
- if (path.startsWith('/')) return `${window.__assetPrefix__ || ''}${path}`;
8
6
  return path;
9
7
  }
10
8
  function convertBackendOptions(options) {
@@ -12,6 +10,12 @@ function convertBackendOptions(options) {
12
10
  const converted = {
13
11
  ...options
14
12
  };
13
+ delete converted.serverLoadPath;
14
+ delete converted.serverAddPath;
15
+ delete converted.serverLoadPaths;
16
+ delete converted.serverAddPaths;
17
+ delete converted._detectedLoadPath;
18
+ delete converted._detectedAddPath;
15
19
  if (converted.loadPath) converted.loadPath = convertPath(converted.loadPath);
16
20
  if (converted.addPath) converted.addPath = convertPath(converted.addPath);
17
21
  return converted;
@@ -1,3 +1,4 @@
1
+ import fs from "fs";
1
2
  const DEFAULT_I18NEXT_BACKEND_OPTIONS = {
2
3
  loadPath: './locales/{{lng}}/{{ns}}.json',
3
4
  addPath: './locales/{{lng}}/{{ns}}.json'
@@ -7,13 +8,43 @@ function convertPath(path) {
7
8
  if (path.startsWith('/')) return `.${path}`;
8
9
  return path;
9
10
  }
11
+ function shouldUseServerPath(currentPath, detectedPath) {
12
+ return !detectedPath || currentPath === detectedPath;
13
+ }
14
+ function getResourceBasePath(resourcePath) {
15
+ const markerIndex = resourcePath.indexOf('{{lng}}');
16
+ if (markerIndex < 0) return resourcePath;
17
+ return resourcePath.slice(0, markerIndex).replace(/[\\/]+$/, '');
18
+ }
19
+ function pathExists(resourcePath) {
20
+ try {
21
+ return fs.existsSync(getResourceBasePath(resourcePath));
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+ function getServerPath(pathCandidates, fallbackPath) {
27
+ const candidates = Array.from(new Set([
28
+ ...pathCandidates || [],
29
+ fallbackPath
30
+ ].filter(Boolean)));
31
+ return candidates.find(pathExists) || candidates[0];
32
+ }
10
33
  function convertBackendOptions(options) {
11
34
  if (!options) return options;
12
35
  const converted = {
13
36
  ...options
14
37
  };
15
- if (converted.loadPath) converted.loadPath = convertPath(converted.loadPath);
16
- if (converted.addPath) converted.addPath = convertPath(converted.addPath);
38
+ if ((converted.serverLoadPath || converted.serverLoadPaths) && shouldUseServerPath(converted.loadPath, converted._detectedLoadPath)) converted.loadPath = getServerPath(converted.serverLoadPaths, converted.serverLoadPath);
39
+ else if (converted.loadPath) converted.loadPath = convertPath(converted.loadPath);
40
+ if ((converted.serverAddPath || converted.serverAddPaths) && shouldUseServerPath(converted.addPath, converted._detectedAddPath)) converted.addPath = getServerPath(converted.serverAddPaths, converted.serverAddPath);
41
+ else if (converted.addPath) converted.addPath = convertPath(converted.addPath);
42
+ delete converted.serverLoadPath;
43
+ delete converted.serverAddPath;
44
+ delete converted.serverLoadPaths;
45
+ delete converted.serverAddPaths;
46
+ delete converted._detectedLoadPath;
47
+ delete converted._detectedAddPath;
17
48
  return converted;
18
49
  }
19
50
  export { DEFAULT_I18NEXT_BACKEND_OPTIONS, convertBackendOptions };
@@ -3,7 +3,7 @@ import { getGlobalBasename } from "@modern-js/runtime/context";
3
3
  import { __webpack_require__ } from "../rslib-runtime.mjs";
4
4
  import * as __rspack_external__modern_js_runtime_router_2dfd0c78 from "@modern-js/runtime/router";
5
5
  __webpack_require__.add({
6
- "@modern-js/runtime/router?644e" (module) {
6
+ 7296 (module) {
7
7
  module.exports = __rspack_external__modern_js_runtime_router_2dfd0c78;
8
8
  }
9
9
  });
@@ -56,7 +56,7 @@ const shouldIgnoreRedirect = (pathname, languages, ignoreRedirectRoutes)=>{
56
56
  };
57
57
  const useRouterHooks = ()=>{
58
58
  try {
59
- const { useLocation, useNavigate, useParams } = __webpack_require__("@modern-js/runtime/router?644e");
59
+ const { useLocation, useNavigate, useParams } = __webpack_require__(7296);
60
60
  return {
61
61
  navigate: useNavigate(),
62
62
  location: useLocation(),
@@ -1,39 +1,8 @@
1
1
  import "node:module";
2
- import fs from "fs";
3
- import path from "path";
4
2
  import { getPublicDirRoutePrefixes } from "@modern-js/server-core";
5
3
  import { getBackendOptions, getLocaleDetectionOptions } from "../shared/utils.mjs";
4
+ import { applyDetectedBackendPaths, detectLocalesDirectory } from "./locales.mjs";
6
5
  import "../runtime/types.mjs";
7
- function hasJsonFiles(dirPath) {
8
- try {
9
- if (!fs.existsSync(dirPath) || !fs.statSync(dirPath).isDirectory()) return false;
10
- const entries = fs.readdirSync(dirPath);
11
- for (const entry of entries){
12
- const entryPath = path.join(dirPath, entry);
13
- const stat = fs.statSync(entryPath);
14
- if (stat.isFile() && entry.endsWith('.json')) return true;
15
- if (stat.isDirectory()) {
16
- if (hasJsonFiles(entryPath)) return true;
17
- }
18
- }
19
- return false;
20
- } catch {
21
- return false;
22
- }
23
- }
24
- function detectLocalesDirectory(appDirectory, normalizedConfig) {
25
- const rootLocalesPath = path.join(appDirectory, 'locales');
26
- if (hasJsonFiles(rootLocalesPath)) return true;
27
- const configPublicPath = path.join(appDirectory, 'config', 'public', 'locales');
28
- if (hasJsonFiles(configPublicPath)) return true;
29
- const publicDir = normalizedConfig?.server?.publicDir;
30
- if (publicDir) {
31
- const publicDirPath = Array.isArray(publicDir) ? publicDir[0] : publicDir;
32
- const localesPath = path.isAbsolute(publicDirPath) ? path.join(publicDirPath, 'locales') : path.join(appDirectory, publicDirPath, 'locales');
33
- if (hasJsonFiles(localesPath)) return true;
34
- }
35
- return false;
36
- }
37
6
  const i18nPlugin = (options = {})=>({
38
7
  name: '@modern-js/plugin-i18n',
39
8
  setup: (api)=>{
@@ -43,26 +12,16 @@ const i18nPlugin = (options = {})=>({
43
12
  let backendOptions;
44
13
  const { appDirectory } = api.getAppContext();
45
14
  const normalizedConfig = api.getNormalizedConfig();
15
+ const detectedLocales = detectLocalesDirectory(appDirectory, normalizedConfig);
46
16
  if (backend) {
47
17
  const entryBackendOptions = getBackendOptions(entrypoint.entryName, backend);
48
- if (entryBackendOptions?.enabled === false) backendOptions = entryBackendOptions;
49
- else if (entryBackendOptions?.loadPath || entryBackendOptions?.addPath) backendOptions = {
18
+ backendOptions = entryBackendOptions?.enabled === false ? entryBackendOptions : detectedLocales ? applyDetectedBackendPaths(entryBackendOptions, detectedLocales) : entryBackendOptions?.loadPath || entryBackendOptions?.addPath ? {
50
19
  ...entryBackendOptions,
51
20
  enabled: true
52
- };
53
- else if (entryBackendOptions?.enabled !== true) {
54
- const hasLocales = detectLocalesDirectory(appDirectory, normalizedConfig);
55
- backendOptions = hasLocales ? {
56
- ...entryBackendOptions,
57
- enabled: true
58
- } : entryBackendOptions;
59
- } else backendOptions = entryBackendOptions;
60
- } else {
61
- const hasLocales = detectLocalesDirectory(appDirectory, normalizedConfig);
62
- if (hasLocales) backendOptions = getBackendOptions(entrypoint.entryName, {
63
- enabled: true
64
- });
65
- }
21
+ } : entryBackendOptions;
22
+ } else if (detectedLocales) backendOptions = applyDetectedBackendPaths(getBackendOptions(entrypoint.entryName, {
23
+ enabled: true
24
+ }), detectedLocales);
66
25
  const { metaName } = api.getAppContext();
67
26
  let extendedConfig = restOptions;
68
27
  if (transformRuntimeConfig) extendedConfig = transformRuntimeConfig(restOptions, entrypoint);