react-i18next 16.0.1 → 16.1.1
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 +8 -0
- package/dist/amd/react-i18next.js +486 -32
- package/dist/amd/react-i18next.min.js +1 -1
- package/dist/commonjs/IcuTrans.js +35 -0
- package/dist/commonjs/IcuTransUtils/TranslationParserError.js +18 -0
- package/dist/commonjs/IcuTransUtils/htmlEntityDecoder.js +218 -0
- package/dist/commonjs/IcuTransUtils/index.js +49 -0
- package/dist/commonjs/IcuTransUtils/renderTranslation.js +114 -0
- package/dist/commonjs/IcuTransUtils/tokenizer.js +58 -0
- package/dist/commonjs/IcuTransWithoutContext.js +56 -0
- package/dist/commonjs/index.js +14 -0
- package/dist/es/IcuTrans.js +29 -0
- package/dist/es/IcuTransUtils/TranslationParserError.js +11 -0
- package/dist/es/IcuTransUtils/htmlEntityDecoder.js +211 -0
- package/dist/es/IcuTransUtils/index.js +4 -0
- package/dist/es/IcuTransUtils/renderTranslation.js +106 -0
- package/dist/es/IcuTransUtils/tokenizer.js +51 -0
- package/dist/es/IcuTransWithoutContext.js +49 -0
- package/dist/es/index.js +2 -0
- package/dist/es/package.json +1 -1
- package/dist/umd/react-i18next.js +486 -32
- package/dist/umd/react-i18next.min.js +1 -1
- package/icu.macro.js +170 -48
- package/index.d.ts +107 -0
- package/package.json +6 -3
- package/react-i18next.js +486 -32
- package/react-i18next.min.js +1 -1
- package/src/IcuTrans.js +103 -0
- package/src/IcuTransUtils/TranslationParserError.js +24 -0
- package/src/IcuTransUtils/htmlEntityDecoder.js +264 -0
- package/src/IcuTransUtils/index.js +4 -0
- package/src/IcuTransUtils/renderTranslation.js +215 -0
- package/src/IcuTransUtils/tokenizer.js +78 -0
- package/src/IcuTransWithoutContext.js +146 -0
- package/src/index.js +2 -0
package/react-i18next.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
|
|
3
3
|
typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactI18next = {}, global.React));
|
|
5
|
-
})(this, (function (exports,
|
|
5
|
+
})(this, (function (exports, React) { 'use strict';
|
|
6
6
|
|
|
7
7
|
const isString$1 = obj => typeof obj === 'string';
|
|
8
8
|
const defer = () => {
|
|
@@ -2426,7 +2426,7 @@
|
|
|
2426
2426
|
const children = node.props?.children ?? node.children;
|
|
2427
2427
|
return node.props?.i18nIsDynamicList ? getAsArray(children) : children;
|
|
2428
2428
|
};
|
|
2429
|
-
const hasValidReactChildren = children => Array.isArray(children) && children.every(
|
|
2429
|
+
const hasValidReactChildren = children => Array.isArray(children) && children.every(React.isValidElement);
|
|
2430
2430
|
const getAsArray = data => Array.isArray(data) ? data : [data];
|
|
2431
2431
|
const mergeProps = (source, target) => {
|
|
2432
2432
|
const newTarget = {
|
|
@@ -2445,7 +2445,7 @@
|
|
|
2445
2445
|
stringNode += `${child}`;
|
|
2446
2446
|
return;
|
|
2447
2447
|
}
|
|
2448
|
-
if (
|
|
2448
|
+
if (React.isValidElement(child)) {
|
|
2449
2449
|
const {
|
|
2450
2450
|
props,
|
|
2451
2451
|
type
|
|
@@ -2509,7 +2509,7 @@
|
|
|
2509
2509
|
const childrenArray = getAsArray(childs);
|
|
2510
2510
|
childrenArray.forEach(child => {
|
|
2511
2511
|
if (isString(child)) return;
|
|
2512
|
-
if (hasChildren(child)) getData(getChildren(child));else if (isObject(child) && !
|
|
2512
|
+
if (hasChildren(child)) getData(getChildren(child));else if (isObject(child) && !React.isValidElement(child)) Object.assign(data, child);
|
|
2513
2513
|
});
|
|
2514
2514
|
};
|
|
2515
2515
|
getData(children);
|
|
@@ -2526,16 +2526,16 @@
|
|
|
2526
2526
|
const pushTranslatedJSX = (child, inner, mem, i, isVoid) => {
|
|
2527
2527
|
if (child.dummy) {
|
|
2528
2528
|
child.children = inner;
|
|
2529
|
-
mem.push(
|
|
2529
|
+
mem.push(React.cloneElement(child, {
|
|
2530
2530
|
key: i
|
|
2531
2531
|
}, isVoid ? undefined : inner));
|
|
2532
2532
|
} else {
|
|
2533
|
-
mem.push(...
|
|
2533
|
+
mem.push(...React.Children.map([child], c => {
|
|
2534
2534
|
const props = {
|
|
2535
2535
|
...c.props
|
|
2536
2536
|
};
|
|
2537
2537
|
delete props.i18nIsDynamicList;
|
|
2538
|
-
return
|
|
2538
|
+
return React.createElement(c.type, {
|
|
2539
2539
|
...props,
|
|
2540
2540
|
key: i,
|
|
2541
2541
|
ref: c.props.ref ?? c.ref
|
|
@@ -2556,7 +2556,7 @@
|
|
|
2556
2556
|
const child = Object.keys(node.attrs).length !== 0 ? mergeProps({
|
|
2557
2557
|
props: node.attrs
|
|
2558
2558
|
}, tmp) : tmp;
|
|
2559
|
-
const isElement =
|
|
2559
|
+
const isElement = React.isValidElement(child);
|
|
2560
2560
|
const isValidTranslationWithChildren = isElement && hasChildren(node, true) && !node.voidElement;
|
|
2561
2561
|
const isEmptyTransWithHTML = emptyChildrenButNeedsHandling && isObject(child) && child.dummy && !isElement;
|
|
2562
2562
|
const isKnownComponent = isObject(knownComponentsMap) && Object.hasOwnProperty.call(knownComponentsMap, node.name);
|
|
@@ -2575,12 +2575,12 @@
|
|
|
2575
2575
|
pushTranslatedJSX(child, inner, mem, i, node.voidElement);
|
|
2576
2576
|
} else if (i18nOptions.transSupportBasicHtmlNodes && keepArray.indexOf(node.name) > -1) {
|
|
2577
2577
|
if (node.voidElement) {
|
|
2578
|
-
mem.push(
|
|
2578
|
+
mem.push(React.createElement(node.name, {
|
|
2579
2579
|
key: `${node.name}-${i}`
|
|
2580
2580
|
}));
|
|
2581
2581
|
} else {
|
|
2582
2582
|
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
|
2583
|
-
mem.push(
|
|
2583
|
+
mem.push(React.createElement(node.name, {
|
|
2584
2584
|
key: `${node.name}-${i}`
|
|
2585
2585
|
}, inner));
|
|
2586
2586
|
}
|
|
@@ -2600,7 +2600,7 @@
|
|
|
2600
2600
|
const wrapTextNodes = i18nOptions.transWrapTextNodes;
|
|
2601
2601
|
const content = shouldUnescape ? i18nOptions.unescape(i18n.services.interpolator.interpolate(node.content, opts, i18n.language)) : i18n.services.interpolator.interpolate(node.content, opts, i18n.language);
|
|
2602
2602
|
if (wrapTextNodes) {
|
|
2603
|
-
mem.push(
|
|
2603
|
+
mem.push(React.createElement(wrapTextNodes, {
|
|
2604
2604
|
key: `${node.name}-${i}`
|
|
2605
2605
|
}, content));
|
|
2606
2606
|
} else {
|
|
@@ -2618,16 +2618,16 @@
|
|
|
2618
2618
|
};
|
|
2619
2619
|
const fixComponentProps = (component, index, translation) => {
|
|
2620
2620
|
const componentKey = component.key || index;
|
|
2621
|
-
const comp =
|
|
2621
|
+
const comp = React.cloneElement(component, {
|
|
2622
2622
|
key: componentKey
|
|
2623
2623
|
});
|
|
2624
2624
|
if (!comp.props || !comp.props.children || translation.indexOf(`${index}/>`) < 0 && translation.indexOf(`${index} />`) < 0) {
|
|
2625
2625
|
return comp;
|
|
2626
2626
|
}
|
|
2627
2627
|
function Componentized() {
|
|
2628
|
-
return
|
|
2628
|
+
return React.createElement(React.Fragment, null, comp);
|
|
2629
2629
|
}
|
|
2630
|
-
return
|
|
2630
|
+
return React.createElement(Componentized, {
|
|
2631
2631
|
key: componentKey
|
|
2632
2632
|
});
|
|
2633
2633
|
};
|
|
@@ -2729,7 +2729,7 @@
|
|
|
2729
2729
|
}
|
|
2730
2730
|
const content = renderNodes(indexedChildren, componentsMap, translation, i18n, reactI18nextOptions, combinedTOpts, shouldUnescape);
|
|
2731
2731
|
const useAsParent = parent ?? reactI18nextOptions.defaultTransParent;
|
|
2732
|
-
return useAsParent ?
|
|
2732
|
+
return useAsParent ? React.createElement(useAsParent, additionalProps, content) : content;
|
|
2733
2733
|
}
|
|
2734
2734
|
|
|
2735
2735
|
const initReactI18next = {
|
|
@@ -2740,7 +2740,7 @@
|
|
|
2740
2740
|
}
|
|
2741
2741
|
};
|
|
2742
2742
|
|
|
2743
|
-
const I18nContext =
|
|
2743
|
+
const I18nContext = React.createContext();
|
|
2744
2744
|
class ReportNamespaces {
|
|
2745
2745
|
constructor() {
|
|
2746
2746
|
this.usedNamespaces = {};
|
|
@@ -2797,7 +2797,7 @@
|
|
|
2797
2797
|
const {
|
|
2798
2798
|
i18n: i18nFromContext,
|
|
2799
2799
|
defaultNS: defaultNSFromContext
|
|
2800
|
-
} =
|
|
2800
|
+
} = React.useContext(I18nContext) || {};
|
|
2801
2801
|
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
|
2802
2802
|
const t = tFromProps || i18n?.t.bind(i18n);
|
|
2803
2803
|
return Trans$1({
|
|
@@ -2818,15 +2818,467 @@
|
|
|
2818
2818
|
});
|
|
2819
2819
|
}
|
|
2820
2820
|
|
|
2821
|
+
class TranslationParserError extends Error {
|
|
2822
|
+
constructor(message, position, translationString) {
|
|
2823
|
+
super(message);
|
|
2824
|
+
this.name = 'TranslationParserError';
|
|
2825
|
+
this.position = position;
|
|
2826
|
+
this.translationString = translationString;
|
|
2827
|
+
if (Error.captureStackTrace) {
|
|
2828
|
+
Error.captureStackTrace(this, TranslationParserError);
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
|
|
2833
|
+
const commonEntities = {
|
|
2834
|
+
' ': '\u00A0',
|
|
2835
|
+
'&': '&',
|
|
2836
|
+
'<': '<',
|
|
2837
|
+
'>': '>',
|
|
2838
|
+
'"': '"',
|
|
2839
|
+
''': "'",
|
|
2840
|
+
'©': '©',
|
|
2841
|
+
'®': '®',
|
|
2842
|
+
'™': '™',
|
|
2843
|
+
'…': '…',
|
|
2844
|
+
'–': '–',
|
|
2845
|
+
'—': '—',
|
|
2846
|
+
'‘': '\u2018',
|
|
2847
|
+
'’': '\u2019',
|
|
2848
|
+
'‚': '\u201A',
|
|
2849
|
+
'“': '\u201C',
|
|
2850
|
+
'”': '\u201D',
|
|
2851
|
+
'„': '\u201E',
|
|
2852
|
+
'†': '†',
|
|
2853
|
+
'‡': '‡',
|
|
2854
|
+
'•': '•',
|
|
2855
|
+
'′': '′',
|
|
2856
|
+
'″': '″',
|
|
2857
|
+
'‹': '‹',
|
|
2858
|
+
'›': '›',
|
|
2859
|
+
'§': '§',
|
|
2860
|
+
'¶': '¶',
|
|
2861
|
+
'·': '·',
|
|
2862
|
+
' ': '\u2002',
|
|
2863
|
+
' ': '\u2003',
|
|
2864
|
+
' ': '\u2009',
|
|
2865
|
+
'€': '€',
|
|
2866
|
+
'£': '£',
|
|
2867
|
+
'¥': '¥',
|
|
2868
|
+
'¢': '¢',
|
|
2869
|
+
'¤': '¤',
|
|
2870
|
+
'×': '×',
|
|
2871
|
+
'÷': '÷',
|
|
2872
|
+
'−': '−',
|
|
2873
|
+
'±': '±',
|
|
2874
|
+
'≠': '≠',
|
|
2875
|
+
'≤': '≤',
|
|
2876
|
+
'≥': '≥',
|
|
2877
|
+
'≈': '≈',
|
|
2878
|
+
'≡': '≡',
|
|
2879
|
+
'∞': '∞',
|
|
2880
|
+
'∫': '∫',
|
|
2881
|
+
'∑': '∑',
|
|
2882
|
+
'∏': '∏',
|
|
2883
|
+
'√': '√',
|
|
2884
|
+
'∂': '∂',
|
|
2885
|
+
'‰': '‰',
|
|
2886
|
+
'°': '°',
|
|
2887
|
+
'µ': 'µ',
|
|
2888
|
+
'←': '←',
|
|
2889
|
+
'↑': '↑',
|
|
2890
|
+
'→': '→',
|
|
2891
|
+
'↓': '↓',
|
|
2892
|
+
'↔': '↔',
|
|
2893
|
+
'↵': '↵',
|
|
2894
|
+
'⇐': '⇐',
|
|
2895
|
+
'⇑': '⇑',
|
|
2896
|
+
'⇒': '⇒',
|
|
2897
|
+
'⇓': '⇓',
|
|
2898
|
+
'⇔': '⇔',
|
|
2899
|
+
'α': 'α',
|
|
2900
|
+
'β': 'β',
|
|
2901
|
+
'γ': 'γ',
|
|
2902
|
+
'δ': 'δ',
|
|
2903
|
+
'ε': 'ε',
|
|
2904
|
+
'ζ': 'ζ',
|
|
2905
|
+
'η': 'η',
|
|
2906
|
+
'θ': 'θ',
|
|
2907
|
+
'ι': 'ι',
|
|
2908
|
+
'κ': 'κ',
|
|
2909
|
+
'λ': 'λ',
|
|
2910
|
+
'μ': 'μ',
|
|
2911
|
+
'ν': 'ν',
|
|
2912
|
+
'ξ': 'ξ',
|
|
2913
|
+
'ο': 'ο',
|
|
2914
|
+
'π': 'π',
|
|
2915
|
+
'ρ': 'ρ',
|
|
2916
|
+
'σ': 'σ',
|
|
2917
|
+
'τ': 'τ',
|
|
2918
|
+
'υ': 'υ',
|
|
2919
|
+
'φ': 'φ',
|
|
2920
|
+
'χ': 'χ',
|
|
2921
|
+
'ψ': 'ψ',
|
|
2922
|
+
'ω': 'ω',
|
|
2923
|
+
'Α': 'Α',
|
|
2924
|
+
'Β': 'Β',
|
|
2925
|
+
'Γ': 'Γ',
|
|
2926
|
+
'Δ': 'Δ',
|
|
2927
|
+
'Ε': 'Ε',
|
|
2928
|
+
'Ζ': 'Ζ',
|
|
2929
|
+
'Η': 'Η',
|
|
2930
|
+
'Θ': 'Θ',
|
|
2931
|
+
'Ι': 'Ι',
|
|
2932
|
+
'Κ': 'Κ',
|
|
2933
|
+
'Λ': 'Λ',
|
|
2934
|
+
'Μ': 'Μ',
|
|
2935
|
+
'Ν': 'Ν',
|
|
2936
|
+
'Ξ': 'Ξ',
|
|
2937
|
+
'Ο': 'Ο',
|
|
2938
|
+
'Π': 'Π',
|
|
2939
|
+
'Ρ': 'Ρ',
|
|
2940
|
+
'Σ': 'Σ',
|
|
2941
|
+
'Τ': 'Τ',
|
|
2942
|
+
'Υ': 'Υ',
|
|
2943
|
+
'Φ': 'Φ',
|
|
2944
|
+
'Χ': 'Χ',
|
|
2945
|
+
'Ψ': 'Ψ',
|
|
2946
|
+
'Ω': 'Ω',
|
|
2947
|
+
'À': 'À',
|
|
2948
|
+
'Á': 'Á',
|
|
2949
|
+
'Â': 'Â',
|
|
2950
|
+
'Ã': 'Ã',
|
|
2951
|
+
'Ä': 'Ä',
|
|
2952
|
+
'Å': 'Å',
|
|
2953
|
+
'Æ': 'Æ',
|
|
2954
|
+
'Ç': 'Ç',
|
|
2955
|
+
'È': 'È',
|
|
2956
|
+
'É': 'É',
|
|
2957
|
+
'Ê': 'Ê',
|
|
2958
|
+
'Ë': 'Ë',
|
|
2959
|
+
'Ì': 'Ì',
|
|
2960
|
+
'Í': 'Í',
|
|
2961
|
+
'Î': 'Î',
|
|
2962
|
+
'Ï': 'Ï',
|
|
2963
|
+
'Ð': 'Ð',
|
|
2964
|
+
'Ñ': 'Ñ',
|
|
2965
|
+
'Ò': 'Ò',
|
|
2966
|
+
'Ó': 'Ó',
|
|
2967
|
+
'Ô': 'Ô',
|
|
2968
|
+
'Õ': 'Õ',
|
|
2969
|
+
'Ö': 'Ö',
|
|
2970
|
+
'Ø': 'Ø',
|
|
2971
|
+
'Ù': 'Ù',
|
|
2972
|
+
'Ú': 'Ú',
|
|
2973
|
+
'Û': 'Û',
|
|
2974
|
+
'Ü': 'Ü',
|
|
2975
|
+
'Ý': 'Ý',
|
|
2976
|
+
'Þ': 'Þ',
|
|
2977
|
+
'ß': 'ß',
|
|
2978
|
+
'à': 'à',
|
|
2979
|
+
'á': 'á',
|
|
2980
|
+
'â': 'â',
|
|
2981
|
+
'ã': 'ã',
|
|
2982
|
+
'ä': 'ä',
|
|
2983
|
+
'å': 'å',
|
|
2984
|
+
'æ': 'æ',
|
|
2985
|
+
'ç': 'ç',
|
|
2986
|
+
'è': 'è',
|
|
2987
|
+
'é': 'é',
|
|
2988
|
+
'ê': 'ê',
|
|
2989
|
+
'ë': 'ë',
|
|
2990
|
+
'ì': 'ì',
|
|
2991
|
+
'í': 'í',
|
|
2992
|
+
'î': 'î',
|
|
2993
|
+
'ï': 'ï',
|
|
2994
|
+
'ð': 'ð',
|
|
2995
|
+
'ñ': 'ñ',
|
|
2996
|
+
'ò': 'ò',
|
|
2997
|
+
'ó': 'ó',
|
|
2998
|
+
'ô': 'ô',
|
|
2999
|
+
'õ': 'õ',
|
|
3000
|
+
'ö': 'ö',
|
|
3001
|
+
'ø': 'ø',
|
|
3002
|
+
'ù': 'ù',
|
|
3003
|
+
'ú': 'ú',
|
|
3004
|
+
'û': 'û',
|
|
3005
|
+
'ü': 'ü',
|
|
3006
|
+
'ý': 'ý',
|
|
3007
|
+
'þ': 'þ',
|
|
3008
|
+
'ÿ': 'ÿ',
|
|
3009
|
+
'¡': '¡',
|
|
3010
|
+
'¿': '¿',
|
|
3011
|
+
'ƒ': 'ƒ',
|
|
3012
|
+
'ˆ': 'ˆ',
|
|
3013
|
+
'˜': '˜',
|
|
3014
|
+
'Œ': 'Œ',
|
|
3015
|
+
'œ': 'œ',
|
|
3016
|
+
'Š': 'Š',
|
|
3017
|
+
'š': 'š',
|
|
3018
|
+
'Ÿ': 'Ÿ',
|
|
3019
|
+
'ª': 'ª',
|
|
3020
|
+
'º': 'º',
|
|
3021
|
+
'¯': '¯',
|
|
3022
|
+
'´': '´',
|
|
3023
|
+
'¸': '¸',
|
|
3024
|
+
'¹': '¹',
|
|
3025
|
+
'²': '²',
|
|
3026
|
+
'³': '³',
|
|
3027
|
+
'¼': '¼',
|
|
3028
|
+
'½': '½',
|
|
3029
|
+
'¾': '¾',
|
|
3030
|
+
'♠': '♠',
|
|
3031
|
+
'♣': '♣',
|
|
3032
|
+
'♥': '♥',
|
|
3033
|
+
'♦': '♦',
|
|
3034
|
+
'◊': '◊',
|
|
3035
|
+
'‾': '‾',
|
|
3036
|
+
'⁄': '⁄',
|
|
3037
|
+
'℘': '℘',
|
|
3038
|
+
'ℑ': 'ℑ',
|
|
3039
|
+
'ℜ': 'ℜ',
|
|
3040
|
+
'ℵ': 'ℵ'
|
|
3041
|
+
};
|
|
3042
|
+
const entityPattern = new RegExp(Object.keys(commonEntities).map(entity => entity.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|'), 'g');
|
|
3043
|
+
const decodeHtmlEntities = text => text.replace(entityPattern, match => commonEntities[match]).replace(/&#(\d+);/g, (_, num) => String.fromCharCode(parseInt(num, 10))).replace(/&#x([0-9a-fA-F]+);/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
|
|
3044
|
+
|
|
3045
|
+
const tokenize = translation => {
|
|
3046
|
+
const tokens = [];
|
|
3047
|
+
let position = 0;
|
|
3048
|
+
let currentText = '';
|
|
3049
|
+
const flushText = () => {
|
|
3050
|
+
if (currentText) {
|
|
3051
|
+
tokens.push({
|
|
3052
|
+
type: 'Text',
|
|
3053
|
+
value: currentText,
|
|
3054
|
+
position: position - currentText.length
|
|
3055
|
+
});
|
|
3056
|
+
currentText = '';
|
|
3057
|
+
}
|
|
3058
|
+
};
|
|
3059
|
+
while (position < translation.length) {
|
|
3060
|
+
const char = translation[position];
|
|
3061
|
+
if (char === '<') {
|
|
3062
|
+
const tagMatch = translation.slice(position).match(/^<(\d+)>/);
|
|
3063
|
+
if (tagMatch) {
|
|
3064
|
+
flushText();
|
|
3065
|
+
tokens.push({
|
|
3066
|
+
type: 'TagOpen',
|
|
3067
|
+
value: tagMatch[0],
|
|
3068
|
+
position,
|
|
3069
|
+
tagNumber: parseInt(tagMatch[1], 10)
|
|
3070
|
+
});
|
|
3071
|
+
position += tagMatch[0].length;
|
|
3072
|
+
} else {
|
|
3073
|
+
const closeTagMatch = translation.slice(position).match(/^<\/(\d+)>/);
|
|
3074
|
+
if (closeTagMatch) {
|
|
3075
|
+
flushText();
|
|
3076
|
+
tokens.push({
|
|
3077
|
+
type: 'TagClose',
|
|
3078
|
+
value: closeTagMatch[0],
|
|
3079
|
+
position,
|
|
3080
|
+
tagNumber: parseInt(closeTagMatch[1], 10)
|
|
3081
|
+
});
|
|
3082
|
+
position += closeTagMatch[0].length;
|
|
3083
|
+
} else {
|
|
3084
|
+
currentText += char;
|
|
3085
|
+
position += 1;
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
} else {
|
|
3089
|
+
currentText += char;
|
|
3090
|
+
position += 1;
|
|
3091
|
+
}
|
|
3092
|
+
}
|
|
3093
|
+
flushText();
|
|
3094
|
+
return tokens;
|
|
3095
|
+
};
|
|
3096
|
+
|
|
3097
|
+
const renderDeclarationNode = (declaration, children, childDeclarations) => {
|
|
3098
|
+
const {
|
|
3099
|
+
type,
|
|
3100
|
+
props = {}
|
|
3101
|
+
} = declaration;
|
|
3102
|
+
if (props.children && Array.isArray(props.children) && childDeclarations) {
|
|
3103
|
+
const {
|
|
3104
|
+
children: _childrenToRemove,
|
|
3105
|
+
...propsWithoutChildren
|
|
3106
|
+
} = props;
|
|
3107
|
+
return React.createElement(type, propsWithoutChildren, ...children);
|
|
3108
|
+
}
|
|
3109
|
+
if (children.length === 0) {
|
|
3110
|
+
return React.createElement(type, props);
|
|
3111
|
+
}
|
|
3112
|
+
if (children.length === 1) {
|
|
3113
|
+
return React.createElement(type, props, children[0]);
|
|
3114
|
+
}
|
|
3115
|
+
return React.createElement(type, props, ...children);
|
|
3116
|
+
};
|
|
3117
|
+
const renderTranslation = (translation, declarations = []) => {
|
|
3118
|
+
if (!translation) {
|
|
3119
|
+
return [];
|
|
3120
|
+
}
|
|
3121
|
+
const tokens = tokenize(translation);
|
|
3122
|
+
const result = [];
|
|
3123
|
+
const stack = [];
|
|
3124
|
+
const literalTagNumbers = new Set();
|
|
3125
|
+
const getCurrentDeclarations = () => {
|
|
3126
|
+
if (stack.length === 0) {
|
|
3127
|
+
return declarations;
|
|
3128
|
+
}
|
|
3129
|
+
const parentFrame = stack[stack.length - 1];
|
|
3130
|
+
if (parentFrame.declaration.props?.children && Array.isArray(parentFrame.declaration.props.children)) {
|
|
3131
|
+
return parentFrame.declaration.props.children;
|
|
3132
|
+
}
|
|
3133
|
+
return parentFrame.declarations;
|
|
3134
|
+
};
|
|
3135
|
+
tokens.forEach(token => {
|
|
3136
|
+
switch (token.type) {
|
|
3137
|
+
case 'Text':
|
|
3138
|
+
{
|
|
3139
|
+
const decoded = decodeHtmlEntities(token.value);
|
|
3140
|
+
const targetArray = stack.length > 0 ? stack[stack.length - 1].children : result;
|
|
3141
|
+
targetArray.push(decoded);
|
|
3142
|
+
}
|
|
3143
|
+
break;
|
|
3144
|
+
case 'TagOpen':
|
|
3145
|
+
{
|
|
3146
|
+
const {
|
|
3147
|
+
tagNumber
|
|
3148
|
+
} = token;
|
|
3149
|
+
const currentDeclarations = getCurrentDeclarations();
|
|
3150
|
+
const declaration = currentDeclarations[tagNumber];
|
|
3151
|
+
if (!declaration) {
|
|
3152
|
+
literalTagNumbers.add(tagNumber);
|
|
3153
|
+
const literalText = `<${tagNumber}>`;
|
|
3154
|
+
const targetArray = stack.length > 0 ? stack[stack.length - 1].children : result;
|
|
3155
|
+
targetArray.push(literalText);
|
|
3156
|
+
break;
|
|
3157
|
+
}
|
|
3158
|
+
stack.push({
|
|
3159
|
+
tagNumber,
|
|
3160
|
+
children: [],
|
|
3161
|
+
position: token.position,
|
|
3162
|
+
declaration,
|
|
3163
|
+
declarations: currentDeclarations
|
|
3164
|
+
});
|
|
3165
|
+
}
|
|
3166
|
+
break;
|
|
3167
|
+
case 'TagClose':
|
|
3168
|
+
{
|
|
3169
|
+
const {
|
|
3170
|
+
tagNumber
|
|
3171
|
+
} = token;
|
|
3172
|
+
if (literalTagNumbers.has(tagNumber)) {
|
|
3173
|
+
const literalText = `</${tagNumber}>`;
|
|
3174
|
+
const literalTargetArray = stack.length > 0 ? stack[stack.length - 1].children : result;
|
|
3175
|
+
literalTargetArray.push(literalText);
|
|
3176
|
+
literalTagNumbers.delete(tagNumber);
|
|
3177
|
+
break;
|
|
3178
|
+
}
|
|
3179
|
+
if (stack.length === 0) {
|
|
3180
|
+
throw new TranslationParserError(`Unexpected closing tag </${tagNumber}> at position ${token.position}`, token.position, translation);
|
|
3181
|
+
}
|
|
3182
|
+
const frame = stack.pop();
|
|
3183
|
+
if (frame.tagNumber !== tagNumber) {
|
|
3184
|
+
throw new TranslationParserError(`Mismatched tags: expected </${frame.tagNumber}> but got </${tagNumber}> at position ${token.position}`, token.position, translation);
|
|
3185
|
+
}
|
|
3186
|
+
const element = renderDeclarationNode(frame.declaration, frame.children, frame.declarations);
|
|
3187
|
+
const elementTargetArray = stack.length > 0 ? stack[stack.length - 1].children : result;
|
|
3188
|
+
elementTargetArray.push(element);
|
|
3189
|
+
}
|
|
3190
|
+
break;
|
|
3191
|
+
}
|
|
3192
|
+
});
|
|
3193
|
+
if (stack.length > 0) {
|
|
3194
|
+
const unclosed = stack[stack.length - 1];
|
|
3195
|
+
throw new TranslationParserError(`Unclosed tag <${unclosed.tagNumber}> at position ${unclosed.position}`, unclosed.position, translation);
|
|
3196
|
+
}
|
|
3197
|
+
return result;
|
|
3198
|
+
};
|
|
3199
|
+
|
|
3200
|
+
function IcuTransWithoutContext({
|
|
3201
|
+
i18nKey,
|
|
3202
|
+
defaultTranslation,
|
|
3203
|
+
content,
|
|
3204
|
+
ns,
|
|
3205
|
+
values = {},
|
|
3206
|
+
i18n: i18nFromProps,
|
|
3207
|
+
t: tFromProps
|
|
3208
|
+
}) {
|
|
3209
|
+
const i18n = i18nFromProps || getI18n();
|
|
3210
|
+
if (!i18n) {
|
|
3211
|
+
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', `IcuTrans: You need to pass in an i18next instance using i18nextReactModule`, {
|
|
3212
|
+
i18nKey
|
|
3213
|
+
});
|
|
3214
|
+
return React.createElement(React.Fragment, {}, defaultTranslation);
|
|
3215
|
+
}
|
|
3216
|
+
const t = tFromProps || i18n.t?.bind(i18n) || (k => k);
|
|
3217
|
+
let namespaces = ns || t.ns || i18n.options?.defaultNS;
|
|
3218
|
+
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
|
3219
|
+
let mergedValues = values;
|
|
3220
|
+
if (i18n.options?.interpolation?.defaultVariables) {
|
|
3221
|
+
mergedValues = values && Object.keys(values).length > 0 ? {
|
|
3222
|
+
...values,
|
|
3223
|
+
...i18n.options.interpolation.defaultVariables
|
|
3224
|
+
} : {
|
|
3225
|
+
...i18n.options.interpolation.defaultVariables
|
|
3226
|
+
};
|
|
3227
|
+
}
|
|
3228
|
+
const translation = t(i18nKey, {
|
|
3229
|
+
defaultValue: defaultTranslation,
|
|
3230
|
+
...mergedValues,
|
|
3231
|
+
ns: namespaces
|
|
3232
|
+
});
|
|
3233
|
+
try {
|
|
3234
|
+
const rendered = renderTranslation(translation, content);
|
|
3235
|
+
return React.createElement(React.Fragment, {}, ...rendered);
|
|
3236
|
+
} catch (error) {
|
|
3237
|
+
warn(i18n, 'ICU_TRANS_RENDER_ERROR', `IcuTrans component error for key "${i18nKey}": ${error.message}`, {
|
|
3238
|
+
i18nKey,
|
|
3239
|
+
error
|
|
3240
|
+
});
|
|
3241
|
+
return React.createElement(React.Fragment, {}, translation);
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
IcuTransWithoutContext.displayName = 'IcuTransWithoutContext';
|
|
3245
|
+
|
|
3246
|
+
function IcuTrans({
|
|
3247
|
+
i18nKey,
|
|
3248
|
+
defaultTranslation,
|
|
3249
|
+
content,
|
|
3250
|
+
ns,
|
|
3251
|
+
values = {},
|
|
3252
|
+
i18n: i18nFromProps,
|
|
3253
|
+
t: tFromProps
|
|
3254
|
+
}) {
|
|
3255
|
+
const {
|
|
3256
|
+
i18n: i18nFromContext,
|
|
3257
|
+
defaultNS: defaultNSFromContext
|
|
3258
|
+
} = React.useContext(I18nContext) || {};
|
|
3259
|
+
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
|
3260
|
+
const t = tFromProps || i18n?.t.bind(i18n);
|
|
3261
|
+
return IcuTransWithoutContext({
|
|
3262
|
+
i18nKey,
|
|
3263
|
+
defaultTranslation,
|
|
3264
|
+
content,
|
|
3265
|
+
ns: ns || t?.ns || defaultNSFromContext || i18n?.options?.defaultNS,
|
|
3266
|
+
values,
|
|
3267
|
+
i18n,
|
|
3268
|
+
t: tFromProps
|
|
3269
|
+
});
|
|
3270
|
+
}
|
|
3271
|
+
IcuTrans.displayName = 'IcuTrans';
|
|
3272
|
+
|
|
2821
3273
|
const usePrevious = (value, ignore) => {
|
|
2822
|
-
const ref =
|
|
2823
|
-
|
|
3274
|
+
const ref = React.useRef();
|
|
3275
|
+
React.useEffect(() => {
|
|
2824
3276
|
ref.current = value;
|
|
2825
3277
|
}, [value, ignore]);
|
|
2826
3278
|
return ref.current;
|
|
2827
3279
|
};
|
|
2828
3280
|
const alwaysNewT = (i18n, language, namespace, keyPrefix) => i18n.getFixedT(language, namespace, keyPrefix);
|
|
2829
|
-
const useMemoizedT = (i18n, language, namespace, keyPrefix) =>
|
|
3281
|
+
const useMemoizedT = (i18n, language, namespace, keyPrefix) => React.useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [i18n, language, namespace, keyPrefix]);
|
|
2830
3282
|
const useTranslation = (ns, props = {}) => {
|
|
2831
3283
|
const {
|
|
2832
3284
|
i18n: i18nFromProps
|
|
@@ -2834,7 +3286,7 @@
|
|
|
2834
3286
|
const {
|
|
2835
3287
|
i18n: i18nFromContext,
|
|
2836
3288
|
defaultNS: defaultNSFromContext
|
|
2837
|
-
} =
|
|
3289
|
+
} = React.useContext(I18nContext) || {};
|
|
2838
3290
|
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
|
2839
3291
|
if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
|
|
2840
3292
|
if (!i18n) {
|
|
@@ -2867,12 +3319,12 @@
|
|
|
2867
3319
|
const memoGetT = useMemoizedT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
|
2868
3320
|
const getT = () => memoGetT;
|
|
2869
3321
|
const getNewT = () => alwaysNewT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
|
2870
|
-
const [t, setT] =
|
|
3322
|
+
const [t, setT] = React.useState(getT);
|
|
2871
3323
|
let joinedNS = namespaces.join();
|
|
2872
3324
|
if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
|
|
2873
3325
|
const previousJoinedNS = usePrevious(joinedNS);
|
|
2874
|
-
const isMounted =
|
|
2875
|
-
|
|
3326
|
+
const isMounted = React.useRef(true);
|
|
3327
|
+
React.useEffect(() => {
|
|
2876
3328
|
const {
|
|
2877
3329
|
bindI18n,
|
|
2878
3330
|
bindI18nStore
|
|
@@ -2903,7 +3355,7 @@
|
|
|
2903
3355
|
if (bindI18nStore && i18n) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, boundReset));
|
|
2904
3356
|
};
|
|
2905
3357
|
}, [i18n, joinedNS]);
|
|
2906
|
-
|
|
3358
|
+
React.useEffect(() => {
|
|
2907
3359
|
if (isMounted.current && ready) {
|
|
2908
3360
|
setT(getT);
|
|
2909
3361
|
}
|
|
@@ -2943,14 +3395,14 @@
|
|
|
2943
3395
|
} else if (!options.withRef && forwardedRef) {
|
|
2944
3396
|
passDownProps.forwardedRef = forwardedRef;
|
|
2945
3397
|
}
|
|
2946
|
-
return
|
|
3398
|
+
return React.createElement(WrappedComponent, passDownProps);
|
|
2947
3399
|
}
|
|
2948
3400
|
I18nextWithTranslation.displayName = `withI18nextTranslation(${getDisplayName(WrappedComponent)})`;
|
|
2949
3401
|
I18nextWithTranslation.WrappedComponent = WrappedComponent;
|
|
2950
|
-
const forwardRef = (props, ref) =>
|
|
3402
|
+
const forwardRef = (props, ref) => React.createElement(I18nextWithTranslation, Object.assign({}, props, {
|
|
2951
3403
|
forwardedRef: ref
|
|
2952
3404
|
}));
|
|
2953
|
-
return options.withRef ?
|
|
3405
|
+
return options.withRef ? React.forwardRef(forwardRef) : I18nextWithTranslation;
|
|
2954
3406
|
};
|
|
2955
3407
|
|
|
2956
3408
|
const Translation = ({
|
|
@@ -2970,11 +3422,11 @@
|
|
|
2970
3422
|
defaultNS,
|
|
2971
3423
|
children
|
|
2972
3424
|
}) {
|
|
2973
|
-
const value =
|
|
3425
|
+
const value = React.useMemo(() => ({
|
|
2974
3426
|
i18n,
|
|
2975
3427
|
defaultNS
|
|
2976
3428
|
}), [i18n, defaultNS]);
|
|
2977
|
-
return
|
|
3429
|
+
return React.createElement(I18nContext.Provider, {
|
|
2978
3430
|
value
|
|
2979
3431
|
}, children);
|
|
2980
3432
|
}
|
|
@@ -2985,7 +3437,7 @@
|
|
|
2985
3437
|
} = props;
|
|
2986
3438
|
const {
|
|
2987
3439
|
i18n: i18nFromContext
|
|
2988
|
-
} =
|
|
3440
|
+
} = React.useContext(I18nContext) || {};
|
|
2989
3441
|
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
|
2990
3442
|
if (i18n.options?.isClone) return;
|
|
2991
3443
|
if (initialI18nStore && !i18n.initializedStoreOnce) {
|
|
@@ -3012,7 +3464,7 @@
|
|
|
3012
3464
|
...rest
|
|
3013
3465
|
}) {
|
|
3014
3466
|
useSSR(initialI18nStore, initialLanguage);
|
|
3015
|
-
return
|
|
3467
|
+
return React.createElement(WrappedComponent, {
|
|
3016
3468
|
...rest
|
|
3017
3469
|
});
|
|
3018
3470
|
}
|
|
@@ -3031,6 +3483,8 @@
|
|
|
3031
3483
|
|
|
3032
3484
|
exports.I18nContext = I18nContext;
|
|
3033
3485
|
exports.I18nextProvider = I18nextProvider;
|
|
3486
|
+
exports.IcuTrans = IcuTrans;
|
|
3487
|
+
exports.IcuTransWithoutContext = IcuTransWithoutContext;
|
|
3034
3488
|
exports.Trans = Trans;
|
|
3035
3489
|
exports.TransWithoutContext = Trans$1;
|
|
3036
3490
|
exports.Translation = Translation;
|