Projektstart
This commit is contained in:
19
frontend/node_modules/react-i18next/src/I18nextProvider.js
generated
vendored
Normal file
19
frontend/node_modules/react-i18next/src/I18nextProvider.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import { createElement, useMemo } from 'react';
|
||||
import { I18nContext } from './context.js';
|
||||
|
||||
export function I18nextProvider({ i18n, defaultNS, children }) {
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
i18n,
|
||||
defaultNS,
|
||||
}),
|
||||
[i18n, defaultNS],
|
||||
);
|
||||
return createElement(
|
||||
I18nContext.Provider,
|
||||
{
|
||||
value,
|
||||
},
|
||||
children,
|
||||
);
|
||||
}
|
||||
46
frontend/node_modules/react-i18next/src/Trans.js
generated
vendored
Normal file
46
frontend/node_modules/react-i18next/src/Trans.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import { useContext } from 'react';
|
||||
import { nodesToString, Trans as TransWithoutContext } from './TransWithoutContext.js';
|
||||
import { getI18n, I18nContext } from './context.js';
|
||||
|
||||
export { nodesToString };
|
||||
|
||||
export function Trans({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions = {},
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns,
|
||||
i18n: i18nFromProps,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
}) {
|
||||
const { i18n: i18nFromContext, defaultNS: defaultNSFromContext } = useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
|
||||
const t = tFromProps || (i18n && i18n.t.bind(i18n));
|
||||
|
||||
return TransWithoutContext({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions,
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
// prepare having a namespace
|
||||
ns:
|
||||
ns || (t && t.ns) || defaultNSFromContext || (i18n && i18n.options && i18n.options.defaultNS),
|
||||
i18n,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps,
|
||||
});
|
||||
}
|
||||
399
frontend/node_modules/react-i18next/src/TransWithoutContext.js
generated
vendored
Normal file
399
frontend/node_modules/react-i18next/src/TransWithoutContext.js
generated
vendored
Normal file
@@ -0,0 +1,399 @@
|
||||
import { Fragment, isValidElement, cloneElement, createElement, Children } from 'react';
|
||||
import HTML from 'html-parse-stringify';
|
||||
import { isObject, isString, warn, warnOnce } from './utils.js';
|
||||
import { getDefaults } from './defaults.js';
|
||||
import { getI18n } from './i18nInstance.js';
|
||||
|
||||
const hasChildren = (node, checkLength) => {
|
||||
if (!node) return false;
|
||||
const base = node.props ? node.props.children : node.children;
|
||||
if (checkLength) return base.length > 0;
|
||||
return !!base;
|
||||
};
|
||||
|
||||
const getChildren = (node) => {
|
||||
if (!node) return [];
|
||||
const children = node.props ? node.props.children : node.children;
|
||||
return node.props && node.props.i18nIsDynamicList ? getAsArray(children) : children;
|
||||
};
|
||||
|
||||
const hasValidReactChildren = (children) =>
|
||||
Array.isArray(children) && children.every(isValidElement);
|
||||
|
||||
const getAsArray = (data) => (Array.isArray(data) ? data : [data]);
|
||||
|
||||
const mergeProps = (source, target) => {
|
||||
const newTarget = { ...target };
|
||||
// overwrite source.props when target.props already set
|
||||
newTarget.props = Object.assign(source.props, target.props);
|
||||
return newTarget;
|
||||
};
|
||||
|
||||
export const nodesToString = (children, i18nOptions) => {
|
||||
if (!children) return '';
|
||||
let stringNode = '';
|
||||
|
||||
// do not use `React.Children.toArray`, will fail at object children
|
||||
const childrenArray = getAsArray(children);
|
||||
const keepArray =
|
||||
i18nOptions.transSupportBasicHtmlNodes && i18nOptions.transKeepBasicHtmlNodesFor
|
||||
? i18nOptions.transKeepBasicHtmlNodesFor
|
||||
: [];
|
||||
|
||||
// e.g. lorem <br/> ipsum {{ messageCount, format }} dolor <strong>bold</strong> amet
|
||||
childrenArray.forEach((child, childIndex) => {
|
||||
if (isString(child)) {
|
||||
// actual e.g. lorem
|
||||
// expected e.g. lorem
|
||||
stringNode += `${child}`;
|
||||
} else if (isValidElement(child)) {
|
||||
const { props, type } = child;
|
||||
const childPropsCount = Object.keys(props).length;
|
||||
const shouldKeepChild = keepArray.indexOf(type) > -1;
|
||||
const childChildren = props.children;
|
||||
|
||||
if (!childChildren && shouldKeepChild && !childPropsCount) {
|
||||
// actual e.g. lorem <br/> ipsum
|
||||
// expected e.g. lorem <br/> ipsum
|
||||
stringNode += `<${type}/>`;
|
||||
} else if (
|
||||
(!childChildren && (!shouldKeepChild || childPropsCount)) ||
|
||||
props.i18nIsDynamicList
|
||||
) {
|
||||
// actual e.g. lorem <hr className="test" /> ipsum
|
||||
// expected e.g. lorem <0></0> ipsum
|
||||
// or
|
||||
// we got a dynamic list like
|
||||
// e.g. <ul i18nIsDynamicList>{['a', 'b'].map(item => ( <li key={item}>{item}</li> ))}</ul>
|
||||
// expected e.g. "<0></0>", not e.g. "<0><0>a</0><1>b</1></0>"
|
||||
stringNode += `<${childIndex}></${childIndex}>`;
|
||||
} else if (shouldKeepChild && childPropsCount === 1 && isString(childChildren)) {
|
||||
// actual e.g. dolor <strong>bold</strong> amet
|
||||
// expected e.g. dolor <strong>bold</strong> amet
|
||||
stringNode += `<${type}>${childChildren}</${type}>`;
|
||||
} else {
|
||||
// regular case mapping the inner children
|
||||
const content = nodesToString(childChildren, i18nOptions);
|
||||
stringNode += `<${childIndex}>${content}</${childIndex}>`;
|
||||
}
|
||||
} else if (child === null) {
|
||||
warn(`Trans: the passed in value is invalid - seems you passed in a null child.`);
|
||||
} else if (isObject(child)) {
|
||||
// e.g. lorem {{ value, format }} ipsum
|
||||
const { format, ...clone } = child;
|
||||
const keys = Object.keys(clone);
|
||||
|
||||
if (keys.length === 1) {
|
||||
const value = format ? `${keys[0]}, ${format}` : keys[0];
|
||||
stringNode += `{{${value}}}`;
|
||||
} else {
|
||||
// not a valid interpolation object (can only contain one value plus format)
|
||||
warn(
|
||||
`react-i18next: the passed in object contained more than one variable - the object should look like {{ value, format }} where format is optional.`,
|
||||
child,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
warn(
|
||||
`Trans: the passed in value is invalid - seems you passed in a variable like {number} - please pass in variables for interpolation as full objects like {{number}}.`,
|
||||
child,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return stringNode;
|
||||
};
|
||||
|
||||
const renderNodes = (children, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
|
||||
if (targetString === '') return [];
|
||||
|
||||
// check if contains tags we need to replace from html string to react nodes
|
||||
const keepArray = i18nOptions.transKeepBasicHtmlNodesFor || [];
|
||||
const emptyChildrenButNeedsHandling =
|
||||
targetString && new RegExp(keepArray.map((keep) => `<${keep}`).join('|')).test(targetString);
|
||||
|
||||
// no need to replace tags in the targetstring
|
||||
if (!children && !emptyChildrenButNeedsHandling && !shouldUnescape) return [targetString];
|
||||
|
||||
// v2 -> interpolates upfront no need for "some <0>{{var}}</0>"" -> will be just "some {{var}}" in translation file
|
||||
const data = {};
|
||||
|
||||
const getData = (childs) => {
|
||||
const childrenArray = getAsArray(childs);
|
||||
|
||||
childrenArray.forEach((child) => {
|
||||
if (isString(child)) return;
|
||||
if (hasChildren(child)) getData(getChildren(child));
|
||||
else if (isObject(child) && !isValidElement(child)) Object.assign(data, child);
|
||||
});
|
||||
};
|
||||
|
||||
getData(children);
|
||||
|
||||
// parse ast from string with additional wrapper tag
|
||||
// -> avoids issues in parser removing prepending text nodes
|
||||
const ast = HTML.parse(`<0>${targetString}</0>`);
|
||||
const opts = { ...data, ...combinedTOpts };
|
||||
|
||||
const renderInner = (child, node, rootReactNode) => {
|
||||
const childs = getChildren(child);
|
||||
const mappedChildren = mapAST(childs, node.children, rootReactNode);
|
||||
// `mappedChildren` will always be empty if using the `i18nIsDynamicList` prop,
|
||||
// but the children might not necessarily be react components
|
||||
return (hasValidReactChildren(childs) && mappedChildren.length === 0) ||
|
||||
(child.props && child.props.i18nIsDynamicList)
|
||||
? childs
|
||||
: mappedChildren;
|
||||
};
|
||||
|
||||
const pushTranslatedJSX = (child, inner, mem, i, isVoid) => {
|
||||
if (child.dummy) {
|
||||
child.children = inner; // needed on preact!
|
||||
mem.push(cloneElement(child, { key: i }, isVoid ? undefined : inner));
|
||||
} else {
|
||||
mem.push(
|
||||
...Children.map([child], (c) => {
|
||||
const props = { ...c.props };
|
||||
delete props.i18nIsDynamicList;
|
||||
// <c.type {...props} key={i} ref={c.ref} {...(isVoid ? {} : { children: inner })} />;
|
||||
return createElement(
|
||||
c.type,
|
||||
{
|
||||
...props,
|
||||
key: i,
|
||||
ref: c.ref,
|
||||
},
|
||||
isVoid ? null : inner,
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// reactNode (the jsx root element or child)
|
||||
// astNode (the translation string as html ast)
|
||||
// rootReactNode (the most outer jsx children array or trans components prop)
|
||||
const mapAST = (reactNode, astNode, rootReactNode) => {
|
||||
const reactNodes = getAsArray(reactNode);
|
||||
const astNodes = getAsArray(astNode);
|
||||
|
||||
return astNodes.reduce((mem, node, i) => {
|
||||
const translationContent =
|
||||
node.children &&
|
||||
node.children[0] &&
|
||||
node.children[0].content &&
|
||||
i18n.services.interpolator.interpolate(node.children[0].content, opts, i18n.language);
|
||||
|
||||
if (node.type === 'tag') {
|
||||
// regular array (components or children)
|
||||
let tmp = reactNodes[parseInt(node.name, 10)];
|
||||
|
||||
// trans components is an object
|
||||
if (rootReactNode.length === 1 && !tmp) tmp = rootReactNode[0][node.name];
|
||||
|
||||
// neither
|
||||
if (!tmp) tmp = {};
|
||||
|
||||
const child =
|
||||
Object.keys(node.attrs).length !== 0 ? mergeProps({ props: node.attrs }, tmp) : tmp;
|
||||
|
||||
const isElement = isValidElement(child);
|
||||
|
||||
const isValidTranslationWithChildren =
|
||||
isElement && hasChildren(node, true) && !node.voidElement;
|
||||
|
||||
const isEmptyTransWithHTML =
|
||||
emptyChildrenButNeedsHandling && isObject(child) && child.dummy && !isElement;
|
||||
|
||||
const isKnownComponent =
|
||||
isObject(children) && Object.hasOwnProperty.call(children, node.name);
|
||||
|
||||
if (isString(child)) {
|
||||
const value = i18n.services.interpolator.interpolate(child, opts, i18n.language);
|
||||
mem.push(value);
|
||||
} else if (
|
||||
hasChildren(child) || // the jsx element has children -> loop
|
||||
isValidTranslationWithChildren // valid jsx element with no children but the translation has -> loop
|
||||
) {
|
||||
const inner = renderInner(child, node, rootReactNode);
|
||||
pushTranslatedJSX(child, inner, mem, i);
|
||||
} else if (isEmptyTransWithHTML) {
|
||||
// we have a empty Trans node (the dummy element) with a targetstring that contains html tags needing
|
||||
// conversion to react nodes
|
||||
// so we just need to map the inner stuff
|
||||
const inner = mapAST(
|
||||
reactNodes /* wrong but we need something */,
|
||||
node.children,
|
||||
rootReactNode,
|
||||
);
|
||||
pushTranslatedJSX(child, inner, mem, i);
|
||||
} else if (Number.isNaN(parseFloat(node.name))) {
|
||||
if (isKnownComponent) {
|
||||
const inner = renderInner(child, node, rootReactNode);
|
||||
pushTranslatedJSX(child, inner, mem, i, node.voidElement);
|
||||
} else if (i18nOptions.transSupportBasicHtmlNodes && keepArray.indexOf(node.name) > -1) {
|
||||
if (node.voidElement) {
|
||||
mem.push(createElement(node.name, { key: `${node.name}-${i}` }));
|
||||
} else {
|
||||
const inner = mapAST(
|
||||
reactNodes /* wrong but we need something */,
|
||||
node.children,
|
||||
rootReactNode,
|
||||
);
|
||||
|
||||
mem.push(createElement(node.name, { key: `${node.name}-${i}` }, inner));
|
||||
}
|
||||
} else if (node.voidElement) {
|
||||
mem.push(`<${node.name} />`);
|
||||
} else {
|
||||
const inner = mapAST(
|
||||
reactNodes /* wrong but we need something */,
|
||||
node.children,
|
||||
rootReactNode,
|
||||
);
|
||||
|
||||
mem.push(`<${node.name}>${inner}</${node.name}>`);
|
||||
}
|
||||
} else if (isObject(child) && !isElement) {
|
||||
const content = node.children[0] ? translationContent : null;
|
||||
|
||||
// v1
|
||||
// as interpolation was done already we just have a regular content node
|
||||
// in the translation AST while having an object in reactNodes
|
||||
// -> push the content no need to interpolate again
|
||||
if (content) mem.push(content);
|
||||
} else {
|
||||
// If component does not have children, but translation - has
|
||||
// with this in component could be components={[<span class='make-beautiful'/>]} and in translation - 'some text <0>some highlighted message</0>'
|
||||
pushTranslatedJSX(
|
||||
child,
|
||||
translationContent,
|
||||
mem,
|
||||
i,
|
||||
node.children.length !== 1 || !translationContent,
|
||||
);
|
||||
}
|
||||
} else if (node.type === 'text') {
|
||||
const wrapTextNodes = i18nOptions.transWrapTextNodes;
|
||||
const content = shouldUnescape
|
||||
? i18nOptions.unescape(
|
||||
i18n.services.interpolator.interpolate(node.content, opts, i18n.language),
|
||||
)
|
||||
: i18n.services.interpolator.interpolate(node.content, opts, i18n.language);
|
||||
if (wrapTextNodes) {
|
||||
mem.push(createElement(wrapTextNodes, { key: `${node.name}-${i}` }, content));
|
||||
} else {
|
||||
mem.push(content);
|
||||
}
|
||||
}
|
||||
return mem;
|
||||
}, []);
|
||||
};
|
||||
|
||||
// call mapAST with having react nodes nested into additional node like
|
||||
// we did for the string ast from translation
|
||||
// return the children of that extra node to get expected result
|
||||
const result = mapAST(
|
||||
[{ dummy: true, children: children || [] }],
|
||||
ast,
|
||||
getAsArray(children || []),
|
||||
);
|
||||
return getChildren(result[0]);
|
||||
};
|
||||
|
||||
export function Trans({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions = {},
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns,
|
||||
i18n: i18nFromProps,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
}) {
|
||||
const i18n = i18nFromProps || getI18n();
|
||||
|
||||
if (!i18n) {
|
||||
warnOnce('You will need to pass in an i18next instance by using i18nextReactModule');
|
||||
return children;
|
||||
}
|
||||
|
||||
const t = tFromProps || i18n.t.bind(i18n) || ((k) => k);
|
||||
|
||||
const reactI18nextOptions = { ...getDefaults(), ...(i18n.options && i18n.options.react) };
|
||||
|
||||
// prepare having a namespace
|
||||
let namespaces = ns || t.ns || (i18n.options && i18n.options.defaultNS);
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
|
||||
const nodeAsString = nodesToString(children, reactI18nextOptions);
|
||||
const defaultValue =
|
||||
defaults || nodeAsString || reactI18nextOptions.transEmptyNodeValue || i18nKey;
|
||||
const { hashTransKey } = reactI18nextOptions;
|
||||
const key =
|
||||
i18nKey ||
|
||||
(hashTransKey ? hashTransKey(nodeAsString || defaultValue) : nodeAsString || defaultValue);
|
||||
if (i18n.options && i18n.options.interpolation && i18n.options.interpolation.defaultVariables) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
values =
|
||||
values && Object.keys(values).length > 0
|
||||
? { ...values, ...i18n.options.interpolation.defaultVariables }
|
||||
: { ...i18n.options.interpolation.defaultVariables };
|
||||
}
|
||||
const interpolationOverride =
|
||||
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
|
||||
? tOptions.interpolation
|
||||
: { interpolation: { ...tOptions.interpolation, prefix: '#$?', suffix: '?$#' } };
|
||||
const combinedTOpts = {
|
||||
...tOptions,
|
||||
context: context || tOptions.context, // Add `context` from the props or fallback to the value from `tOptions`
|
||||
count,
|
||||
...values,
|
||||
...interpolationOverride,
|
||||
defaultValue,
|
||||
ns: namespaces,
|
||||
};
|
||||
const translation = key ? t(key, combinedTOpts) : defaultValue;
|
||||
|
||||
if (components) {
|
||||
Object.keys(components).forEach((c) => {
|
||||
const comp = components[c];
|
||||
if (
|
||||
typeof comp.type === 'function' ||
|
||||
!comp.props ||
|
||||
!comp.props.children ||
|
||||
(translation.indexOf(`${c}/>`) < 0 && translation.indexOf(`${c} />`) < 0)
|
||||
)
|
||||
return;
|
||||
|
||||
// eslint-disable-next-line react/no-unstable-nested-components, no-inner-declarations
|
||||
function Componentized() {
|
||||
// <>{comp}</>
|
||||
return createElement(Fragment, null, comp);
|
||||
}
|
||||
// <Componentized />
|
||||
components[c] = createElement(Componentized);
|
||||
});
|
||||
}
|
||||
|
||||
const content = renderNodes(
|
||||
components || children,
|
||||
translation,
|
||||
i18n,
|
||||
reactI18nextOptions,
|
||||
combinedTOpts,
|
||||
shouldUnescape,
|
||||
);
|
||||
|
||||
// allows user to pass `null` to `parent`
|
||||
// and override `defaultTransParent` if is present
|
||||
const useAsParent = parent !== undefined ? parent : reactI18nextOptions.defaultTransParent;
|
||||
|
||||
return useAsParent ? createElement(useAsParent, additionalProps, content) : content;
|
||||
}
|
||||
15
frontend/node_modules/react-i18next/src/Translation.js
generated
vendored
Normal file
15
frontend/node_modules/react-i18next/src/Translation.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useTranslation } from './useTranslation.js';
|
||||
|
||||
export function Translation(props) {
|
||||
const { ns, children, ...options } = props;
|
||||
const [t, i18n, ready] = useTranslation(ns, options);
|
||||
|
||||
return children(
|
||||
t,
|
||||
{
|
||||
i18n,
|
||||
lng: i18n.language,
|
||||
},
|
||||
ready,
|
||||
);
|
||||
}
|
||||
54
frontend/node_modules/react-i18next/src/context.js
generated
vendored
Normal file
54
frontend/node_modules/react-i18next/src/context.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import { createContext } from 'react';
|
||||
import { getDefaults, setDefaults } from './defaults.js';
|
||||
import { getI18n, setI18n } from './i18nInstance.js';
|
||||
import { initReactI18next } from './initReactI18next.js';
|
||||
|
||||
export { getDefaults, setDefaults, getI18n, setI18n, initReactI18next };
|
||||
|
||||
export const I18nContext = createContext();
|
||||
|
||||
export class ReportNamespaces {
|
||||
constructor() {
|
||||
this.usedNamespaces = {};
|
||||
}
|
||||
|
||||
addUsedNamespaces(namespaces) {
|
||||
namespaces.forEach((ns) => {
|
||||
if (!this.usedNamespaces[ns]) this.usedNamespaces[ns] = true;
|
||||
});
|
||||
}
|
||||
|
||||
getUsedNamespaces = () => Object.keys(this.usedNamespaces);
|
||||
}
|
||||
|
||||
export const composeInitialProps = (ForComponent) => async (ctx) => {
|
||||
const componentsInitialProps = ForComponent.getInitialProps
|
||||
? await ForComponent.getInitialProps(ctx)
|
||||
: {};
|
||||
|
||||
const i18nInitialProps = getInitialProps();
|
||||
|
||||
return {
|
||||
...componentsInitialProps,
|
||||
...i18nInitialProps,
|
||||
};
|
||||
};
|
||||
|
||||
export const getInitialProps = () => {
|
||||
const i18n = getI18n();
|
||||
const namespaces = i18n.reportNamespaces ? i18n.reportNamespaces.getUsedNamespaces() : [];
|
||||
|
||||
const ret = {};
|
||||
const initialI18nStore = {};
|
||||
i18n.languages.forEach((l) => {
|
||||
initialI18nStore[l] = {};
|
||||
namespaces.forEach((ns) => {
|
||||
initialI18nStore[l][ns] = i18n.getResourceBundle(l, ns) || {};
|
||||
});
|
||||
});
|
||||
|
||||
ret.initialI18nStore = initialI18nStore;
|
||||
ret.initialLanguage = i18n.language;
|
||||
|
||||
return ret;
|
||||
};
|
||||
20
frontend/node_modules/react-i18next/src/defaults.js
generated
vendored
Normal file
20
frontend/node_modules/react-i18next/src/defaults.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { unescape } from './unescape.js';
|
||||
|
||||
let defaultOptions = {
|
||||
bindI18n: 'languageChanged',
|
||||
bindI18nStore: '',
|
||||
// nsMode: 'fallback' // loop through all namespaces given to hook, HOC, render prop for key lookup
|
||||
transEmptyNodeValue: '',
|
||||
transSupportBasicHtmlNodes: true,
|
||||
transWrapTextNodes: '',
|
||||
transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p'],
|
||||
// hashTransKey: key => key // calculate a key for Trans component based on defaultValue
|
||||
useSuspense: true,
|
||||
unescape,
|
||||
};
|
||||
|
||||
export const setDefaults = (options = {}) => {
|
||||
defaultOptions = { ...defaultOptions, ...options };
|
||||
};
|
||||
|
||||
export const getDefaults = () => defaultOptions;
|
||||
7
frontend/node_modules/react-i18next/src/i18nInstance.js
generated
vendored
Normal file
7
frontend/node_modules/react-i18next/src/i18nInstance.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
let i18nInstance;
|
||||
|
||||
export const setI18n = (instance) => {
|
||||
i18nInstance = instance;
|
||||
};
|
||||
|
||||
export const getI18n = () => i18nInstance;
|
||||
22
frontend/node_modules/react-i18next/src/index.js
generated
vendored
Normal file
22
frontend/node_modules/react-i18next/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
export { Trans } from './Trans.js';
|
||||
export { Trans as TransWithoutContext } from './TransWithoutContext.js';
|
||||
export { useTranslation } from './useTranslation.js';
|
||||
export { withTranslation } from './withTranslation.js';
|
||||
export { Translation } from './Translation.js';
|
||||
export { I18nextProvider } from './I18nextProvider.js';
|
||||
export { withSSR } from './withSSR.js';
|
||||
export { useSSR } from './useSSR.js';
|
||||
export { initReactI18next } from './initReactI18next.js';
|
||||
export { setDefaults, getDefaults } from './defaults.js';
|
||||
export { setI18n, getI18n } from './i18nInstance.js';
|
||||
|
||||
export { I18nContext, composeInitialProps, getInitialProps } from './context.js';
|
||||
|
||||
// dummy functions for icu.macro support
|
||||
|
||||
export const date = () => '';
|
||||
export const time = () => '';
|
||||
export const number = () => '';
|
||||
export const select = () => '';
|
||||
export const plural = () => '';
|
||||
export const selectOrdinal = () => '';
|
||||
11
frontend/node_modules/react-i18next/src/initReactI18next.js
generated
vendored
Normal file
11
frontend/node_modules/react-i18next/src/initReactI18next.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { setDefaults } from './defaults.js';
|
||||
import { setI18n } from './i18nInstance.js';
|
||||
|
||||
export const initReactI18next = {
|
||||
type: '3rdParty',
|
||||
|
||||
init(instance) {
|
||||
setDefaults(instance.options.react);
|
||||
setI18n(instance);
|
||||
},
|
||||
};
|
||||
31
frontend/node_modules/react-i18next/src/unescape.js
generated
vendored
Normal file
31
frontend/node_modules/react-i18next/src/unescape.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// unescape common html entities
|
||||
|
||||
const matchHtmlEntity =
|
||||
/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g;
|
||||
|
||||
const htmlEntities = {
|
||||
'&': '&',
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'>': '>',
|
||||
''': "'",
|
||||
''': "'",
|
||||
'"': '"',
|
||||
'"': '"',
|
||||
' ': ' ',
|
||||
' ': ' ',
|
||||
'©': '©',
|
||||
'©': '©',
|
||||
'®': '®',
|
||||
'®': '®',
|
||||
'…': '…',
|
||||
'…': '…',
|
||||
'/': '/',
|
||||
'/': '/',
|
||||
};
|
||||
|
||||
const unescapeHtmlEntity = (m) => htmlEntities[m];
|
||||
|
||||
export const unescape = (text) => text.replace(matchHtmlEntity, unescapeHtmlEntity);
|
||||
33
frontend/node_modules/react-i18next/src/useSSR.js
generated
vendored
Normal file
33
frontend/node_modules/react-i18next/src/useSSR.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { useContext } from 'react';
|
||||
import { getI18n, I18nContext } from './context.js';
|
||||
|
||||
export const useSSR = (initialI18nStore, initialLanguage, props = {}) => {
|
||||
const { i18n: i18nFromProps } = props;
|
||||
const { i18n: i18nFromContext } = useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
|
||||
// opt out if is a cloned instance, eg. created by i18next-http-middleware on request
|
||||
// -> do not set initial stuff on server side
|
||||
if (i18n.options && i18n.options.isClone) return;
|
||||
|
||||
// nextjs / SSR: getting data from next.js or other ssr stack
|
||||
if (initialI18nStore && !i18n.initializedStoreOnce) {
|
||||
i18n.services.resourceStore.data = initialI18nStore;
|
||||
|
||||
// add namespaces to the config - so a languageChange call loads all namespaces needed
|
||||
i18n.options.ns = Object.values(initialI18nStore).reduce((mem, lngResources) => {
|
||||
Object.keys(lngResources).forEach((ns) => {
|
||||
if (mem.indexOf(ns) < 0) mem.push(ns);
|
||||
});
|
||||
return mem;
|
||||
}, i18n.options.ns);
|
||||
|
||||
i18n.initializedStoreOnce = true;
|
||||
i18n.isInitialized = true;
|
||||
}
|
||||
|
||||
if (initialLanguage && !i18n.initializedLanguageOnce) {
|
||||
i18n.changeLanguage(initialLanguage);
|
||||
i18n.initializedLanguageOnce = true;
|
||||
}
|
||||
};
|
||||
165
frontend/node_modules/react-i18next/src/useTranslation.js
generated
vendored
Normal file
165
frontend/node_modules/react-i18next/src/useTranslation.js
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
import { useState, useEffect, useContext, useRef, useCallback } from 'react';
|
||||
import { getI18n, getDefaults, ReportNamespaces, I18nContext } from './context.js';
|
||||
import {
|
||||
warnOnce,
|
||||
loadNamespaces,
|
||||
loadLanguages,
|
||||
hasLoadedNamespace,
|
||||
isString,
|
||||
isObject,
|
||||
} from './utils.js';
|
||||
|
||||
const usePrevious = (value, ignore) => {
|
||||
const ref = useRef();
|
||||
useEffect(() => {
|
||||
ref.current = ignore ? ref.current : value;
|
||||
}, [value, ignore]);
|
||||
return ref.current;
|
||||
};
|
||||
|
||||
const alwaysNewT = (i18n, language, namespace, keyPrefix) =>
|
||||
i18n.getFixedT(language, namespace, keyPrefix);
|
||||
|
||||
const useMemoizedT = (i18n, language, namespace, keyPrefix) =>
|
||||
useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [
|
||||
i18n,
|
||||
language,
|
||||
namespace,
|
||||
keyPrefix,
|
||||
]);
|
||||
|
||||
export const useTranslation = (ns, props = {}) => {
|
||||
// assert we have the needed i18nInstance
|
||||
const { i18n: i18nFromProps } = props;
|
||||
const { i18n: i18nFromContext, defaultNS: defaultNSFromContext } = useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
|
||||
if (!i18n) {
|
||||
warnOnce('You will need to pass in an i18next instance by using initReactI18next');
|
||||
const notReadyT = (k, optsOrDefaultValue) => {
|
||||
if (isString(optsOrDefaultValue)) return optsOrDefaultValue;
|
||||
if (isObject(optsOrDefaultValue) && isString(optsOrDefaultValue.defaultValue))
|
||||
return optsOrDefaultValue.defaultValue;
|
||||
return Array.isArray(k) ? k[k.length - 1] : k;
|
||||
};
|
||||
const retNotReady = [notReadyT, {}, false];
|
||||
retNotReady.t = notReadyT;
|
||||
retNotReady.i18n = {};
|
||||
retNotReady.ready = false;
|
||||
return retNotReady;
|
||||
}
|
||||
|
||||
if (i18n.options.react && i18n.options.react.wait !== undefined)
|
||||
warnOnce(
|
||||
'It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.',
|
||||
);
|
||||
|
||||
const i18nOptions = { ...getDefaults(), ...i18n.options.react, ...props };
|
||||
const { useSuspense, keyPrefix } = i18nOptions;
|
||||
|
||||
// prepare having a namespace
|
||||
let namespaces = ns || defaultNSFromContext || (i18n.options && i18n.options.defaultNS);
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
|
||||
// report namespaces as used
|
||||
if (i18n.reportNamespaces.addUsedNamespaces) i18n.reportNamespaces.addUsedNamespaces(namespaces);
|
||||
|
||||
// are we ready? yes if all namespaces in first language are loaded already (either with data or empty object on failed load)
|
||||
const ready =
|
||||
(i18n.isInitialized || i18n.initializedStoreOnce) &&
|
||||
namespaces.every((n) => hasLoadedNamespace(n, i18n, i18nOptions));
|
||||
|
||||
// binding t function to namespace (acts also as rerender trigger *when* args have changed)
|
||||
const memoGetT = useMemoizedT(
|
||||
i18n,
|
||||
props.lng || null,
|
||||
i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0],
|
||||
keyPrefix,
|
||||
);
|
||||
// using useState with a function expects an initializer, not the function itself:
|
||||
const getT = () => memoGetT;
|
||||
const getNewT = () =>
|
||||
alwaysNewT(
|
||||
i18n,
|
||||
props.lng || null,
|
||||
i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0],
|
||||
keyPrefix,
|
||||
);
|
||||
|
||||
const [t, setT] = useState(getT);
|
||||
|
||||
let joinedNS = namespaces.join();
|
||||
if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
|
||||
const previousJoinedNS = usePrevious(joinedNS);
|
||||
|
||||
const isMounted = useRef(true);
|
||||
useEffect(() => {
|
||||
const { bindI18n, bindI18nStore } = i18nOptions;
|
||||
isMounted.current = true;
|
||||
|
||||
// if not ready and not using suspense load the namespaces
|
||||
// in side effect and do not call resetT if unmounted
|
||||
if (!ready && !useSuspense) {
|
||||
if (props.lng) {
|
||||
loadLanguages(i18n, props.lng, namespaces, () => {
|
||||
if (isMounted.current) setT(getNewT);
|
||||
});
|
||||
} else {
|
||||
loadNamespaces(i18n, namespaces, () => {
|
||||
if (isMounted.current) setT(getNewT);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (ready && previousJoinedNS && previousJoinedNS !== joinedNS && isMounted.current) {
|
||||
setT(getNewT);
|
||||
}
|
||||
|
||||
const boundReset = () => {
|
||||
if (isMounted.current) setT(getNewT);
|
||||
};
|
||||
|
||||
// bind events to trigger change, like languageChanged
|
||||
if (bindI18n && i18n) i18n.on(bindI18n, boundReset);
|
||||
if (bindI18nStore && i18n) i18n.store.on(bindI18nStore, boundReset);
|
||||
|
||||
// unbinding on unmount
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
if (bindI18n && i18n) bindI18n.split(' ').forEach((e) => i18n.off(e, boundReset));
|
||||
if (bindI18nStore && i18n)
|
||||
bindI18nStore.split(' ').forEach((e) => i18n.store.off(e, boundReset));
|
||||
};
|
||||
}, [i18n, joinedNS]); // re-run effect whenever list of namespaces changes
|
||||
|
||||
// t is correctly initialized by useState hook. We only need to update it after i18n
|
||||
// instance was replaced (for example in the provider).
|
||||
useEffect(() => {
|
||||
if (isMounted.current && ready) {
|
||||
// not getNewT: depend on dependency list of the useCallback call within
|
||||
// useMemoizedT to only provide a newly-bound t *iff* i18n instance was
|
||||
// replaced; see bug 1691 https://github.com/i18next/react-i18next/issues/1691
|
||||
setT(getT);
|
||||
}
|
||||
}, [i18n, keyPrefix, ready]); // re-run when i18n instance or keyPrefix were replaced
|
||||
|
||||
const ret = [t, i18n, ready];
|
||||
ret.t = t;
|
||||
ret.i18n = i18n;
|
||||
ret.ready = ready;
|
||||
|
||||
// return hook stuff if ready
|
||||
if (ready) return ret;
|
||||
|
||||
// not yet loaded namespaces -> load them -> and return if useSuspense option set false
|
||||
if (!ready && !useSuspense) return ret;
|
||||
|
||||
// not yet loaded namespaces -> load them -> and trigger suspense
|
||||
throw new Promise((resolve) => {
|
||||
if (props.lng) {
|
||||
loadLanguages(i18n, props.lng, namespaces, () => resolve());
|
||||
} else {
|
||||
loadNamespaces(i18n, namespaces, () => resolve());
|
||||
}
|
||||
});
|
||||
};
|
||||
134
frontend/node_modules/react-i18next/src/utils.js
generated
vendored
Normal file
134
frontend/node_modules/react-i18next/src/utils.js
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
// Do not use arrow function here as it will break optimizations of arguments
|
||||
export function warn(...args) {
|
||||
if (console && console.warn) {
|
||||
if (isString(args[0])) args[0] = `react-i18next:: ${args[0]}`;
|
||||
console.warn(...args);
|
||||
}
|
||||
}
|
||||
|
||||
const alreadyWarned = {};
|
||||
// Do not use arrow function here as it will break optimizations of arguments
|
||||
export function warnOnce(...args) {
|
||||
if (isString(args[0]) && alreadyWarned[args[0]]) return;
|
||||
if (isString(args[0])) alreadyWarned[args[0]] = new Date();
|
||||
warn(...args);
|
||||
}
|
||||
|
||||
// not needed right now
|
||||
//
|
||||
// export function deprecated(...args) {
|
||||
// if (process && process.env && (!process.env.NODE_ENV || process.env.NODE_ENV === 'development')) {
|
||||
// if (isString(args[0])) args[0] = `deprecation warning -> ${args[0]}`;
|
||||
// warnOnce(...args);
|
||||
// }
|
||||
// }
|
||||
|
||||
const loadedClb = (i18n, cb) => () => {
|
||||
// delay ready if not yet initialized i18n instance
|
||||
if (i18n.isInitialized) {
|
||||
cb();
|
||||
} else {
|
||||
const initialized = () => {
|
||||
// due to emitter removing issue in i18next we need to delay remove
|
||||
setTimeout(() => {
|
||||
i18n.off('initialized', initialized);
|
||||
}, 0);
|
||||
cb();
|
||||
};
|
||||
i18n.on('initialized', initialized);
|
||||
}
|
||||
};
|
||||
|
||||
export const loadNamespaces = (i18n, ns, cb) => {
|
||||
i18n.loadNamespaces(ns, loadedClb(i18n, cb));
|
||||
};
|
||||
|
||||
// should work with I18NEXT >= v22.5.0
|
||||
export const loadLanguages = (i18n, lng, ns, cb) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
if (isString(ns)) ns = [ns];
|
||||
ns.forEach((n) => {
|
||||
if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
|
||||
});
|
||||
i18n.loadLanguages(lng, loadedClb(i18n, cb));
|
||||
};
|
||||
|
||||
// WAIT A LITTLE FOR I18NEXT BEING UPDATED IN THE WILD, before removing this old i18next version support
|
||||
const oldI18nextHasLoadedNamespace = (ns, i18n, options = {}) => {
|
||||
const lng = i18n.languages[0];
|
||||
const fallbackLng = i18n.options ? i18n.options.fallbackLng : false;
|
||||
const lastLng = i18n.languages[i18n.languages.length - 1];
|
||||
|
||||
// we're in cimode so this shall pass
|
||||
if (lng.toLowerCase() === 'cimode') return true;
|
||||
|
||||
const loadNotPending = (l, n) => {
|
||||
const loadState = i18n.services.backendConnector.state[`${l}|${n}`];
|
||||
return loadState === -1 || loadState === 2;
|
||||
};
|
||||
|
||||
// bound to trigger on event languageChanging
|
||||
// so set ready to false while we are changing the language
|
||||
// and namespace pending (depends on having a backend)
|
||||
if (
|
||||
options.bindI18n &&
|
||||
options.bindI18n.indexOf('languageChanging') > -1 &&
|
||||
i18n.services.backendConnector.backend &&
|
||||
i18n.isLanguageChangingTo &&
|
||||
!loadNotPending(i18n.isLanguageChangingTo, ns)
|
||||
)
|
||||
return false;
|
||||
|
||||
// loaded -> SUCCESS
|
||||
if (i18n.hasResourceBundle(lng, ns)) return true;
|
||||
|
||||
// were not loading at all -> SEMI SUCCESS
|
||||
if (
|
||||
!i18n.services.backendConnector.backend ||
|
||||
(i18n.options.resources && !i18n.options.partialBundledLanguages)
|
||||
)
|
||||
return true;
|
||||
|
||||
// failed loading ns - but at least fallback is not pending -> SEMI SUCCESS
|
||||
if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
export const hasLoadedNamespace = (ns, i18n, options = {}) => {
|
||||
if (!i18n.languages || !i18n.languages.length) {
|
||||
warnOnce('i18n.languages were undefined or empty', i18n.languages);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ignoreJSONStructure was introduced in v20.0.0 (MARCH 2021)
|
||||
const isNewerI18next = i18n.options.ignoreJSONStructure !== undefined;
|
||||
if (!isNewerI18next) {
|
||||
// WAIT A LITTLE FOR I18NEXT BEING UPDATED IN THE WILD, before removing this old i18next version support
|
||||
return oldI18nextHasLoadedNamespace(ns, i18n, options);
|
||||
}
|
||||
|
||||
// IN I18NEXT > v19.4.5 WE CAN (INTRODUCED JUNE 2020)
|
||||
return i18n.hasLoadedNamespace(ns, {
|
||||
lng: options.lng,
|
||||
precheck: (i18nInstance, loadNotPending) => {
|
||||
if (
|
||||
options.bindI18n &&
|
||||
options.bindI18n.indexOf('languageChanging') > -1 &&
|
||||
i18nInstance.services.backendConnector.backend &&
|
||||
i18nInstance.isLanguageChangingTo &&
|
||||
!loadNotPending(i18nInstance.isLanguageChangingTo, ns)
|
||||
)
|
||||
return false;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const getDisplayName = (Component) =>
|
||||
Component.displayName ||
|
||||
Component.name ||
|
||||
(isString(Component) && Component.length > 0 ? Component : 'Unknown');
|
||||
|
||||
export const isString = (obj) => typeof obj === 'string';
|
||||
|
||||
export const isObject = (obj) => typeof obj === 'object' && obj !== null;
|
||||
21
frontend/node_modules/react-i18next/src/withSSR.js
generated
vendored
Normal file
21
frontend/node_modules/react-i18next/src/withSSR.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import { createElement } from 'react';
|
||||
import { useSSR } from './useSSR.js';
|
||||
import { composeInitialProps } from './context.js';
|
||||
import { getDisplayName } from './utils.js';
|
||||
|
||||
export const withSSR = () =>
|
||||
function Extend(WrappedComponent) {
|
||||
function I18nextWithSSR({ initialI18nStore, initialLanguage, ...rest }) {
|
||||
useSSR(initialI18nStore, initialLanguage);
|
||||
|
||||
return createElement(WrappedComponent, {
|
||||
...rest,
|
||||
});
|
||||
}
|
||||
|
||||
I18nextWithSSR.getInitialProps = composeInitialProps(WrappedComponent);
|
||||
I18nextWithSSR.displayName = `withI18nextSSR(${getDisplayName(WrappedComponent)})`;
|
||||
I18nextWithSSR.WrappedComponent = WrappedComponent;
|
||||
|
||||
return I18nextWithSSR;
|
||||
};
|
||||
35
frontend/node_modules/react-i18next/src/withTranslation.js
generated
vendored
Normal file
35
frontend/node_modules/react-i18next/src/withTranslation.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import { createElement, forwardRef as forwardRefReact } from 'react';
|
||||
import { useTranslation } from './useTranslation.js';
|
||||
import { getDisplayName } from './utils.js';
|
||||
|
||||
export const withTranslation = (ns, options = {}) =>
|
||||
function Extend(WrappedComponent) {
|
||||
function I18nextWithTranslation({ forwardedRef, ...rest }) {
|
||||
const [t, i18n, ready] = useTranslation(ns, { ...rest, keyPrefix: options.keyPrefix });
|
||||
|
||||
const passDownProps = {
|
||||
...rest,
|
||||
t,
|
||||
i18n,
|
||||
tReady: ready,
|
||||
};
|
||||
if (options.withRef && forwardedRef) {
|
||||
passDownProps.ref = forwardedRef;
|
||||
} else if (!options.withRef && forwardedRef) {
|
||||
passDownProps.forwardedRef = forwardedRef;
|
||||
}
|
||||
return createElement(WrappedComponent, passDownProps);
|
||||
}
|
||||
|
||||
I18nextWithTranslation.displayName = `withI18nextTranslation(${getDisplayName(
|
||||
WrappedComponent,
|
||||
)})`;
|
||||
|
||||
I18nextWithTranslation.WrappedComponent = WrappedComponent;
|
||||
|
||||
const forwardRef = (props, ref) =>
|
||||
// eslint-disable-next-line prefer-object-spread
|
||||
createElement(I18nextWithTranslation, Object.assign({}, props, { forwardedRef: ref }));
|
||||
|
||||
return options.withRef ? forwardRefReact(forwardRef) : I18nextWithTranslation;
|
||||
};
|
||||
Reference in New Issue
Block a user