react-i18next 14.1.1 → 14.1.3
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/CHANGELOG.md +13 -0
- package/README.md +0 -2
- package/dist/amd/react-i18next.js +112 -126
- package/dist/amd/react-i18next.min.js +1 -1
- package/dist/commonjs/TransWithoutContext.js +51 -45
- package/dist/commonjs/context.js +15 -23
- package/dist/commonjs/defaults.js +6 -7
- package/dist/commonjs/i18nInstance.js +6 -7
- package/dist/commonjs/useSSR.js +4 -3
- package/dist/commonjs/useTranslation.js +11 -14
- package/dist/commonjs/utils.js +22 -19
- package/dist/commonjs/withSSR.js +19 -20
- package/dist/commonjs/withTranslation.js +4 -3
- package/dist/es/TransWithoutContext.js +50 -45
- package/dist/es/context.js +11 -20
- package/dist/es/defaults.js +3 -5
- package/dist/es/i18nInstance.js +3 -5
- package/dist/es/package.json +1 -1
- package/dist/es/useSSR.js +2 -2
- package/dist/es/useTranslation.js +10 -14
- package/dist/es/utils.js +15 -15
- package/dist/es/withSSR.js +17 -19
- package/dist/es/withTranslation.js +2 -2
- package/dist/umd/react-i18next.js +112 -126
- package/dist/umd/react-i18next.min.js +1 -1
- package/package.json +2 -2
- package/react-i18next.js +112 -126
- package/react-i18next.min.js +1 -1
- package/src/TransWithoutContext.js +49 -47
- package/src/context.js +13 -34
- package/src/defaults.js +3 -5
- package/src/i18nInstance.js +3 -5
- package/src/useSSR.js +2 -2
- package/src/useTranslation.js +19 -18
- package/src/utils.js +23 -20
- package/src/withSSR.js +2 -3
- package/src/withTranslation.js +2 -3
|
@@ -1,39 +1,35 @@
|
|
|
1
1
|
import { Fragment, isValidElement, cloneElement, createElement, Children } from 'react';
|
|
2
2
|
import HTML from 'html-parse-stringify';
|
|
3
|
-
import { warn, warnOnce } from './utils.js';
|
|
3
|
+
import { isObject, isString, warn, warnOnce } from './utils.js';
|
|
4
4
|
import { getDefaults } from './defaults.js';
|
|
5
5
|
import { getI18n } from './i18nInstance.js';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const hasChildren = (node, checkLength) => {
|
|
8
8
|
if (!node) return false;
|
|
9
9
|
const base = node.props ? node.props.children : node.children;
|
|
10
10
|
if (checkLength) return base.length > 0;
|
|
11
11
|
return !!base;
|
|
12
|
-
}
|
|
12
|
+
};
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const getChildren = (node) => {
|
|
15
15
|
if (!node) return [];
|
|
16
16
|
const children = node.props ? node.props.children : node.children;
|
|
17
17
|
return node.props && node.props.i18nIsDynamicList ? getAsArray(children) : children;
|
|
18
|
-
}
|
|
18
|
+
};
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return children.every((child) => isValidElement(child));
|
|
23
|
-
}
|
|
20
|
+
const hasValidReactChildren = (children) =>
|
|
21
|
+
Array.isArray(children) && children.every(isValidElement);
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
return Array.isArray(data) ? data : [data];
|
|
27
|
-
}
|
|
23
|
+
const getAsArray = (data) => (Array.isArray(data) ? data : [data]);
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
const mergeProps = (source, target) => {
|
|
30
26
|
const newTarget = { ...target };
|
|
31
27
|
// overwrite source.props when target.props already set
|
|
32
28
|
newTarget.props = Object.assign(source.props, target.props);
|
|
33
29
|
return newTarget;
|
|
34
|
-
}
|
|
30
|
+
};
|
|
35
31
|
|
|
36
|
-
export
|
|
32
|
+
export const nodesToString = (children, i18nOptions) => {
|
|
37
33
|
if (!children) return '';
|
|
38
34
|
let stringNode = '';
|
|
39
35
|
|
|
@@ -46,32 +42,35 @@ export function nodesToString(children, i18nOptions) {
|
|
|
46
42
|
|
|
47
43
|
// e.g. lorem <br/> ipsum {{ messageCount, format }} dolor <strong>bold</strong> amet
|
|
48
44
|
childrenArray.forEach((child, childIndex) => {
|
|
49
|
-
if (
|
|
45
|
+
if (isString(child)) {
|
|
50
46
|
// actual e.g. lorem
|
|
51
47
|
// expected e.g. lorem
|
|
52
48
|
stringNode += `${child}`;
|
|
53
49
|
} else if (isValidElement(child)) {
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
50
|
+
const { props, type } = child;
|
|
51
|
+
const childPropsCount = Object.keys(props).length;
|
|
52
|
+
const shouldKeepChild = keepArray.indexOf(type) > -1;
|
|
53
|
+
const childChildren = props.children;
|
|
57
54
|
|
|
58
|
-
if (!childChildren && shouldKeepChild && childPropsCount
|
|
55
|
+
if (!childChildren && shouldKeepChild && !childPropsCount) {
|
|
59
56
|
// actual e.g. lorem <br/> ipsum
|
|
60
57
|
// expected e.g. lorem <br/> ipsum
|
|
61
|
-
stringNode += `<${
|
|
62
|
-
} else if (
|
|
58
|
+
stringNode += `<${type}/>`;
|
|
59
|
+
} else if (
|
|
60
|
+
(!childChildren && (!shouldKeepChild || childPropsCount)) ||
|
|
61
|
+
props.i18nIsDynamicList
|
|
62
|
+
) {
|
|
63
63
|
// actual e.g. lorem <hr className="test" /> ipsum
|
|
64
64
|
// expected e.g. lorem <0></0> ipsum
|
|
65
|
-
|
|
66
|
-
} else if (child.props.i18nIsDynamicList) {
|
|
65
|
+
// or
|
|
67
66
|
// we got a dynamic list like
|
|
68
67
|
// e.g. <ul i18nIsDynamicList>{['a', 'b'].map(item => ( <li key={item}>{item}</li> ))}</ul>
|
|
69
68
|
// expected e.g. "<0></0>", not e.g. "<0><0>a</0><1>b</1></0>"
|
|
70
69
|
stringNode += `<${childIndex}></${childIndex}>`;
|
|
71
|
-
} else if (shouldKeepChild && childPropsCount === 1 &&
|
|
70
|
+
} else if (shouldKeepChild && childPropsCount === 1 && isString(childChildren)) {
|
|
72
71
|
// actual e.g. dolor <strong>bold</strong> amet
|
|
73
72
|
// expected e.g. dolor <strong>bold</strong> amet
|
|
74
|
-
stringNode += `<${
|
|
73
|
+
stringNode += `<${type}>${childChildren}</${type}>`;
|
|
75
74
|
} else {
|
|
76
75
|
// regular case mapping the inner children
|
|
77
76
|
const content = nodesToString(childChildren, i18nOptions);
|
|
@@ -79,7 +78,7 @@ export function nodesToString(children, i18nOptions) {
|
|
|
79
78
|
}
|
|
80
79
|
} else if (child === null) {
|
|
81
80
|
warn(`Trans: the passed in value is invalid - seems you passed in a null child.`);
|
|
82
|
-
} else if (
|
|
81
|
+
} else if (isObject(child)) {
|
|
83
82
|
// e.g. lorem {{ value, format }} ipsum
|
|
84
83
|
const { format, ...clone } = child;
|
|
85
84
|
const keys = Object.keys(clone);
|
|
@@ -103,9 +102,9 @@ export function nodesToString(children, i18nOptions) {
|
|
|
103
102
|
});
|
|
104
103
|
|
|
105
104
|
return stringNode;
|
|
106
|
-
}
|
|
105
|
+
};
|
|
107
106
|
|
|
108
|
-
|
|
107
|
+
const renderNodes = (children, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
|
|
109
108
|
if (targetString === '') return [];
|
|
110
109
|
|
|
111
110
|
// check if contains tags we need to replace from html string to react nodes
|
|
@@ -119,15 +118,15 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
|
|
|
119
118
|
// v2 -> interpolates upfront no need for "some <0>{{var}}</0>"" -> will be just "some {{var}}" in translation file
|
|
120
119
|
const data = {};
|
|
121
120
|
|
|
122
|
-
|
|
121
|
+
const getData = (childs) => {
|
|
123
122
|
const childrenArray = getAsArray(childs);
|
|
124
123
|
|
|
125
124
|
childrenArray.forEach((child) => {
|
|
126
|
-
if (
|
|
125
|
+
if (isString(child)) return;
|
|
127
126
|
if (hasChildren(child)) getData(getChildren(child));
|
|
128
|
-
else if (
|
|
127
|
+
else if (isObject(child) && !isValidElement(child)) Object.assign(data, child);
|
|
129
128
|
});
|
|
130
|
-
}
|
|
129
|
+
};
|
|
131
130
|
|
|
132
131
|
getData(children);
|
|
133
132
|
|
|
@@ -136,7 +135,7 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
|
|
|
136
135
|
const ast = HTML.parse(`<0>${targetString}</0>`);
|
|
137
136
|
const opts = { ...data, ...combinedTOpts };
|
|
138
137
|
|
|
139
|
-
|
|
138
|
+
const renderInner = (child, node, rootReactNode) => {
|
|
140
139
|
const childs = getChildren(child);
|
|
141
140
|
const mappedChildren = mapAST(childs, node.children, rootReactNode);
|
|
142
141
|
// `mappedChildren` will always be empty if using the `i18nIsDynamicList` prop,
|
|
@@ -145,9 +144,9 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
|
|
|
145
144
|
(child.props && child.props.i18nIsDynamicList)
|
|
146
145
|
? childs
|
|
147
146
|
: mappedChildren;
|
|
148
|
-
}
|
|
147
|
+
};
|
|
149
148
|
|
|
150
|
-
|
|
149
|
+
const pushTranslatedJSX = (child, inner, mem, i, isVoid) => {
|
|
151
150
|
if (child.dummy) {
|
|
152
151
|
child.children = inner; // needed on preact!
|
|
153
152
|
mem.push(cloneElement(child, { key: i }, isVoid ? undefined : inner));
|
|
@@ -169,12 +168,12 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
|
|
|
169
168
|
}),
|
|
170
169
|
);
|
|
171
170
|
}
|
|
172
|
-
}
|
|
171
|
+
};
|
|
173
172
|
|
|
174
173
|
// reactNode (the jsx root element or child)
|
|
175
174
|
// astNode (the translation string as html ast)
|
|
176
175
|
// rootReactNode (the most outer jsx children array or trans components prop)
|
|
177
|
-
|
|
176
|
+
const mapAST = (reactNode, astNode, rootReactNode) => {
|
|
178
177
|
const reactNodes = getAsArray(reactNode);
|
|
179
178
|
const astNodes = getAsArray(astNode);
|
|
180
179
|
|
|
@@ -204,14 +203,12 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
|
|
|
204
203
|
isElement && hasChildren(node, true) && !node.voidElement;
|
|
205
204
|
|
|
206
205
|
const isEmptyTransWithHTML =
|
|
207
|
-
emptyChildrenButNeedsHandling &&
|
|
206
|
+
emptyChildrenButNeedsHandling && isObject(child) && child.dummy && !isElement;
|
|
208
207
|
|
|
209
208
|
const isKnownComponent =
|
|
210
|
-
|
|
211
|
-
children !== null &&
|
|
212
|
-
Object.hasOwnProperty.call(children, node.name);
|
|
209
|
+
isObject(children) && Object.hasOwnProperty.call(children, node.name);
|
|
213
210
|
|
|
214
|
-
if (
|
|
211
|
+
if (isString(child)) {
|
|
215
212
|
const value = i18n.services.interpolator.interpolate(child, opts, i18n.language);
|
|
216
213
|
mem.push(value);
|
|
217
214
|
} else if (
|
|
@@ -257,7 +254,7 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
|
|
|
257
254
|
|
|
258
255
|
mem.push(`<${node.name}>${inner}</${node.name}>`);
|
|
259
256
|
}
|
|
260
|
-
} else if (
|
|
257
|
+
} else if (isObject(child) && !isElement) {
|
|
261
258
|
const content = node.children[0] ? translationContent : null;
|
|
262
259
|
|
|
263
260
|
// v1
|
|
@@ -291,7 +288,7 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
|
|
|
291
288
|
}
|
|
292
289
|
return mem;
|
|
293
290
|
}, []);
|
|
294
|
-
}
|
|
291
|
+
};
|
|
295
292
|
|
|
296
293
|
// call mapAST with having react nodes nested into additional node like
|
|
297
294
|
// we did for the string ast from translation
|
|
@@ -302,7 +299,7 @@ function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, s
|
|
|
302
299
|
getAsArray(children || []),
|
|
303
300
|
);
|
|
304
301
|
return getChildren(result[0]);
|
|
305
|
-
}
|
|
302
|
+
};
|
|
306
303
|
|
|
307
304
|
export function Trans({
|
|
308
305
|
children,
|
|
@@ -333,7 +330,7 @@ export function Trans({
|
|
|
333
330
|
|
|
334
331
|
// prepare having a namespace
|
|
335
332
|
let namespaces = ns || t.ns || (i18n.options && i18n.options.defaultNS);
|
|
336
|
-
namespaces =
|
|
333
|
+
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
|
337
334
|
|
|
338
335
|
const nodeAsString = nodesToString(children, reactI18nextOptions);
|
|
339
336
|
const defaultValue =
|
|
@@ -349,11 +346,16 @@ export function Trans({
|
|
|
349
346
|
? { ...values, ...i18n.options.interpolation.defaultVariables }
|
|
350
347
|
: { ...i18n.options.interpolation.defaultVariables };
|
|
351
348
|
}
|
|
349
|
+
const interpolationOverride =
|
|
350
|
+
values || count !== undefined || !children // if !children gets problems in future, undo that fix: https://github.com/i18next/react-i18next/issues/1729 by removing !children from this condition
|
|
351
|
+
? tOptions.interpolation
|
|
352
|
+
: { interpolation: { ...tOptions.interpolation, prefix: '#$?', suffix: '?$#' } };
|
|
352
353
|
const combinedTOpts = {
|
|
353
354
|
...tOptions,
|
|
354
355
|
context: context || tOptions.context, // Add `context` from the props or fallback to the value from `tOptions`
|
|
355
356
|
count,
|
|
356
357
|
...values,
|
|
358
|
+
...interpolationOverride,
|
|
357
359
|
defaultValue,
|
|
358
360
|
ns: namespaces,
|
|
359
361
|
};
|
package/src/context.js
CHANGED
|
@@ -18,44 +18,23 @@ export class ReportNamespaces {
|
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
getUsedNamespaces()
|
|
22
|
-
return Object.keys(this.usedNamespaces);
|
|
23
|
-
}
|
|
21
|
+
getUsedNamespaces = () => Object.keys(this.usedNamespaces);
|
|
24
22
|
}
|
|
25
23
|
|
|
26
|
-
export
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (ForComponent.getInitialProps) {
|
|
32
|
-
ForComponent.getInitialProps(ctx).then((componentsInitialProps) => {
|
|
33
|
-
resolve({
|
|
34
|
-
...componentsInitialProps,
|
|
35
|
-
...i18nInitialProps,
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
} else {
|
|
39
|
-
resolve(i18nInitialProps);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
// Avoid async for now - so we do not need to pull in regenerator
|
|
43
|
-
|
|
44
|
-
// return async ctx => {
|
|
45
|
-
// const componentsInitialProps = ForComponent.getInitialProps
|
|
46
|
-
// ? await ForComponent.getInitialProps(ctx)
|
|
47
|
-
// : {};
|
|
24
|
+
export const composeInitialProps = (ForComponent) => async (ctx) => {
|
|
25
|
+
const componentsInitialProps = ForComponent.getInitialProps
|
|
26
|
+
? await ForComponent.getInitialProps(ctx)
|
|
27
|
+
: {};
|
|
48
28
|
|
|
49
|
-
|
|
29
|
+
const i18nInitialProps = getInitialProps();
|
|
50
30
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
31
|
+
return {
|
|
32
|
+
...componentsInitialProps,
|
|
33
|
+
...i18nInitialProps,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
57
36
|
|
|
58
|
-
export
|
|
37
|
+
export const getInitialProps = () => {
|
|
59
38
|
const i18n = getI18n();
|
|
60
39
|
const namespaces = i18n.reportNamespaces ? i18n.reportNamespaces.getUsedNamespaces() : [];
|
|
61
40
|
|
|
@@ -72,4 +51,4 @@ export function getInitialProps() {
|
|
|
72
51
|
ret.initialLanguage = i18n.language;
|
|
73
52
|
|
|
74
53
|
return ret;
|
|
75
|
-
}
|
|
54
|
+
};
|
package/src/defaults.js
CHANGED
|
@@ -13,10 +13,8 @@ let defaultOptions = {
|
|
|
13
13
|
unescape,
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
export
|
|
16
|
+
export const setDefaults = (options = {}) => {
|
|
17
17
|
defaultOptions = { ...defaultOptions, ...options };
|
|
18
|
-
}
|
|
18
|
+
};
|
|
19
19
|
|
|
20
|
-
export
|
|
21
|
-
return defaultOptions;
|
|
22
|
-
}
|
|
20
|
+
export const getDefaults = () => defaultOptions;
|
package/src/i18nInstance.js
CHANGED
package/src/useSSR.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useContext } from 'react';
|
|
2
2
|
import { getI18n, I18nContext } from './context.js';
|
|
3
3
|
|
|
4
|
-
export
|
|
4
|
+
export const useSSR = (initialI18nStore, initialLanguage, props = {}) => {
|
|
5
5
|
const { i18n: i18nFromProps } = props;
|
|
6
6
|
const { i18n: i18nFromContext } = useContext(I18nContext) || {};
|
|
7
7
|
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
|
@@ -30,4 +30,4 @@ export function useSSR(initialI18nStore, initialLanguage, props = {}) {
|
|
|
30
30
|
i18n.changeLanguage(initialLanguage);
|
|
31
31
|
i18n.initializedLanguageOnce = true;
|
|
32
32
|
}
|
|
33
|
-
}
|
|
33
|
+
};
|
package/src/useTranslation.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { useState, useEffect, useContext, useRef, useCallback } from 'react';
|
|
2
2
|
import { getI18n, getDefaults, ReportNamespaces, I18nContext } from './context.js';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
warnOnce,
|
|
5
|
+
loadNamespaces,
|
|
6
|
+
loadLanguages,
|
|
7
|
+
hasLoadedNamespace,
|
|
8
|
+
isString,
|
|
9
|
+
isObject,
|
|
10
|
+
} from './utils.js';
|
|
4
11
|
|
|
5
12
|
const usePrevious = (value, ignore) => {
|
|
6
13
|
const ref = useRef();
|
|
@@ -10,20 +17,18 @@ const usePrevious = (value, ignore) => {
|
|
|
10
17
|
return ref.current;
|
|
11
18
|
};
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
20
|
+
const alwaysNewT = (i18n, language, namespace, keyPrefix) =>
|
|
21
|
+
i18n.getFixedT(language, namespace, keyPrefix);
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
const useMemoizedT = (i18n, language, namespace, keyPrefix) =>
|
|
24
|
+
useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [
|
|
19
25
|
i18n,
|
|
20
26
|
language,
|
|
21
27
|
namespace,
|
|
22
28
|
keyPrefix,
|
|
23
29
|
]);
|
|
24
|
-
}
|
|
25
30
|
|
|
26
|
-
export
|
|
31
|
+
export const useTranslation = (ns, props = {}) => {
|
|
27
32
|
// assert we have the needed i18nInstance
|
|
28
33
|
const { i18n: i18nFromProps } = props;
|
|
29
34
|
const { i18n: i18nFromContext, defaultNS: defaultNSFromContext } = useContext(I18nContext) || {};
|
|
@@ -32,12 +37,8 @@ export function useTranslation(ns, props = {}) {
|
|
|
32
37
|
if (!i18n) {
|
|
33
38
|
warnOnce('You will need to pass in an i18next instance by using initReactI18next');
|
|
34
39
|
const notReadyT = (k, optsOrDefaultValue) => {
|
|
35
|
-
if (
|
|
36
|
-
if (
|
|
37
|
-
optsOrDefaultValue &&
|
|
38
|
-
typeof optsOrDefaultValue === 'object' &&
|
|
39
|
-
typeof optsOrDefaultValue.defaultValue === 'string'
|
|
40
|
-
)
|
|
40
|
+
if (isString(optsOrDefaultValue)) return optsOrDefaultValue;
|
|
41
|
+
if (isObject(optsOrDefaultValue) && isString(optsOrDefaultValue.defaultValue))
|
|
41
42
|
return optsOrDefaultValue.defaultValue;
|
|
42
43
|
return Array.isArray(k) ? k[k.length - 1] : k;
|
|
43
44
|
};
|
|
@@ -58,7 +59,7 @@ export function useTranslation(ns, props = {}) {
|
|
|
58
59
|
|
|
59
60
|
// prepare having a namespace
|
|
60
61
|
let namespaces = ns || defaultNSFromContext || (i18n.options && i18n.options.defaultNS);
|
|
61
|
-
namespaces =
|
|
62
|
+
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
|
62
63
|
|
|
63
64
|
// report namespaces as used
|
|
64
65
|
if (i18n.reportNamespaces.addUsedNamespaces) i18n.reportNamespaces.addUsedNamespaces(namespaces);
|
|
@@ -114,9 +115,9 @@ export function useTranslation(ns, props = {}) {
|
|
|
114
115
|
setT(getNewT);
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
|
|
118
|
+
const boundReset = () => {
|
|
118
119
|
if (isMounted.current) setT(getNewT);
|
|
119
|
-
}
|
|
120
|
+
};
|
|
120
121
|
|
|
121
122
|
// bind events to trigger change, like languageChanged
|
|
122
123
|
if (bindI18n && i18n) i18n.on(bindI18n, boundReset);
|
|
@@ -161,4 +162,4 @@ export function useTranslation(ns, props = {}) {
|
|
|
161
162
|
loadNamespaces(i18n, namespaces, () => resolve());
|
|
162
163
|
}
|
|
163
164
|
});
|
|
164
|
-
}
|
|
165
|
+
};
|
package/src/utils.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
// Do not use arrow function here as it will break optimizations of arguments
|
|
1
2
|
export function warn(...args) {
|
|
2
3
|
if (console && console.warn) {
|
|
3
|
-
if (
|
|
4
|
+
if (isString(args[0])) args[0] = `react-i18next:: ${args[0]}`;
|
|
4
5
|
console.warn(...args);
|
|
5
6
|
}
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
const alreadyWarned = {};
|
|
10
|
+
// Do not use arrow function here as it will break optimizations of arguments
|
|
9
11
|
export function warnOnce(...args) {
|
|
10
|
-
if (
|
|
11
|
-
if (
|
|
12
|
+
if (isString(args[0]) && alreadyWarned[args[0]]) return;
|
|
13
|
+
if (isString(args[0])) alreadyWarned[args[0]] = new Date();
|
|
12
14
|
warn(...args);
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -16,7 +18,7 @@ export function warnOnce(...args) {
|
|
|
16
18
|
//
|
|
17
19
|
// export function deprecated(...args) {
|
|
18
20
|
// if (process && process.env && (!process.env.NODE_ENV || process.env.NODE_ENV === 'development')) {
|
|
19
|
-
// if (
|
|
21
|
+
// if (isString(args[0])) args[0] = `deprecation warning -> ${args[0]}`;
|
|
20
22
|
// warnOnce(...args);
|
|
21
23
|
// }
|
|
22
24
|
// }
|
|
@@ -37,22 +39,22 @@ const loadedClb = (i18n, cb) => () => {
|
|
|
37
39
|
}
|
|
38
40
|
};
|
|
39
41
|
|
|
40
|
-
export
|
|
42
|
+
export const loadNamespaces = (i18n, ns, cb) => {
|
|
41
43
|
i18n.loadNamespaces(ns, loadedClb(i18n, cb));
|
|
42
|
-
}
|
|
44
|
+
};
|
|
43
45
|
|
|
44
46
|
// should work with I18NEXT >= v22.5.0
|
|
45
|
-
export
|
|
47
|
+
export const loadLanguages = (i18n, lng, ns, cb) => {
|
|
46
48
|
// eslint-disable-next-line no-param-reassign
|
|
47
|
-
if (
|
|
49
|
+
if (isString(ns)) ns = [ns];
|
|
48
50
|
ns.forEach((n) => {
|
|
49
51
|
if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
|
|
50
52
|
});
|
|
51
53
|
i18n.loadLanguages(lng, loadedClb(i18n, cb));
|
|
52
|
-
}
|
|
54
|
+
};
|
|
53
55
|
|
|
54
56
|
// WAIT A LITTLE FOR I18NEXT BEING UPDATED IN THE WILD, before removing this old i18next version support
|
|
55
|
-
|
|
57
|
+
const oldI18nextHasLoadedNamespace = (ns, i18n, options = {}) => {
|
|
56
58
|
const lng = i18n.languages[0];
|
|
57
59
|
const fallbackLng = i18n.options ? i18n.options.fallbackLng : false;
|
|
58
60
|
const lastLng = i18n.languages[i18n.languages.length - 1];
|
|
@@ -91,9 +93,9 @@ function oldI18nextHasLoadedNamespace(ns, i18n, options = {}) {
|
|
|
91
93
|
if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true;
|
|
92
94
|
|
|
93
95
|
return false;
|
|
94
|
-
}
|
|
96
|
+
};
|
|
95
97
|
|
|
96
|
-
export
|
|
98
|
+
export const hasLoadedNamespace = (ns, i18n, options = {}) => {
|
|
97
99
|
if (!i18n.languages || !i18n.languages.length) {
|
|
98
100
|
warnOnce('i18n.languages were undefined or empty', i18n.languages);
|
|
99
101
|
return true;
|
|
@@ -120,12 +122,13 @@ export function hasLoadedNamespace(ns, i18n, options = {}) {
|
|
|
120
122
|
return false;
|
|
121
123
|
},
|
|
122
124
|
});
|
|
123
|
-
}
|
|
125
|
+
};
|
|
124
126
|
|
|
125
|
-
export
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
127
|
+
export const getDisplayName = (Component) =>
|
|
128
|
+
Component.displayName ||
|
|
129
|
+
Component.name ||
|
|
130
|
+
(isString(Component) && Component.length > 0 ? Component : 'Unknown');
|
|
131
|
+
|
|
132
|
+
export const isString = (obj) => typeof obj === 'string';
|
|
133
|
+
|
|
134
|
+
export const isObject = (obj) => typeof obj === 'object' && obj !== null;
|
package/src/withSSR.js
CHANGED
|
@@ -3,8 +3,8 @@ import { useSSR } from './useSSR.js';
|
|
|
3
3
|
import { composeInitialProps } from './context.js';
|
|
4
4
|
import { getDisplayName } from './utils.js';
|
|
5
5
|
|
|
6
|
-
export
|
|
7
|
-
|
|
6
|
+
export const withSSR = () =>
|
|
7
|
+
function Extend(WrappedComponent) {
|
|
8
8
|
function I18nextWithSSR({ initialI18nStore, initialLanguage, ...rest }) {
|
|
9
9
|
useSSR(initialI18nStore, initialLanguage);
|
|
10
10
|
|
|
@@ -19,4 +19,3 @@ export function withSSR() {
|
|
|
19
19
|
|
|
20
20
|
return I18nextWithSSR;
|
|
21
21
|
};
|
|
22
|
-
}
|
package/src/withTranslation.js
CHANGED
|
@@ -2,8 +2,8 @@ import { createElement, forwardRef as forwardRefReact } from 'react';
|
|
|
2
2
|
import { useTranslation } from './useTranslation.js';
|
|
3
3
|
import { getDisplayName } from './utils.js';
|
|
4
4
|
|
|
5
|
-
export
|
|
6
|
-
|
|
5
|
+
export const withTranslation = (ns, options = {}) =>
|
|
6
|
+
function Extend(WrappedComponent) {
|
|
7
7
|
function I18nextWithTranslation({ forwardedRef, ...rest }) {
|
|
8
8
|
const [t, i18n, ready] = useTranslation(ns, { ...rest, keyPrefix: options.keyPrefix });
|
|
9
9
|
|
|
@@ -33,4 +33,3 @@ export function withTranslation(ns, options = {}) {
|
|
|
33
33
|
|
|
34
34
|
return options.withRef ? forwardRefReact(forwardRef) : I18nextWithTranslation;
|
|
35
35
|
};
|
|
36
|
-
}
|