next-i18next 2.1.3 → 4.1.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 +12 -9
- package/dist/commonjs/config/create-config.js +69 -18
- package/dist/commonjs/config/default-config.js +2 -2
- package/dist/commonjs/create-i18next-client.js +7 -3
- package/dist/commonjs/index.js +7 -1
- package/dist/commonjs/utils/console-message.js +3 -3
- package/dist/commonjs/utils/subpath-is-present.js +1 -1
- package/dist/es/config/create-config.js +65 -17
- package/dist/es/config/default-config.js +2 -2
- package/dist/es/create-i18next-client.js +7 -2
- package/dist/es/index.js +6 -1
- package/dist/es/utils/console-message.js +2 -2
- package/dist/es/utils/subpath-is-present.js +1 -1
- package/package.json +4 -8
- package/types.d.ts +6 -4
package/README.md
CHANGED
|
@@ -31,18 +31,21 @@ You need to also have `react` and `next` installed.
|
|
|
31
31
|
By default, `next-i18next` expects your translations to be organised as such:
|
|
32
32
|
```
|
|
33
33
|
.
|
|
34
|
-
└──
|
|
35
|
-
└──
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
└──
|
|
34
|
+
└── public
|
|
35
|
+
└── static
|
|
36
|
+
└── locales
|
|
37
|
+
├── en
|
|
38
|
+
| └── common.json
|
|
39
|
+
└── de
|
|
40
|
+
└── common.json
|
|
40
41
|
```
|
|
41
42
|
|
|
42
43
|
This structure can also be seen in the [simple example](./examples/simple).
|
|
43
44
|
|
|
44
45
|
If you want to structure your translations/namespaces in a custom way, you will need to pass modified `localePath` and `localeStructure` values into the initialisation config.
|
|
45
46
|
|
|
47
|
+
If translations are not found in `config.localePath` or `public/static/locales` an attempt will be made to find the locales in `static/locales`, if found a deprecation warning will be logged.
|
|
48
|
+
|
|
46
49
|
### 3. Project setup
|
|
47
50
|
|
|
48
51
|
The default export of `next-i18next` is a class constructor, into which you pass your config options. The resulting class has all the methods you will need to translate your app:
|
|
@@ -236,10 +239,10 @@ MyPage.getInitialProps = async({ req }) => {
|
|
|
236
239
|
| `browserLanguageDetection` | `true` |
|
|
237
240
|
| `defaultNS` | `'common'` |
|
|
238
241
|
| `defaultLanguage` | `'en'` |
|
|
239
|
-
| `ignoreRoutes` | `['/_next/', '/static/']` |
|
|
242
|
+
| `ignoreRoutes` | `['/_next/', '/static/', '/public/', '/api/']` |
|
|
240
243
|
| `otherLanguages` (required) | `[]` |
|
|
241
244
|
| `localeExtension` | `'json'` |
|
|
242
|
-
| `localePath` | `'static/locales'` |
|
|
245
|
+
| `localePath` | `'public/static/locales'` |
|
|
243
246
|
| `localeStructure` | `'{{lng}}/{{ns}}'` |
|
|
244
247
|
| `localeSubpaths` | `{}` |
|
|
245
248
|
| `serverLanguageDetection` | `true` |
|
|
@@ -263,7 +266,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
|
|
|
263
266
|
|
|
264
267
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
|
265
268
|
<!-- prettier-ignore -->
|
|
266
|
-
<table cellspacing="0" cellpadding="1"><tr><td><a href="https://github.com/capellini"><img src="https://avatars3.githubusercontent.com/u/75311?v=4" width="100px;" height="100px;" alt="Rob Capellini"/><br /><sub><b>Rob Capellini</b></sub></a><br /><a href="https://github.com/isaachinman/next-i18next/commits?author=capellini" title="Code">💻</a> <a href="https://github.com/isaachinman/next-i18next/commits?author=capellini" title="Tests">⚠️</a></td><td><a href="https://en.kachkaev.ru"><img src="https://avatars3.githubusercontent.com/u/608862?v=4" width="100px;" height="100px;" alt="Alexander Kachkaev"/><br /><sub><b>Alexander Kachkaev</b></sub></a><br /><a href="#talk-kachkaev" title="Talks">📢</a> <a href="#question-kachkaev" title="Answering Questions">💬</a> <a href="#ideas-kachkaev" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/isaachinman/next-i18next/commits?author=kachkaev" title="Code">💻</a> <a href="https://github.com/isaachinman/next-i18next/commits?author=kachkaev" title="Tests">⚠️</a></td><td><a href="https://kandelborg.dk"><img src="https://avatars1.githubusercontent.com/u/33042011?v=4" width="100px;" height="100px;" alt="Mathias Wøbbe"/><br /><sub><b>Mathias Wøbbe</b></sub></a><br /><a href="https://github.com/isaachinman/next-i18next/commits?author=MathiasKandelborg" title="Code">💻</a> <a href="#ideas-MathiasKandelborg" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/isaachinman/next-i18next/commits?author=MathiasKandelborg" title="Tests">⚠️</a></td><td><a href="http://lucasfeliciano.com"><img src="https://avatars3.githubusercontent.com/u/968014?v=4" width="100px;" height="100px;" alt="Lucas Feliciano"/><br /><sub><b>Lucas Feliciano</b></sub></a><br /><a href="#ideas-lucasfeliciano" title="Ideas, Planning, & Feedback">🤔</a> <a href="#review-lucasfeliciano" title="Reviewed Pull Requests">👀</a></td><td><a href="http://www.fifteenprospects.com"><img src="https://avatars2.githubusercontent.com/u/6932550?v=4" width="100px;" height="100px;" alt="Ryan Leung"/><br /><sub><b>Ryan Leung</b></sub></a><br /><a href="https://github.com/isaachinman/next-i18next/commits?author=minocys" title="Code">💻</a></td></tr></table>
|
|
269
|
+
<table cellspacing="0" cellpadding="1"><tr><td><a href="https://github.com/capellini"><img src="https://avatars3.githubusercontent.com/u/75311?v=4" width="100px;" height="100px;" alt="Rob Capellini"/><br /><sub><b>Rob Capellini</b></sub></a><br /><a href="https://github.com/isaachinman/next-i18next/commits?author=capellini" title="Code">💻</a> <a href="https://github.com/isaachinman/next-i18next/commits?author=capellini" title="Tests">⚠️</a></td><td><a href="https://en.kachkaev.ru"><img src="https://avatars3.githubusercontent.com/u/608862?v=4" width="100px;" height="100px;" alt="Alexander Kachkaev"/><br /><sub><b>Alexander Kachkaev</b></sub></a><br /><a href="#talk-kachkaev" title="Talks">📢</a> <a href="#question-kachkaev" title="Answering Questions">💬</a> <a href="#ideas-kachkaev" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/isaachinman/next-i18next/commits?author=kachkaev" title="Code">💻</a> <a href="https://github.com/isaachinman/next-i18next/commits?author=kachkaev" title="Tests">⚠️</a></td><td><a href="https://kandelborg.dk"><img src="https://avatars1.githubusercontent.com/u/33042011?v=4" width="100px;" height="100px;" alt="Mathias Wøbbe"/><br /><sub><b>Mathias Wøbbe</b></sub></a><br /><a href="https://github.com/isaachinman/next-i18next/commits?author=MathiasKandelborg" title="Code">💻</a> <a href="#ideas-MathiasKandelborg" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/isaachinman/next-i18next/commits?author=MathiasKandelborg" title="Tests">⚠️</a></td><td><a href="http://lucasfeliciano.com"><img src="https://avatars3.githubusercontent.com/u/968014?v=4" width="100px;" height="100px;" alt="Lucas Feliciano"/><br /><sub><b>Lucas Feliciano</b></sub></a><br /><a href="#ideas-lucasfeliciano" title="Ideas, Planning, & Feedback">🤔</a> <a href="#review-lucasfeliciano" title="Reviewed Pull Requests">👀</a></td><td><a href="http://www.fifteenprospects.com"><img src="https://avatars2.githubusercontent.com/u/6932550?v=4" width="100px;" height="100px;" alt="Ryan Leung"/><br /><sub><b>Ryan Leung</b></sub></a><br /><a href="https://github.com/isaachinman/next-i18next/commits?author=minocys" title="Code">💻</a></td><td><a href="http://nathanfriemel.com"><img src="https://avatars3.githubusercontent.com/u/1325835?v=4" width="100px;" height="100px;" alt="Nathan Friemel"/><br /><sub><b>Nathan Friemel</b></sub></a><br /><a href="https://github.com/isaachinman/next-i18next/commits?author=nathanfriemel" title="Code">💻</a> <a href="https://github.com/isaachinman/next-i18next/commits?author=nathanfriemel" title="Documentation">📖</a> <a href="#example-nathanfriemel" title="Examples">💡</a> <a href="#ideas-nathanfriemel" title="Ideas, Planning, & Feedback">🤔</a></td></tr></table>
|
|
267
270
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
|
268
271
|
|
|
269
272
|
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
|
@@ -11,6 +11,8 @@ exports.createConfig = void 0;
|
|
|
11
11
|
|
|
12
12
|
require("core-js/modules/es6.array.for-each");
|
|
13
13
|
|
|
14
|
+
require("core-js/modules/es6.string.starts-with");
|
|
15
|
+
|
|
14
16
|
require("core-js/modules/es6.regexp.replace");
|
|
15
17
|
|
|
16
18
|
require("core-js/modules/es6.array.map");
|
|
@@ -23,7 +25,7 @@ require("core-js/modules/es6.array.filter");
|
|
|
23
25
|
|
|
24
26
|
var _defaultConfig = require("./default-config");
|
|
25
27
|
|
|
26
|
-
var
|
|
28
|
+
var _utils = require("../utils");
|
|
27
29
|
|
|
28
30
|
var deepMergeObjects = ['backend', 'detection'];
|
|
29
31
|
|
|
@@ -33,13 +35,21 @@ var dedupe = function dedupe(names) {
|
|
|
33
35
|
});
|
|
34
36
|
};
|
|
35
37
|
|
|
38
|
+
var STATIC_LOCALE_PATH = 'static/locales';
|
|
39
|
+
|
|
36
40
|
var createConfig = function createConfig(userConfig) {
|
|
37
41
|
if (typeof userConfig.localeSubpaths === 'string') {
|
|
38
42
|
throw new Error('The localeSubpaths option has been changed to an object. Please refer to documentation.');
|
|
39
|
-
}
|
|
43
|
+
}
|
|
44
|
+
/*
|
|
45
|
+
Initial merge of default and user-provided config
|
|
46
|
+
*/
|
|
40
47
|
|
|
41
48
|
|
|
42
|
-
var combinedConfig = (0, _objectSpread2["default"])({}, _defaultConfig.defaultConfig, userConfig);
|
|
49
|
+
var combinedConfig = (0, _objectSpread2["default"])({}, _defaultConfig.defaultConfig, userConfig);
|
|
50
|
+
/*
|
|
51
|
+
Sensible defaults to prevent user duplication
|
|
52
|
+
*/
|
|
43
53
|
|
|
44
54
|
combinedConfig.allLanguages = dedupe(combinedConfig.otherLanguages.concat([combinedConfig.defaultLanguage]));
|
|
45
55
|
combinedConfig.whitelist = combinedConfig.allLanguages;
|
|
@@ -49,26 +59,49 @@ var createConfig = function createConfig(userConfig) {
|
|
|
49
59
|
localePath = combinedConfig.localePath,
|
|
50
60
|
localeStructure = combinedConfig.localeStructure;
|
|
51
61
|
|
|
52
|
-
if ((0,
|
|
62
|
+
if ((0, _utils.isServer)()) {
|
|
53
63
|
var fs = eval("require('fs')");
|
|
54
64
|
|
|
55
|
-
var path = require('path');
|
|
56
|
-
// https://github.com/isaachinman/next-i18next/issues/358
|
|
65
|
+
var path = require('path');
|
|
57
66
|
|
|
67
|
+
var serverLocalePath = localePath;
|
|
68
|
+
/*
|
|
69
|
+
Validate defaultNS
|
|
70
|
+
https://github.com/isaachinman/next-i18next/issues/358
|
|
71
|
+
*/
|
|
58
72
|
|
|
59
|
-
if (
|
|
60
|
-
var
|
|
73
|
+
if (typeof combinedConfig.defaultNS === 'string') {
|
|
74
|
+
var defaultFile = "/".concat(defaultLanguage, "/").concat(combinedConfig.defaultNS, ".").concat(localeExtension);
|
|
75
|
+
var defaultNSPath = path.join(process.cwd(), localePath, defaultFile);
|
|
61
76
|
var defaultNSExists = fs.existsSync(defaultNSPath);
|
|
62
77
|
|
|
63
78
|
if (!defaultNSExists) {
|
|
64
|
-
|
|
79
|
+
/*
|
|
80
|
+
If defaultNS doesn't exist, try to fall back to the deprecated static folder
|
|
81
|
+
https://github.com/isaachinman/next-i18next/issues/523
|
|
82
|
+
*/
|
|
83
|
+
var staticDirPath = path.join(process.cwd(), STATIC_LOCALE_PATH, defaultFile);
|
|
84
|
+
var staticDirExists = fs.existsSync(staticDirPath);
|
|
85
|
+
|
|
86
|
+
if (staticDirExists) {
|
|
87
|
+
(0, _utils.consoleMessage)('warn', 'next-i18next: Falling back to /static folder, deprecated in next@9.1.*', combinedConfig);
|
|
88
|
+
serverLocalePath = STATIC_LOCALE_PATH;
|
|
89
|
+
} else if (process.env.NODE_ENV !== 'production') {
|
|
90
|
+
throw new Error("Default namespace not found at ".concat(defaultNSPath));
|
|
91
|
+
}
|
|
65
92
|
}
|
|
66
|
-
}
|
|
93
|
+
}
|
|
94
|
+
/*
|
|
95
|
+
Set server side backend
|
|
96
|
+
*/
|
|
67
97
|
|
|
68
98
|
|
|
69
99
|
combinedConfig.backend = {
|
|
70
|
-
loadPath: path.join(process.cwd(), "".concat(
|
|
71
|
-
addPath: path.join(process.cwd(), "".concat(
|
|
100
|
+
loadPath: path.join(process.cwd(), "".concat(serverLocalePath, "/").concat(localeStructure, ".").concat(localeExtension)),
|
|
101
|
+
addPath: path.join(process.cwd(), "".concat(serverLocalePath, "/").concat(localeStructure, ".missing.").concat(localeExtension))
|
|
102
|
+
/*
|
|
103
|
+
Set server side preload (languages and namespaces)
|
|
104
|
+
*/
|
|
72
105
|
|
|
73
106
|
};
|
|
74
107
|
combinedConfig.preload = allLanguages;
|
|
@@ -80,21 +113,39 @@ var createConfig = function createConfig(userConfig) {
|
|
|
80
113
|
});
|
|
81
114
|
};
|
|
82
115
|
|
|
83
|
-
combinedConfig.ns = getAllNamespaces(path.join(process.cwd(), "".concat(
|
|
116
|
+
combinedConfig.ns = getAllNamespaces(path.join(process.cwd(), "".concat(serverLocalePath, "/").concat(defaultLanguage)));
|
|
84
117
|
}
|
|
85
118
|
} else {
|
|
86
|
-
|
|
119
|
+
var clientLocalePath = localePath;
|
|
120
|
+
/*
|
|
121
|
+
Remove public prefix from client site config
|
|
122
|
+
*/
|
|
123
|
+
|
|
124
|
+
if (localePath.startsWith('public/')) {
|
|
125
|
+
clientLocalePath = localePath.replace(/^public\//, '');
|
|
126
|
+
}
|
|
127
|
+
/*
|
|
128
|
+
Set client side backend
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
|
|
87
132
|
combinedConfig.backend = {
|
|
88
|
-
loadPath: "/".concat(
|
|
89
|
-
addPath: "/".concat(
|
|
133
|
+
loadPath: "/".concat(clientLocalePath, "/").concat(localeStructure, ".").concat(localeExtension),
|
|
134
|
+
addPath: "/".concat(clientLocalePath, "/").concat(localeStructure, ".missing.").concat(localeExtension)
|
|
90
135
|
};
|
|
91
136
|
combinedConfig.ns = [combinedConfig.defaultNS];
|
|
92
|
-
}
|
|
137
|
+
}
|
|
138
|
+
/*
|
|
139
|
+
Set fallback language to defaultLanguage in production
|
|
140
|
+
*/
|
|
93
141
|
|
|
94
142
|
|
|
95
143
|
if (!userConfig.fallbackLng) {
|
|
96
144
|
combinedConfig.fallbackLng = process.env.NODE_ENV === 'production' ? combinedConfig.defaultLanguage : false;
|
|
97
|
-
}
|
|
145
|
+
}
|
|
146
|
+
/*
|
|
147
|
+
Deep merge with overwrite - goes last
|
|
148
|
+
*/
|
|
98
149
|
|
|
99
150
|
|
|
100
151
|
deepMergeObjects.forEach(function (obj) {
|
|
@@ -12,7 +12,7 @@ var _utils = require("../utils");
|
|
|
12
12
|
var DEFAULT_LANGUAGE = 'en';
|
|
13
13
|
var OTHER_LANGUAGES = [];
|
|
14
14
|
var DEFAULT_NAMESPACE = 'common';
|
|
15
|
-
var LOCALE_PATH = 'static/locales';
|
|
15
|
+
var LOCALE_PATH = 'public/static/locales';
|
|
16
16
|
var LOCALE_STRUCTURE = '{{lng}}/{{ns}}';
|
|
17
17
|
var LOCALE_EXTENSION = 'json';
|
|
18
18
|
var defaultConfig = {
|
|
@@ -34,7 +34,7 @@ var defaultConfig = {
|
|
|
34
34
|
},
|
|
35
35
|
browserLanguageDetection: true,
|
|
36
36
|
serverLanguageDetection: true,
|
|
37
|
-
ignoreRoutes: ['/_next/', '/static/'],
|
|
37
|
+
ignoreRoutes: ['/_next/', '/static/', '/public/', '/api/'],
|
|
38
38
|
customDetectors: [],
|
|
39
39
|
detection: {
|
|
40
40
|
lookupCookie: 'next-i18next',
|
|
@@ -20,6 +20,8 @@ var _i18nextXhrBackend = _interopRequireDefault(require("i18next-xhr-backend"));
|
|
|
20
20
|
var _i18nextBrowserLanguagedetector = _interopRequireDefault(require("i18next-browser-languagedetector"));
|
|
21
21
|
|
|
22
22
|
var _default = function _default(config) {
|
|
23
|
+
var initPromise;
|
|
24
|
+
|
|
23
25
|
if (!_i18next["default"].isInitialized) {
|
|
24
26
|
if (_detectNode["default"]) {
|
|
25
27
|
var i18nextNodeBackend = eval("require('i18next-node-fs-backend')");
|
|
@@ -51,11 +53,13 @@ var _default = function _default(config) {
|
|
|
51
53
|
config.use.forEach(function (x) {
|
|
52
54
|
return _i18next["default"].use(x);
|
|
53
55
|
});
|
|
54
|
-
|
|
55
|
-
_i18next["default"].init(config);
|
|
56
|
+
initPromise = _i18next["default"].init(config);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
return
|
|
59
|
+
return {
|
|
60
|
+
i18n: _i18next["default"],
|
|
61
|
+
initPromise: initPromise
|
|
62
|
+
};
|
|
59
63
|
};
|
|
60
64
|
|
|
61
65
|
exports["default"] = _default;
|
package/dist/commonjs/index.js
CHANGED
|
@@ -43,6 +43,7 @@ var NextI18Next = function NextI18Next(userConfig) {
|
|
|
43
43
|
(0, _defineProperty2["default"])(this, "Link", void 0);
|
|
44
44
|
(0, _defineProperty2["default"])(this, "Router", void 0);
|
|
45
45
|
(0, _defineProperty2["default"])(this, "i18n", void 0);
|
|
46
|
+
(0, _defineProperty2["default"])(this, "initPromise", void 0);
|
|
46
47
|
(0, _defineProperty2["default"])(this, "config", void 0);
|
|
47
48
|
(0, _defineProperty2["default"])(this, "useTranslation", void 0);
|
|
48
49
|
(0, _defineProperty2["default"])(this, "withTranslation", void 0);
|
|
@@ -61,7 +62,12 @@ var NextI18Next = function NextI18Next(userConfig) {
|
|
|
61
62
|
throw new Error('next-i18next has upgraded to react-i18next v10 - please rename withNamespaces to withTranslation.');
|
|
62
63
|
};
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
var _createI18NextClient = (0, _createI18nextClient["default"])(this.config),
|
|
66
|
+
i18n = _createI18NextClient.i18n,
|
|
67
|
+
initPromise = _createI18NextClient.initPromise;
|
|
68
|
+
|
|
69
|
+
this.i18n = i18n;
|
|
70
|
+
this.initPromise = initPromise;
|
|
65
71
|
this.appWithTranslation = _hocs.appWithTranslation.bind(this);
|
|
66
72
|
|
|
67
73
|
this.withTranslation = function (namespace, options) {
|
|
@@ -44,9 +44,9 @@ var logMessage = function logMessage(messageType, message) {
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
var consoleMessage = function consoleMessage(messageType, message) {
|
|
47
|
-
var
|
|
48
|
-
|
|
49
|
-
strictMode =
|
|
47
|
+
var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.config;
|
|
48
|
+
var errorStackTraceLimit = config.errorStackTraceLimit,
|
|
49
|
+
strictMode = config.strictMode;
|
|
50
50
|
var prevStackLimit = Error.stackTraceLimit;
|
|
51
51
|
var util;
|
|
52
52
|
|
|
@@ -19,7 +19,7 @@ var subpathIsPresent = function subpathIsPresent(url, subpath) {
|
|
|
19
19
|
var _parseUrl = (0, _url.parse)(url),
|
|
20
20
|
pathname = _parseUrl.pathname;
|
|
21
21
|
|
|
22
|
-
return pathname.length === subpath.length + 1 && pathname === "/".concat(subpath) || pathname.startsWith("/".concat(subpath, "/"));
|
|
22
|
+
return typeof pathname === 'string' && (pathname.length === subpath.length + 1 && pathname === "/".concat(subpath) || pathname.startsWith("/".concat(subpath, "/")));
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
exports.subpathIsPresent = subpathIsPresent;
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import { defaultConfig } from './default-config';
|
|
2
|
-
import { isServer } from '../utils
|
|
2
|
+
import { consoleMessage, isServer } from '../utils';
|
|
3
3
|
const deepMergeObjects = ['backend', 'detection'];
|
|
4
4
|
|
|
5
5
|
const dedupe = names => names.filter((v, i) => names.indexOf(v) === i);
|
|
6
6
|
|
|
7
|
+
const STATIC_LOCALE_PATH = 'static/locales';
|
|
7
8
|
export const createConfig = userConfig => {
|
|
8
9
|
if (typeof userConfig.localeSubpaths === 'string') {
|
|
9
10
|
throw new Error('The localeSubpaths option has been changed to an object. Please refer to documentation.');
|
|
10
|
-
}
|
|
11
|
+
}
|
|
12
|
+
/*
|
|
13
|
+
Initial merge of default and user-provided config
|
|
14
|
+
*/
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
const combinedConfig = { ...defaultConfig,
|
|
14
18
|
...userConfig
|
|
15
|
-
};
|
|
19
|
+
};
|
|
20
|
+
/*
|
|
21
|
+
Sensible defaults to prevent user duplication
|
|
22
|
+
*/
|
|
16
23
|
|
|
17
24
|
combinedConfig.allLanguages = dedupe(combinedConfig.otherLanguages.concat([combinedConfig.defaultLanguage]));
|
|
18
25
|
combinedConfig.whitelist = combinedConfig.allLanguages;
|
|
@@ -27,23 +34,46 @@ export const createConfig = userConfig => {
|
|
|
27
34
|
if (isServer()) {
|
|
28
35
|
const fs = eval("require('fs')");
|
|
29
36
|
|
|
30
|
-
const path = require('path');
|
|
31
|
-
// https://github.com/isaachinman/next-i18next/issues/358
|
|
37
|
+
const path = require('path');
|
|
32
38
|
|
|
39
|
+
let serverLocalePath = localePath;
|
|
40
|
+
/*
|
|
41
|
+
Validate defaultNS
|
|
42
|
+
https://github.com/isaachinman/next-i18next/issues/358
|
|
43
|
+
*/
|
|
33
44
|
|
|
34
|
-
if (
|
|
35
|
-
const
|
|
45
|
+
if (typeof combinedConfig.defaultNS === 'string') {
|
|
46
|
+
const defaultFile = `/${defaultLanguage}/${combinedConfig.defaultNS}.${localeExtension}`;
|
|
47
|
+
const defaultNSPath = path.join(process.cwd(), localePath, defaultFile);
|
|
36
48
|
const defaultNSExists = fs.existsSync(defaultNSPath);
|
|
37
49
|
|
|
38
50
|
if (!defaultNSExists) {
|
|
39
|
-
|
|
51
|
+
/*
|
|
52
|
+
If defaultNS doesn't exist, try to fall back to the deprecated static folder
|
|
53
|
+
https://github.com/isaachinman/next-i18next/issues/523
|
|
54
|
+
*/
|
|
55
|
+
const staticDirPath = path.join(process.cwd(), STATIC_LOCALE_PATH, defaultFile);
|
|
56
|
+
const staticDirExists = fs.existsSync(staticDirPath);
|
|
57
|
+
|
|
58
|
+
if (staticDirExists) {
|
|
59
|
+
consoleMessage('warn', 'next-i18next: Falling back to /static folder, deprecated in next@9.1.*', combinedConfig);
|
|
60
|
+
serverLocalePath = STATIC_LOCALE_PATH;
|
|
61
|
+
} else if (process.env.NODE_ENV !== 'production') {
|
|
62
|
+
throw new Error(`Default namespace not found at ${defaultNSPath}`);
|
|
63
|
+
}
|
|
40
64
|
}
|
|
41
|
-
}
|
|
65
|
+
}
|
|
66
|
+
/*
|
|
67
|
+
Set server side backend
|
|
68
|
+
*/
|
|
42
69
|
|
|
43
70
|
|
|
44
71
|
combinedConfig.backend = {
|
|
45
|
-
loadPath: path.join(process.cwd(), `${
|
|
46
|
-
addPath: path.join(process.cwd(), `${
|
|
72
|
+
loadPath: path.join(process.cwd(), `${serverLocalePath}/${localeStructure}.${localeExtension}`),
|
|
73
|
+
addPath: path.join(process.cwd(), `${serverLocalePath}/${localeStructure}.missing.${localeExtension}`)
|
|
74
|
+
/*
|
|
75
|
+
Set server side preload (languages and namespaces)
|
|
76
|
+
*/
|
|
47
77
|
|
|
48
78
|
};
|
|
49
79
|
combinedConfig.preload = allLanguages;
|
|
@@ -51,21 +81,39 @@ export const createConfig = userConfig => {
|
|
|
51
81
|
if (!combinedConfig.ns) {
|
|
52
82
|
const getAllNamespaces = p => fs.readdirSync(p).map(file => file.replace(`.${localeExtension}`, ''));
|
|
53
83
|
|
|
54
|
-
combinedConfig.ns = getAllNamespaces(path.join(process.cwd(), `${
|
|
84
|
+
combinedConfig.ns = getAllNamespaces(path.join(process.cwd(), `${serverLocalePath}/${defaultLanguage}`));
|
|
55
85
|
}
|
|
56
86
|
} else {
|
|
57
|
-
|
|
87
|
+
let clientLocalePath = localePath;
|
|
88
|
+
/*
|
|
89
|
+
Remove public prefix from client site config
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
if (localePath.startsWith('public/')) {
|
|
93
|
+
clientLocalePath = localePath.replace(/^public\//, '');
|
|
94
|
+
}
|
|
95
|
+
/*
|
|
96
|
+
Set client side backend
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
|
|
58
100
|
combinedConfig.backend = {
|
|
59
|
-
loadPath: `/${
|
|
60
|
-
addPath: `/${
|
|
101
|
+
loadPath: `/${clientLocalePath}/${localeStructure}.${localeExtension}`,
|
|
102
|
+
addPath: `/${clientLocalePath}/${localeStructure}.missing.${localeExtension}`
|
|
61
103
|
};
|
|
62
104
|
combinedConfig.ns = [combinedConfig.defaultNS];
|
|
63
|
-
}
|
|
105
|
+
}
|
|
106
|
+
/*
|
|
107
|
+
Set fallback language to defaultLanguage in production
|
|
108
|
+
*/
|
|
64
109
|
|
|
65
110
|
|
|
66
111
|
if (!userConfig.fallbackLng) {
|
|
67
112
|
combinedConfig.fallbackLng = process.env.NODE_ENV === 'production' ? combinedConfig.defaultLanguage : false;
|
|
68
|
-
}
|
|
113
|
+
}
|
|
114
|
+
/*
|
|
115
|
+
Deep merge with overwrite - goes last
|
|
116
|
+
*/
|
|
69
117
|
|
|
70
118
|
|
|
71
119
|
deepMergeObjects.forEach(obj => {
|
|
@@ -2,7 +2,7 @@ import { isServer } from '../utils';
|
|
|
2
2
|
const DEFAULT_LANGUAGE = 'en';
|
|
3
3
|
const OTHER_LANGUAGES = [];
|
|
4
4
|
const DEFAULT_NAMESPACE = 'common';
|
|
5
|
-
const LOCALE_PATH = 'static/locales';
|
|
5
|
+
const LOCALE_PATH = 'public/static/locales';
|
|
6
6
|
const LOCALE_STRUCTURE = '{{lng}}/{{ns}}';
|
|
7
7
|
const LOCALE_EXTENSION = 'json';
|
|
8
8
|
export const defaultConfig = {
|
|
@@ -22,7 +22,7 @@ export const defaultConfig = {
|
|
|
22
22
|
},
|
|
23
23
|
browserLanguageDetection: true,
|
|
24
24
|
serverLanguageDetection: true,
|
|
25
|
-
ignoreRoutes: ['/_next/', '/static/'],
|
|
25
|
+
ignoreRoutes: ['/_next/', '/static/', '/public/', '/api/'],
|
|
26
26
|
customDetectors: [],
|
|
27
27
|
detection: {
|
|
28
28
|
lookupCookie: 'next-i18next',
|
|
@@ -3,6 +3,8 @@ import i18n from 'i18next';
|
|
|
3
3
|
import i18nextXHRBackend from 'i18next-xhr-backend';
|
|
4
4
|
import I18nextBrowserLanguageDetector from 'i18next-browser-languagedetector';
|
|
5
5
|
export default (config => {
|
|
6
|
+
let initPromise;
|
|
7
|
+
|
|
6
8
|
if (!i18n.isInitialized) {
|
|
7
9
|
if (isNode) {
|
|
8
10
|
const i18nextNodeBackend = eval("require('i18next-node-fs-backend')");
|
|
@@ -25,8 +27,11 @@ export default (config => {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
config.use.forEach(x => i18n.use(x));
|
|
28
|
-
i18n.init(config);
|
|
30
|
+
initPromise = i18n.init(config);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
return
|
|
33
|
+
return {
|
|
34
|
+
i18n,
|
|
35
|
+
initPromise
|
|
36
|
+
};
|
|
32
37
|
});
|
package/dist/es/index.js
CHANGED
|
@@ -21,7 +21,12 @@ export default class NextI18Next {
|
|
|
21
21
|
throw new Error('next-i18next has upgraded to react-i18next v10 - please rename withNamespaces to withTranslation.');
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const {
|
|
25
|
+
i18n,
|
|
26
|
+
initPromise
|
|
27
|
+
} = createI18NextClient(this.config);
|
|
28
|
+
this.i18n = i18n;
|
|
29
|
+
this.initPromise = initPromise;
|
|
25
30
|
this.appWithTranslation = appWithTranslation.bind(this);
|
|
26
31
|
|
|
27
32
|
this.withTranslation = (namespace, options) => Component => hoistNonReactStatics(withTranslation(namespace, options)(Component), Component);
|
|
@@ -14,11 +14,11 @@ const logMessage = (messageType, message) => {
|
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
export const consoleMessage = function (messageType, message) {
|
|
17
|
+
export const consoleMessage = function (messageType, message, config = this.config) {
|
|
18
18
|
const {
|
|
19
19
|
errorStackTraceLimit,
|
|
20
20
|
strictMode
|
|
21
|
-
} =
|
|
21
|
+
} = config;
|
|
22
22
|
const prevStackLimit = Error.stackTraceLimit;
|
|
23
23
|
let util;
|
|
24
24
|
|
|
@@ -7,5 +7,5 @@ export const subpathIsPresent = (url, subpath) => {
|
|
|
7
7
|
const {
|
|
8
8
|
pathname
|
|
9
9
|
} = parseUrl(url);
|
|
10
|
-
return pathname.length === subpath.length + 1 && pathname === `/${subpath}` || pathname.startsWith(`/${subpath}/`);
|
|
10
|
+
return typeof pathname === 'string' && (pathname.length === subpath.length + 1 && pathname === `/${subpath}` || pathname.startsWith(`/${subpath}/`));
|
|
11
11
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-i18next",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"repository": "git@github.com:isaachinman/next-i18next.git",
|
|
5
5
|
"author": "Isaac Hinman <isaac@isaachinman.com>",
|
|
6
6
|
"funding": {
|
|
@@ -95,15 +95,15 @@
|
|
|
95
95
|
"jsdom-global": "^3.0.2",
|
|
96
96
|
"next": "^9.0.1",
|
|
97
97
|
"puppeteer": "^1.11.0",
|
|
98
|
-
"react": "^16.
|
|
99
|
-
"react-dom": "^16.
|
|
98
|
+
"react": "^16.12.0",
|
|
99
|
+
"react-dom": "^16.12.0",
|
|
100
100
|
"typescript": "^3.5.3"
|
|
101
101
|
},
|
|
102
102
|
"dependencies": {
|
|
103
103
|
"core-js": "^2",
|
|
104
104
|
"detect-node": "^2.0.4",
|
|
105
105
|
"hoist-non-react-statics": "^3.2.0",
|
|
106
|
-
"i18next": "^
|
|
106
|
+
"i18next": "^19.0.3",
|
|
107
107
|
"i18next-browser-languagedetector": "^4.0.0",
|
|
108
108
|
"i18next-express-middleware": "^1.5.0",
|
|
109
109
|
"i18next-node-fs-backend": "^2.1.0",
|
|
@@ -113,10 +113,6 @@
|
|
|
113
113
|
"react-i18next": "^11.0.0",
|
|
114
114
|
"url": "^0.11.0"
|
|
115
115
|
},
|
|
116
|
-
"resolutions": {
|
|
117
|
-
"**/react": "^16.8.6",
|
|
118
|
-
"**/react-dom": "^16.8.6"
|
|
119
|
-
},
|
|
120
116
|
"peerDependencies": {
|
|
121
117
|
"next": ">= 7.0.0",
|
|
122
118
|
"react": ">= 16.8.0"
|
package/types.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from 'react-i18next'
|
|
10
10
|
import { LinkProps } from 'next/link'
|
|
11
11
|
import { SingletonRouter } from 'next/router'
|
|
12
|
-
import
|
|
12
|
+
import { InitOptions, i18n, TFunction as I18NextTFunction } from 'i18next'
|
|
13
13
|
|
|
14
14
|
export type InitConfig = {
|
|
15
15
|
browserLanguageDetection?: boolean;
|
|
@@ -23,7 +23,7 @@ export type InitConfig = {
|
|
|
23
23
|
localeSubpaths?: Record<string, string>;
|
|
24
24
|
use?: any[];
|
|
25
25
|
customDetectors?: any[];
|
|
26
|
-
} &
|
|
26
|
+
} & InitOptions
|
|
27
27
|
|
|
28
28
|
export type Config = {
|
|
29
29
|
fallbackLng: boolean;
|
|
@@ -42,10 +42,11 @@ export type Link = React.ComponentClass<LinkProps>
|
|
|
42
42
|
export type Router = SingletonRouter
|
|
43
43
|
export type UseTranslation = typeof useTranslation
|
|
44
44
|
export type AppWithTranslation = <P extends object>(Component: React.ComponentType<P> | React.ElementType<P>) => any
|
|
45
|
-
export type TFunction =
|
|
46
|
-
export type I18n =
|
|
45
|
+
export type TFunction = I18NextTFunction
|
|
46
|
+
export type I18n = i18n
|
|
47
47
|
export type WithTranslationHocType = typeof withTranslation
|
|
48
48
|
export type WithTranslation = ReactI18nextWithTranslation
|
|
49
|
+
export type InitPromise = Promise<TFunction>
|
|
49
50
|
|
|
50
51
|
declare class NextI18Next {
|
|
51
52
|
constructor(config: InitConfig);
|
|
@@ -53,6 +54,7 @@ declare class NextI18Next {
|
|
|
53
54
|
Link: Link
|
|
54
55
|
Router: Router
|
|
55
56
|
i18n: I18n
|
|
57
|
+
initPromise: InitPromise
|
|
56
58
|
config: Config
|
|
57
59
|
useTranslation: UseTranslation
|
|
58
60
|
withTranslation: WithTranslationHocType
|