worked on GarageApp stuff
This commit is contained in:
parent
60aaf17af3
commit
eb606572b0
51919 changed files with 2168177 additions and 18 deletions
74
node_modules/react-i18next/.eslintrc.json
generated
vendored
Normal file
74
node_modules/react-i18next/.eslintrc.json
generated
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"extends": ["airbnb", "prettier"],
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 8,
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true,
|
||||
"impliedStrict": true,
|
||||
"classes": true
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
"reportUnusedDisableDirectives": true,
|
||||
"rules": {
|
||||
"no-debugger": 0,
|
||||
"no-alert": 0,
|
||||
"no-unused-vars": [1, { "argsIgnorePattern": "res|next|^err" }],
|
||||
"prefer-arrow-callback": ["error", { "allowNamedFunctions": true }],
|
||||
"prefer-const": ["error", { "destructuring": "all" }],
|
||||
"arrow-body-style": [2, "as-needed"],
|
||||
"no-unused-expressions": [2, { "allowTaggedTemplates": true }],
|
||||
"no-param-reassign": [2, { "props": false }],
|
||||
"no-console": 0,
|
||||
"no-use-before-define": 0,
|
||||
"no-nested-ternary": 0,
|
||||
"import/prefer-default-export": 0,
|
||||
"import/no-extraneous-dependencies": 1,
|
||||
"import/no-named-as-default-member": 1,
|
||||
"import": 0,
|
||||
"func-names": 0,
|
||||
"space-before-function-paren": 0,
|
||||
"comma-dangle": 0,
|
||||
"max-len": 0,
|
||||
"import/extensions": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"consistent-return": 0,
|
||||
"react/display-name": 1,
|
||||
"react/no-array-index-key": 0,
|
||||
"react/jsx-no-useless-fragment": ["error", { "allowExpressions": true }],
|
||||
"react/react-in-jsx-scope": 0,
|
||||
"react/prefer-stateless-function": 0,
|
||||
"react/forbid-prop-types": 0,
|
||||
"react/no-unescaped-entities": 0,
|
||||
"react/prop-types": 0,
|
||||
"jsx-a11y/accessible-emoji": 0,
|
||||
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
|
||||
"react/no-unknown-property": ["error", { "ignore": ["i18nIsDynamicList"] }],
|
||||
"radix": 0,
|
||||
"no-shadow": [
|
||||
2,
|
||||
{ "hoist": "all", "allow": ["resolve", "reject", "done", "next", "err", "error"] }
|
||||
],
|
||||
"quotes": [2, "single", { "avoidEscape": true, "allowTemplateLiterals": true }],
|
||||
"jsx-a11y/href-no-hash": "off",
|
||||
"jsx-a11y/anchor-is-valid": ["warn", { "aspects": ["invalidHref"] }],
|
||||
"react/jsx-props-no-spreading": 0
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["test/*"],
|
||||
"extends": ["plugin:testing-library/react", "plugin:jest-dom/recommended"],
|
||||
"globals": {
|
||||
"globalThis": false
|
||||
},
|
||||
"rules": {
|
||||
"testing-library/no-node-access": ["error", { "allowContainerFirstChild": true }],
|
||||
"testing-library/no-manual-cleanup": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
1
node_modules/react-i18next/.husky/pre-commit
generated
vendored
Normal file
1
node_modules/react-i18next/.husky/pre-commit
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
npm exec lint-staged
|
||||
4
node_modules/react-i18next/.prettierignore
generated
vendored
Normal file
4
node_modules/react-i18next/.prettierignore
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
**/dist/
|
||||
**/react-i18next.js
|
||||
**/react-i18next.min.js
|
||||
**/example/
|
||||
1416
node_modules/react-i18next/CHANGELOG.md
generated
vendored
Normal file
1416
node_modules/react-i18next/CHANGELOG.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
22
node_modules/react-i18next/LICENSE
generated
vendored
Normal file
22
node_modules/react-i18next/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2025 i18next
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
181
node_modules/react-i18next/README.md
generated
vendored
Normal file
181
node_modules/react-i18next/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
# react-i18next [](https://twitter.com/intent/tweet?text=Awesome%20react-i18next%20for%20react.js%20based%20on%20i18next%20internationalization%20ecosystem%20&url=https://github.com/i18next/react-i18next&via=jamuhl&hashtags=i18n,reactjs,js,dev)
|
||||
|
||||
[](https://github.com/i18next/react-i18next/actions/workflows/CI.yml)
|
||||
[](https://codeclimate.com/github/i18next/react-i18next)
|
||||
[](https://coveralls.io/github/i18next/react-i18next)
|
||||
[![Quality][quality-badge]][quality-url]
|
||||
[![npm][npm-dl-badge]][npm-url]
|
||||
|
||||
[npm-icon]: https://nodei.co/npm/react-i18next.png?downloads=true
|
||||
[npm-url]: https://npmjs.org/package/react-i18next
|
||||
[quality-badge]: https://npm.packagequality.com/shield/react-i18next.svg
|
||||
[quality-url]: https://packagequality.com/#?package=react-i18next
|
||||
[npm-dl-badge]: https://img.shields.io/npm/dw/react-i18next
|
||||
|
||||
### IMPORTANT:
|
||||
|
||||
Master Branch is the newest version using hooks (>= v10).
|
||||
|
||||
```bash
|
||||
$ >=v10.0.0
|
||||
npm i react-i18next
|
||||
```
|
||||
|
||||
**react-native: To use hooks within react-native, you must use react-native v0.59.0 or higher**
|
||||
|
||||
For the legacy version please use the [v9.x.x Branch](https://github.com/i18next/react-i18next/tree/v9.x.x)
|
||||
|
||||
```bash
|
||||
$ v9.0.10 (legacy)
|
||||
npm i react-i18next@legacy
|
||||
```
|
||||
|
||||
### Documentation
|
||||
|
||||
The documentation is published on [react.i18next.com](https://react.i18next.com) and PR changes can be supplied [here](https://github.com/i18next/react-i18next-gitbook).
|
||||
|
||||
The general i18next documentation is published on [www.i18next.com](https://www.i18next.com) and PR changes can be supplied [here](https://github.com/i18next/i18next-gitbook).
|
||||
|
||||
### What will my code look like?
|
||||
|
||||
**Before:** Your react code would have looked something like:
|
||||
|
||||
```html
|
||||
...
|
||||
<div>Just simple content</div>
|
||||
<div>
|
||||
Hello <strong title="this is your name">{name}</strong>, you have {count} unread message(s). <Link to="/msgs">Go to messages</Link>.
|
||||
</div>
|
||||
...
|
||||
```
|
||||
|
||||
**After:** With the trans component just change it to:
|
||||
|
||||
```html
|
||||
...
|
||||
<div>{t('simpleContent')}</div>
|
||||
<Trans i18nKey="userMessagesUnread" count={count}>
|
||||
Hello <strong title={t('nameTitle')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>.
|
||||
</Trans>
|
||||
...
|
||||
```
|
||||
|
||||
### 📖 What others say
|
||||
|
||||
- [How to properly internationalize a React application using i18next](https://locize.com/blog/react-i18next/) by Adriano Raiano
|
||||
- [I18n with React and i18next](https://alligator.io/react/i18n-with-react-and-i18next) via Alligator.io by Danny Hurlburt
|
||||
- [Ultimate Localization of React (Mobx) App with i18next](https://itnext.io/ultimate-localization-of-react-mobx-app-with-i18next-efab77712149) via itnext.io by Viktor Shevchenko
|
||||
- [Internationalization for react done right Using the i18next i18n ecosystem](https://reactjsexample.com/internationalization-for-react-done-right-using-the-i18next-i18n-ecosystem/) via reactjsexample.com
|
||||
- [How to translate React application with react-i18next](https://codetain.com/blog/how-to-translate-react-application-with-react-i18next/) via codetain.co by Norbert Suski
|
||||
- [Building i18n with Gatsby](https://www.gatsbyjs.org/blog/2017-10-17-building-i18n-with-gatsby/) via gatsbyjs.org by Samuel Goudie
|
||||
- [Get your react.js application translated with style](https://medium.com/@jamuhl/get-your-react-js-application-translated-with-style-4ad090aefc2c) by Jan Mühlemann
|
||||
- [Translate your expo.io / react-native mobile application](https://medium.com/@jamuhl/translate-your-expo-io-react-native-mobile-application-aa220b2362d2) by Jan Mühlemann
|
||||
- You're welcome to share your story...
|
||||
|
||||
### Why i18next?
|
||||
|
||||
- **Simplicity:** no need to change your webpack configuration or add additional babel transpilers, just use create-react-app and go.
|
||||
- **Production ready** we know there are more needs for production than just doing i18n on the clientside, so we offer wider support on [serverside](https://www.i18next.com/overview/supported-frameworks) too (nodejs, php, ruby, .net, ...). **Learn once - translate everywhere**.
|
||||
- **Beyond i18n** comes with [locize](https://locize.com) bridging the gap between development and translations - covering the whole translation process.
|
||||
|
||||

|
||||
|
||||
### Localization workflow
|
||||
|
||||
Want to learn more about how seamless your internationalization and translation process can be?
|
||||
|
||||
[](https://youtu.be/osScyaGMVqo)
|
||||
|
||||
[watch the video](https://youtu.be/osScyaGMVqo)
|
||||
|
||||
### Installation
|
||||
|
||||
Source can be loaded via [npm](https://www.npmjs.com/package/react-i18next) or [downloaded](https://github.com/i18next/react-i18next/blob/master/react-i18next.min.js) from this repo.
|
||||
|
||||
```
|
||||
# npm package
|
||||
$ npm install react-i18next
|
||||
```
|
||||
|
||||
- If you don't use a module loader it will be added to `window.reactI18next`
|
||||
|
||||
### Do you like to read a more complete step by step tutorial?
|
||||
|
||||
[Here](https://locize.com/blog/react-i18next/) you'll find a simple tutorial on how to best use react-i18next.
|
||||
Some basics of i18next and some cool possibilities on how to optimize your localization workflow.
|
||||
|
||||
### Examples
|
||||
|
||||
- [Example react](https://github.com/i18next/react-i18next/tree/master/example/react)
|
||||
- [React examples with typescript](https://github.com/i18next/react-i18next/tree/master/example/react-typescript)
|
||||
- [Example locize.com](https://github.com/i18next/react-i18next/tree/master/example/locize)
|
||||
|
||||
#### v9 samples
|
||||
|
||||
- [Example react](https://github.com/i18next/react-i18next/tree/v9.x.x/example/react)
|
||||
- [Example preact](https://github.com/i18next/react-i18next/tree/v9.x.x/example/preact)
|
||||
- [Example react-native](https://github.com/i18next/react-i18next/tree/v9.x.x/example/reactnative-expo)
|
||||
- [Example expo.io](https://github.com/i18next/react-i18next/tree/v9.x.x/example/reactnative-expo)
|
||||
- [Example next.js](https://github.com/i18next/react-i18next/tree/v9.x.x/example/nextjs)
|
||||
- [Example razzle](https://github.com/i18next/react-i18next/tree/v9.x.x/example/razzle-ssr)
|
||||
- [Example hashbase / beaker browser](https://github.com/i18next/react-i18next/tree/v9.x.x/example/dat)
|
||||
- [Example storybook](https://github.com/i18next/react-i18next/tree/v9.x.x/example/storybook)
|
||||
- [Example locize.com](https://github.com/i18next/react-i18next/tree/v9.x.x/example/locize)
|
||||
- [Example test with jest](https://github.com/i18next/react-i18next/tree/v9.x.x/example/test-jest)
|
||||
|
||||
### Requirements
|
||||
|
||||
- react >= **16.8.0**
|
||||
- react-dom >= **16.8.0**
|
||||
- react-native >= **0.59.0**
|
||||
- i18next >= **10.0.0** (typescript users: >=17.0.9)
|
||||
|
||||
#### v9
|
||||
|
||||
- react >= **0.14.0** (in case of < v16 or preact you will need to define parent in [Trans component](https://react.i18next.com/legacy-v9/trans-component#trans-props) or globally in [i18next.react options](https://react.i18next.com/legacy-v9/trans-component#additional-options-on-i-18-next-init))
|
||||
- i18next >= **2.0.0**
|
||||
|
||||
## Core Contributors
|
||||
|
||||
Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="http://twitter.com/jamuhl"><img src="https://avatars3.githubusercontent.com/u/977772?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jan Mühlemann</b></sub></a><br /><a href="https://github.com/i18next/react-i18next/commits?author=jamuhl" title="Code">💻</a> <a href="#example-jamuhl" title="Examples">💡</a> <a href="https://github.com/i18next/react-i18next/pulls?q=is%3Apr+reviewed-by%3Ajamuhl+" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/i18next/react-i18next/commits?author=jamuhl" title="Documentation">📖</a> <a href="#question-jamuhl" title="Answering Questions">💬</a></td>
|
||||
<td align="center"><a href="http://twitter.com/#!/adrirai"><img src="https://avatars0.githubusercontent.com/u/1086194?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Adriano Raiano</b></sub></a><br /><a href="https://github.com/i18next/react-i18next/commits?author=adrai" title="Code">💻</a> <a href="#example-adrai" title="Examples">💡</a> <a href="https://github.com/i18next/react-i18next/pulls?q=is%3Apr+reviewed-by%3Aadrai+" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/i18next/react-i18next/commits?author=adrai" title="Documentation">📖</a> <a href="#question-adrai" title="Answering Questions">💬</a></td>
|
||||
<td align="center"><a href="https://github.com/pedrodurek"><img src="https://avatars1.githubusercontent.com/u/12190482?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pedro Durek</b></sub></a><br /><a href="https://github.com/i18next/react-i18next/commits?author=pedrodurek" title="Code">💻</a> <a href="#example-pedrodurek" title="Examples">💡</a> <a href="https://github.com/i18next/react-i18next/pulls?q=is%3Apr+reviewed-by%3Apedrodurek+" title="Reviewed Pull Requests">👀</a> <a href="#question-pedrodurek" title="Answering Questions">💬</a></td>
|
||||
<td align="center"><a href="https://tigerabrodi.dev/"><img src="https://avatars1.githubusercontent.com/u/49603590?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tiger Abrodi</b></sub></a><br /><a href="https://github.com/i18next/react-i18next/commits?author=tigerabrodi" title="Code">💻</a> <a href="https://github.com/i18next/react-i18next/pulls?q=is%3Apr+reviewed-by%3Atigerabrodi" title="Reviewed Pull Requests">👀</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind are welcome!
|
||||
|
||||
---
|
||||
|
||||
<h3 align="center">Gold Sponsors</h3>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://locize.com/" target="_blank">
|
||||
<img src="https://raw.githubusercontent.com/i18next/i18next/master/assets/locize_sponsor_240.gif" width="240px">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**localization as a service - locize.com**
|
||||
|
||||
Needing a translation management? Want to edit your translations with an InContext Editor? Use the original provided to you by the maintainers of i18next!
|
||||
|
||||

|
||||
|
||||
By using [locize](http://locize.com/?utm_source=react_i18next_readme&utm_medium=github) you directly support the future of i18next and react-i18next.
|
||||
|
||||
---
|
||||
1
node_modules/react-i18next/TransWithoutContext.d.mts
generated
vendored
Normal file
1
node_modules/react-i18next/TransWithoutContext.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './TransWithoutContext.js';
|
||||
73
node_modules/react-i18next/TransWithoutContext.d.ts
generated
vendored
Normal file
73
node_modules/react-i18next/TransWithoutContext.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import type { i18n, ParseKeys, Namespace, TypeOptions, TOptions, TFunction } from 'i18next';
|
||||
import * as React from 'react';
|
||||
|
||||
type _DefaultNamespace = TypeOptions['defaultNS'];
|
||||
|
||||
type TransChild = React.ReactNode | Record<string, unknown>;
|
||||
export type TransProps<
|
||||
Key extends ParseKeys<Ns, TOpt, KPrefix>,
|
||||
Ns extends Namespace = _DefaultNamespace,
|
||||
KPrefix = undefined,
|
||||
TContext extends string | undefined = undefined,
|
||||
TOpt extends TOptions & { context?: TContext } = { context: TContext },
|
||||
E = React.HTMLProps<HTMLDivElement>,
|
||||
> = E & {
|
||||
children?: TransChild | readonly TransChild[];
|
||||
components?: readonly React.ReactElement[] | { readonly [tagName: string]: React.ReactElement };
|
||||
count?: number;
|
||||
context?: TContext;
|
||||
defaults?: string;
|
||||
i18n?: i18n;
|
||||
i18nKey?: Key | Key[];
|
||||
ns?: Ns;
|
||||
parent?: string | React.ComponentType<any> | null; // used in React.createElement if not null
|
||||
tOptions?: TOpt;
|
||||
values?: {};
|
||||
shouldUnescape?: boolean;
|
||||
t?: TFunction<Ns, KPrefix>;
|
||||
};
|
||||
|
||||
export function Trans<
|
||||
Key extends ParseKeys<Ns, TOpt, KPrefix>,
|
||||
Ns extends Namespace = _DefaultNamespace,
|
||||
KPrefix = undefined,
|
||||
TContext extends string | undefined = undefined,
|
||||
TOpt extends TOptions & { context?: TContext } = { context: TContext },
|
||||
E = React.HTMLProps<HTMLDivElement>,
|
||||
>(props: TransProps<Key, Ns, KPrefix, TContext, TOpt, E>): React.ReactElement;
|
||||
|
||||
export type ErrorCode =
|
||||
| 'NO_I18NEXT_INSTANCE'
|
||||
| 'NO_LANGUAGES'
|
||||
| 'DEPRECATED_OPTION'
|
||||
| 'TRANS_NULL_VALUE'
|
||||
| 'TRANS_INVALID_OBJ'
|
||||
| 'TRANS_INVALID_VAR'
|
||||
| 'TRANS_INVALID_COMPONENTS';
|
||||
|
||||
export type ErrorMeta = {
|
||||
code: ErrorCode;
|
||||
i18nKey?: string;
|
||||
[x: string]: any;
|
||||
};
|
||||
|
||||
/**
|
||||
* Use to type the logger arguments
|
||||
* @example
|
||||
* ```
|
||||
* import type { ErrorArgs } from 'react-i18next';
|
||||
*
|
||||
* const logger = {
|
||||
* // ....
|
||||
* warn: function (...args: ErrorArgs) {
|
||||
* if (args[1]?.code === 'TRANS_INVALID_OBJ') {
|
||||
* const [msg, { i18nKey, ...rest }] = args;
|
||||
* return log(i18nKey, msg, rest);
|
||||
* }
|
||||
* log(...args);
|
||||
* }
|
||||
* }
|
||||
* i18n.use(logger).use(i18nReactPlugin).init({...});
|
||||
* ```
|
||||
*/
|
||||
export type ErrorArgs = readonly [string, ErrorMeta | undefined, ...any[]];
|
||||
867
node_modules/react-i18next/dist/amd/react-i18next.js
generated
vendored
Normal file
867
node_modules/react-i18next/dist/amd/react-i18next.js
generated
vendored
Normal file
|
|
@ -0,0 +1,867 @@
|
|||
define(['exports', 'react'], (function (exports, react) { 'use strict';
|
||||
|
||||
function getDefaultExportFromCjs (x) {
|
||||
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
||||
}
|
||||
|
||||
var voidElements = {
|
||||
"area": true,
|
||||
"base": true,
|
||||
"br": true,
|
||||
"col": true,
|
||||
"embed": true,
|
||||
"hr": true,
|
||||
"img": true,
|
||||
"input": true,
|
||||
"link": true,
|
||||
"meta": true,
|
||||
"param": true,
|
||||
"source": true,
|
||||
"track": true,
|
||||
"wbr": true
|
||||
};
|
||||
|
||||
var e = /*@__PURE__*/getDefaultExportFromCjs(voidElements);
|
||||
|
||||
var t = /\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?(".*?"|'.*?')/g;
|
||||
function n(n) {
|
||||
var r = {
|
||||
type: "tag",
|
||||
name: "",
|
||||
voidElement: false,
|
||||
attrs: {},
|
||||
children: []
|
||||
},
|
||||
i = n.match(/<\/?([^\s]+?)[/\s>]/);
|
||||
if (i && (r.name = i[1], (e[i[1]] || "/" === n.charAt(n.length - 2)) && (r.voidElement = true), r.name.startsWith("!--"))) {
|
||||
var s = n.indexOf("--\x3e");
|
||||
return {
|
||||
type: "comment",
|
||||
comment: -1 !== s ? n.slice(4, s) : ""
|
||||
};
|
||||
}
|
||||
for (var a = new RegExp(t), c = null; null !== (c = a.exec(n));) if (c[0].trim()) if (c[1]) {
|
||||
var o = c[1].trim(),
|
||||
l = [o, ""];
|
||||
o.indexOf("=") > -1 && (l = o.split("=")), r.attrs[l[0]] = l[1], a.lastIndex--;
|
||||
} else c[2] && (r.attrs[c[2]] = c[3].trim().substring(1, c[3].length - 1));
|
||||
return r;
|
||||
}
|
||||
var r = /<[a-zA-Z0-9\-\!\/](?:"[^"]*"|'[^']*'|[^'">])*>/g,
|
||||
i = /^\s*$/,
|
||||
s = Object.create(null);
|
||||
function a(e, t) {
|
||||
switch (t.type) {
|
||||
case "text":
|
||||
return e + t.content;
|
||||
case "tag":
|
||||
return e += "<" + t.name + (t.attrs ? function (e) {
|
||||
var t = [];
|
||||
for (var n in e) t.push(n + '="' + e[n] + '"');
|
||||
return t.length ? " " + t.join(" ") : "";
|
||||
}(t.attrs) : "") + (t.voidElement ? "/>" : ">"), t.voidElement ? e : e + t.children.reduce(a, "") + "</" + t.name + ">";
|
||||
case "comment":
|
||||
return e + "\x3c!--" + t.comment + "--\x3e";
|
||||
}
|
||||
}
|
||||
var c = {
|
||||
parse: function (e, t) {
|
||||
t || (t = {}), t.components || (t.components = s);
|
||||
var a,
|
||||
c = [],
|
||||
o = [],
|
||||
l = -1,
|
||||
m = false;
|
||||
if (0 !== e.indexOf("<")) {
|
||||
var u = e.indexOf("<");
|
||||
c.push({
|
||||
type: "text",
|
||||
content: -1 === u ? e : e.substring(0, u)
|
||||
});
|
||||
}
|
||||
return e.replace(r, function (r, s) {
|
||||
if (m) {
|
||||
if (r !== "</" + a.name + ">") return;
|
||||
m = false;
|
||||
}
|
||||
var u,
|
||||
f = "/" !== r.charAt(1),
|
||||
h = r.startsWith("\x3c!--"),
|
||||
p = s + r.length,
|
||||
d = e.charAt(p);
|
||||
if (h) {
|
||||
var v = n(r);
|
||||
return l < 0 ? (c.push(v), c) : ((u = o[l]).children.push(v), c);
|
||||
}
|
||||
if (f && (l++, "tag" === (a = n(r)).type && t.components[a.name] && (a.type = "component", m = true), a.voidElement || m || !d || "<" === d || a.children.push({
|
||||
type: "text",
|
||||
content: e.slice(p, e.indexOf("<", p))
|
||||
}), 0 === l && c.push(a), (u = o[l - 1]) && u.children.push(a), o[l] = a), (!f || a.voidElement) && (l > -1 && (a.voidElement || a.name === r.slice(2, -1)) && (l--, a = -1 === l ? c : o[l]), !m && "<" !== d && d)) {
|
||||
u = -1 === l ? c : o[l].children;
|
||||
var x = e.indexOf("<", p),
|
||||
g = e.slice(p, -1 === x ? void 0 : x);
|
||||
i.test(g) && (g = " "), (x > -1 && l + u.length >= 0 || " " !== g) && u.push({
|
||||
type: "text",
|
||||
content: g
|
||||
});
|
||||
}
|
||||
}), c;
|
||||
},
|
||||
stringify: function (e) {
|
||||
return e.reduce(function (e, t) {
|
||||
return e + a("", t);
|
||||
}, "");
|
||||
}
|
||||
};
|
||||
|
||||
const warn = (i18n, code, msg, rest) => {
|
||||
const args = [msg, {
|
||||
code,
|
||||
...(rest || {})
|
||||
}];
|
||||
if (i18n?.services?.logger?.forward) {
|
||||
return i18n.services.logger.forward(args, 'warn', 'react-i18next::', true);
|
||||
}
|
||||
if (isString(args[0])) args[0] = `react-i18next:: ${args[0]}`;
|
||||
if (i18n?.services?.logger?.warn) {
|
||||
i18n.services.logger.warn(...args);
|
||||
} else if (console?.warn) {
|
||||
console.warn(...args);
|
||||
}
|
||||
};
|
||||
const alreadyWarned = {};
|
||||
const warnOnce = (i18n, code, msg, rest) => {
|
||||
if (isString(msg) && alreadyWarned[msg]) return;
|
||||
if (isString(msg)) alreadyWarned[msg] = new Date();
|
||||
warn(i18n, code, msg, rest);
|
||||
};
|
||||
const loadedClb = (i18n, cb) => () => {
|
||||
if (i18n.isInitialized) {
|
||||
cb();
|
||||
} else {
|
||||
const initialized = () => {
|
||||
setTimeout(() => {
|
||||
i18n.off('initialized', initialized);
|
||||
}, 0);
|
||||
cb();
|
||||
};
|
||||
i18n.on('initialized', initialized);
|
||||
}
|
||||
};
|
||||
const loadNamespaces = (i18n, ns, cb) => {
|
||||
i18n.loadNamespaces(ns, loadedClb(i18n, cb));
|
||||
};
|
||||
const loadLanguages = (i18n, lng, ns, cb) => {
|
||||
if (isString(ns)) ns = [ns];
|
||||
if (i18n.options.preload && i18n.options.preload.indexOf(lng) > -1) return loadNamespaces(i18n, ns, cb);
|
||||
ns.forEach(n => {
|
||||
if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
|
||||
});
|
||||
i18n.loadLanguages(lng, loadedClb(i18n, cb));
|
||||
};
|
||||
const hasLoadedNamespace = (ns, i18n, options = {}) => {
|
||||
if (!i18n.languages || !i18n.languages.length) {
|
||||
warnOnce(i18n, 'NO_LANGUAGES', 'i18n.languages were undefined or empty', {
|
||||
languages: i18n.languages
|
||||
});
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
});
|
||||
};
|
||||
const getDisplayName = Component => Component.displayName || Component.name || (isString(Component) && Component.length > 0 ? Component : 'Unknown');
|
||||
const isString = obj => typeof obj === 'string';
|
||||
const isObject = obj => typeof obj === 'object' && obj !== null;
|
||||
|
||||
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];
|
||||
const unescape = text => text.replace(matchHtmlEntity, unescapeHtmlEntity);
|
||||
|
||||
let defaultOptions = {
|
||||
bindI18n: 'languageChanged',
|
||||
bindI18nStore: '',
|
||||
transEmptyNodeValue: '',
|
||||
transSupportBasicHtmlNodes: true,
|
||||
transWrapTextNodes: '',
|
||||
transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p'],
|
||||
useSuspense: true,
|
||||
unescape
|
||||
};
|
||||
const setDefaults = (options = {}) => {
|
||||
defaultOptions = {
|
||||
...defaultOptions,
|
||||
...options
|
||||
};
|
||||
};
|
||||
const getDefaults = () => defaultOptions;
|
||||
|
||||
let i18nInstance;
|
||||
const setI18n = instance => {
|
||||
i18nInstance = instance;
|
||||
};
|
||||
const getI18n = () => i18nInstance;
|
||||
|
||||
const hasChildren = (node, checkLength) => {
|
||||
if (!node) return false;
|
||||
const base = node.props?.children ?? node.children;
|
||||
if (checkLength) return base.length > 0;
|
||||
return !!base;
|
||||
};
|
||||
const getChildren = node => {
|
||||
if (!node) return [];
|
||||
const children = node.props?.children ?? node.children;
|
||||
return node.props?.i18nIsDynamicList ? getAsArray(children) : children;
|
||||
};
|
||||
const hasValidReactChildren = children => Array.isArray(children) && children.every(react.isValidElement);
|
||||
const getAsArray = data => Array.isArray(data) ? data : [data];
|
||||
const mergeProps = (source, target) => {
|
||||
const newTarget = {
|
||||
...target
|
||||
};
|
||||
newTarget.props = Object.assign(source.props, target.props);
|
||||
return newTarget;
|
||||
};
|
||||
const nodesToString = (children, i18nOptions, i18n, i18nKey) => {
|
||||
if (!children) return '';
|
||||
let stringNode = '';
|
||||
const childrenArray = getAsArray(children);
|
||||
const keepArray = i18nOptions?.transSupportBasicHtmlNodes ? i18nOptions.transKeepBasicHtmlNodesFor ?? [] : [];
|
||||
childrenArray.forEach((child, childIndex) => {
|
||||
if (isString(child)) {
|
||||
stringNode += `${child}`;
|
||||
return;
|
||||
}
|
||||
if (react.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) {
|
||||
stringNode += `<${type}/>`;
|
||||
return;
|
||||
}
|
||||
if (!childChildren && (!shouldKeepChild || childPropsCount) || props.i18nIsDynamicList) {
|
||||
stringNode += `<${childIndex}></${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (shouldKeepChild && childPropsCount === 1 && isString(childChildren)) {
|
||||
stringNode += `<${type}>${childChildren}</${type}>`;
|
||||
return;
|
||||
}
|
||||
const content = nodesToString(childChildren, i18nOptions, i18n, i18nKey);
|
||||
stringNode += `<${childIndex}>${content}</${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (child === null) {
|
||||
warn(i18n, 'TRANS_NULL_VALUE', `Passed in a null value as child`, {
|
||||
i18nKey
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isObject(child)) {
|
||||
const {
|
||||
format,
|
||||
...clone
|
||||
} = child;
|
||||
const keys = Object.keys(clone);
|
||||
if (keys.length === 1) {
|
||||
const value = format ? `${keys[0]}, ${format}` : keys[0];
|
||||
stringNode += `{{${value}}}`;
|
||||
return;
|
||||
}
|
||||
warn(i18n, 'TRANS_INVALID_OBJ', `Invalid child - Object should only have keys {{ value, format }} (format is optional).`, {
|
||||
i18nKey,
|
||||
child
|
||||
});
|
||||
return;
|
||||
}
|
||||
warn(i18n, 'TRANS_INVALID_VAR', `Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.`, {
|
||||
i18nKey,
|
||||
child
|
||||
});
|
||||
});
|
||||
return stringNode;
|
||||
};
|
||||
const renderNodes = (children, knownComponentsMap, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
|
||||
if (targetString === '') return [];
|
||||
const keepArray = i18nOptions.transKeepBasicHtmlNodesFor || [];
|
||||
const emptyChildrenButNeedsHandling = targetString && new RegExp(keepArray.map(keep => `<${keep}`).join('|')).test(targetString);
|
||||
if (!children && !knownComponentsMap && !emptyChildrenButNeedsHandling && !shouldUnescape) return [targetString];
|
||||
const data = knownComponentsMap ?? {};
|
||||
const getData = childs => {
|
||||
const childrenArray = getAsArray(childs);
|
||||
childrenArray.forEach(child => {
|
||||
if (isString(child)) return;
|
||||
if (hasChildren(child)) getData(getChildren(child));else if (isObject(child) && !react.isValidElement(child)) Object.assign(data, child);
|
||||
});
|
||||
};
|
||||
getData(children);
|
||||
const ast = c.parse(`<0>${targetString}</0>`);
|
||||
const opts = {
|
||||
...data,
|
||||
...combinedTOpts
|
||||
};
|
||||
const renderInner = (child, node, rootReactNode) => {
|
||||
const childs = getChildren(child);
|
||||
const mappedChildren = mapAST(childs, node.children, rootReactNode);
|
||||
return hasValidReactChildren(childs) && mappedChildren.length === 0 || child.props?.i18nIsDynamicList ? childs : mappedChildren;
|
||||
};
|
||||
const pushTranslatedJSX = (child, inner, mem, i, isVoid) => {
|
||||
if (child.dummy) {
|
||||
child.children = inner;
|
||||
mem.push(react.cloneElement(child, {
|
||||
key: i
|
||||
}, isVoid ? undefined : inner));
|
||||
} else {
|
||||
mem.push(...react.Children.map([child], c => {
|
||||
const props = {
|
||||
...c.props
|
||||
};
|
||||
delete props.i18nIsDynamicList;
|
||||
return react.createElement(c.type, {
|
||||
...props,
|
||||
key: i,
|
||||
ref: c.props.ref ?? c.ref
|
||||
}, isVoid ? null : inner);
|
||||
}));
|
||||
}
|
||||
};
|
||||
const mapAST = (reactNode, astNode, rootReactNode) => {
|
||||
const reactNodes = getAsArray(reactNode);
|
||||
const astNodes = getAsArray(astNode);
|
||||
return astNodes.reduce((mem, node, i) => {
|
||||
const translationContent = node.children?.[0]?.content && i18n.services.interpolator.interpolate(node.children[0].content, opts, i18n.language);
|
||||
if (node.type === 'tag') {
|
||||
let tmp = reactNodes[parseInt(node.name, 10)];
|
||||
if (!tmp && knownComponentsMap) tmp = knownComponentsMap[node.name];
|
||||
if (rootReactNode.length === 1 && !tmp) tmp = rootReactNode[0][node.name];
|
||||
if (!tmp) tmp = {};
|
||||
const child = Object.keys(node.attrs).length !== 0 ? mergeProps({
|
||||
props: node.attrs
|
||||
}, tmp) : tmp;
|
||||
const isElement = react.isValidElement(child);
|
||||
const isValidTranslationWithChildren = isElement && hasChildren(node, true) && !node.voidElement;
|
||||
const isEmptyTransWithHTML = emptyChildrenButNeedsHandling && isObject(child) && child.dummy && !isElement;
|
||||
const isKnownComponent = isObject(knownComponentsMap) && Object.hasOwnProperty.call(knownComponentsMap, node.name);
|
||||
if (isString(child)) {
|
||||
const value = i18n.services.interpolator.interpolate(child, opts, i18n.language);
|
||||
mem.push(value);
|
||||
} else if (hasChildren(child) || isValidTranslationWithChildren) {
|
||||
const inner = renderInner(child, node, rootReactNode);
|
||||
pushTranslatedJSX(child, inner, mem, i);
|
||||
} else if (isEmptyTransWithHTML) {
|
||||
const inner = mapAST(reactNodes, 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(react.createElement(node.name, {
|
||||
key: `${node.name}-${i}`
|
||||
}));
|
||||
} else {
|
||||
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
||||
mem.push(react.createElement(node.name, {
|
||||
key: `${node.name}-${i}`
|
||||
}, inner));
|
||||
}
|
||||
} else if (node.voidElement) {
|
||||
mem.push(`<${node.name} />`);
|
||||
} else {
|
||||
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
||||
mem.push(`<${node.name}>${inner}</${node.name}>`);
|
||||
}
|
||||
} else if (isObject(child) && !isElement) {
|
||||
const content = node.children[0] ? translationContent : null;
|
||||
if (content) mem.push(content);
|
||||
} else {
|
||||
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(react.createElement(wrapTextNodes, {
|
||||
key: `${node.name}-${i}`
|
||||
}, content));
|
||||
} else {
|
||||
mem.push(content);
|
||||
}
|
||||
}
|
||||
return mem;
|
||||
}, []);
|
||||
};
|
||||
const result = mapAST([{
|
||||
dummy: true,
|
||||
children: children || []
|
||||
}], ast, getAsArray(children || []));
|
||||
return getChildren(result[0]);
|
||||
};
|
||||
const fixComponentProps = (component, index, translation) => {
|
||||
const componentKey = component.key || index;
|
||||
const comp = react.cloneElement(component, {
|
||||
key: componentKey
|
||||
});
|
||||
if (!comp.props || !comp.props.children || translation.indexOf(`${index}/>`) < 0 && translation.indexOf(`${index} />`) < 0) {
|
||||
return comp;
|
||||
}
|
||||
function Componentized() {
|
||||
return react.createElement(react.Fragment, null, comp);
|
||||
}
|
||||
return react.createElement(Componentized, {
|
||||
key: componentKey
|
||||
});
|
||||
};
|
||||
const generateArrayComponents = (components, translation) => components.map((c, index) => fixComponentProps(c, index, translation));
|
||||
const generateObjectComponents = (components, translation) => {
|
||||
const componentMap = {};
|
||||
Object.keys(components).forEach(c => {
|
||||
Object.assign(componentMap, {
|
||||
[c]: fixComponentProps(components[c], c, translation)
|
||||
});
|
||||
});
|
||||
return componentMap;
|
||||
};
|
||||
const generateComponents = (components, translation, i18n, i18nKey) => {
|
||||
if (!components) return null;
|
||||
if (Array.isArray(components)) {
|
||||
return generateArrayComponents(components, translation);
|
||||
}
|
||||
if (isObject(components)) {
|
||||
return generateObjectComponents(components, translation);
|
||||
}
|
||||
warnOnce(i18n, 'TRANS_INVALID_COMPONENTS', `<Trans /> "components" prop expects an object or array`, {
|
||||
i18nKey
|
||||
});
|
||||
return null;
|
||||
};
|
||||
const isComponentsMap = object => {
|
||||
if (!isObject(object)) return false;
|
||||
if (Array.isArray(object)) return false;
|
||||
return Object.keys(object).reduce((acc, key) => acc && Number.isNaN(Number.parseFloat(key)), true);
|
||||
};
|
||||
function Trans$1({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions = {},
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns,
|
||||
i18n: i18nFromProps,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
}) {
|
||||
const i18n = i18nFromProps || getI18n();
|
||||
if (!i18n) {
|
||||
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', `Trans: You need to pass in an i18next instance using i18nextReactModule`, {
|
||||
i18nKey
|
||||
});
|
||||
return children;
|
||||
}
|
||||
const t = tFromProps || i18n.t.bind(i18n) || (k => k);
|
||||
const reactI18nextOptions = {
|
||||
...getDefaults(),
|
||||
...i18n.options?.react
|
||||
};
|
||||
let namespaces = ns || t.ns || i18n.options?.defaultNS;
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
const nodeAsString = nodesToString(children, reactI18nextOptions, i18n, i18nKey);
|
||||
const defaultValue = defaults || nodeAsString || reactI18nextOptions.transEmptyNodeValue || i18nKey;
|
||||
const {
|
||||
hashTransKey
|
||||
} = reactI18nextOptions;
|
||||
const key = i18nKey || (hashTransKey ? hashTransKey(nodeAsString || defaultValue) : nodeAsString || defaultValue);
|
||||
if (i18n.options?.interpolation?.defaultVariables) {
|
||||
values = values && Object.keys(values).length > 0 ? {
|
||||
...values,
|
||||
...i18n.options.interpolation.defaultVariables
|
||||
} : {
|
||||
...i18n.options.interpolation.defaultVariables
|
||||
};
|
||||
}
|
||||
const interpolationOverride = values || count !== undefined && !i18n.options?.interpolation?.alwaysFormat || !children ? tOptions.interpolation : {
|
||||
interpolation: {
|
||||
...tOptions.interpolation,
|
||||
prefix: '#$?',
|
||||
suffix: '?$#'
|
||||
}
|
||||
};
|
||||
const combinedTOpts = {
|
||||
...tOptions,
|
||||
context: context || tOptions.context,
|
||||
count,
|
||||
...values,
|
||||
...interpolationOverride,
|
||||
defaultValue,
|
||||
ns: namespaces
|
||||
};
|
||||
const translation = key ? t(key, combinedTOpts) : defaultValue;
|
||||
const generatedComponents = generateComponents(components, translation, i18n, i18nKey);
|
||||
let indexedChildren = generatedComponents || children;
|
||||
let componentsMap = null;
|
||||
if (isComponentsMap(generatedComponents)) {
|
||||
componentsMap = generatedComponents;
|
||||
indexedChildren = children;
|
||||
}
|
||||
const content = renderNodes(indexedChildren, componentsMap, translation, i18n, reactI18nextOptions, combinedTOpts, shouldUnescape);
|
||||
const useAsParent = parent ?? reactI18nextOptions.defaultTransParent;
|
||||
return useAsParent ? react.createElement(useAsParent, additionalProps, content) : content;
|
||||
}
|
||||
|
||||
const initReactI18next = {
|
||||
type: '3rdParty',
|
||||
init(instance) {
|
||||
setDefaults(instance.options.react);
|
||||
setI18n(instance);
|
||||
}
|
||||
};
|
||||
|
||||
const I18nContext = react.createContext();
|
||||
class ReportNamespaces {
|
||||
constructor() {
|
||||
this.usedNamespaces = {};
|
||||
}
|
||||
addUsedNamespaces(namespaces) {
|
||||
namespaces.forEach(ns => {
|
||||
if (!this.usedNamespaces[ns]) this.usedNamespaces[ns] = true;
|
||||
});
|
||||
}
|
||||
getUsedNamespaces() {
|
||||
return Object.keys(this.usedNamespaces);
|
||||
}
|
||||
}
|
||||
const composeInitialProps = ForComponent => async ctx => {
|
||||
const componentsInitialProps = (await ForComponent.getInitialProps?.(ctx)) ?? {};
|
||||
const i18nInitialProps = getInitialProps();
|
||||
return {
|
||||
...componentsInitialProps,
|
||||
...i18nInitialProps
|
||||
};
|
||||
};
|
||||
const getInitialProps = () => {
|
||||
const i18n = getI18n();
|
||||
const namespaces = 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;
|
||||
};
|
||||
|
||||
function Trans({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions = {},
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns,
|
||||
i18n: i18nFromProps,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
}) {
|
||||
const {
|
||||
i18n: i18nFromContext,
|
||||
defaultNS: defaultNSFromContext
|
||||
} = react.useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
const t = tFromProps || i18n?.t.bind(i18n);
|
||||
return Trans$1({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions,
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns: ns || t?.ns || defaultNSFromContext || i18n?.options?.defaultNS,
|
||||
i18n,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
});
|
||||
}
|
||||
|
||||
const usePrevious = (value, ignore) => {
|
||||
const ref = react.useRef();
|
||||
react.useEffect(() => {
|
||||
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) => react.useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [i18n, language, namespace, keyPrefix]);
|
||||
const useTranslation = (ns, props = {}) => {
|
||||
const {
|
||||
i18n: i18nFromProps
|
||||
} = props;
|
||||
const {
|
||||
i18n: i18nFromContext,
|
||||
defaultNS: defaultNSFromContext
|
||||
} = react.useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
|
||||
if (!i18n) {
|
||||
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', 'useTranslation: 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?.wait) warnOnce(i18n, 'DEPRECATED_OPTION', 'useTranslation: 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;
|
||||
let namespaces = ns || defaultNSFromContext || i18n.options?.defaultNS;
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
i18n.reportNamespaces.addUsedNamespaces?.(namespaces);
|
||||
const ready = (i18n.isInitialized || i18n.initializedStoreOnce) && namespaces.every(n => hasLoadedNamespace(n, i18n, i18nOptions));
|
||||
const memoGetT = useMemoizedT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
||||
const getT = () => memoGetT;
|
||||
const getNewT = () => alwaysNewT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
||||
const [t, setT] = react.useState(getT);
|
||||
let joinedNS = namespaces.join();
|
||||
if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
|
||||
const previousJoinedNS = usePrevious(joinedNS);
|
||||
const isMounted = react.useRef(true);
|
||||
react.useEffect(() => {
|
||||
const {
|
||||
bindI18n,
|
||||
bindI18nStore
|
||||
} = i18nOptions;
|
||||
isMounted.current = true;
|
||||
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);
|
||||
};
|
||||
if (bindI18n) i18n?.on(bindI18n, boundReset);
|
||||
if (bindI18nStore) i18n?.store.on(bindI18nStore, boundReset);
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
if (i18n && bindI18n) bindI18n?.split(' ').forEach(e => i18n.off(e, boundReset));
|
||||
if (bindI18nStore && i18n) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, boundReset));
|
||||
};
|
||||
}, [i18n, joinedNS]);
|
||||
react.useEffect(() => {
|
||||
if (isMounted.current && ready) {
|
||||
setT(getT);
|
||||
}
|
||||
}, [i18n, keyPrefix, ready]);
|
||||
const ret = [t, i18n, ready];
|
||||
ret.t = t;
|
||||
ret.i18n = i18n;
|
||||
ret.ready = ready;
|
||||
if (ready) return ret;
|
||||
if (!ready && !useSuspense) return ret;
|
||||
throw new Promise(resolve => {
|
||||
if (props.lng) {
|
||||
loadLanguages(i18n, props.lng, namespaces, () => resolve());
|
||||
} else {
|
||||
loadNamespaces(i18n, namespaces, () => resolve());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
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 react.createElement(WrappedComponent, passDownProps);
|
||||
}
|
||||
I18nextWithTranslation.displayName = `withI18nextTranslation(${getDisplayName(WrappedComponent)})`;
|
||||
I18nextWithTranslation.WrappedComponent = WrappedComponent;
|
||||
const forwardRef = (props, ref) => react.createElement(I18nextWithTranslation, Object.assign({}, props, {
|
||||
forwardedRef: ref
|
||||
}));
|
||||
return options.withRef ? react.forwardRef(forwardRef) : I18nextWithTranslation;
|
||||
};
|
||||
|
||||
const Translation = ({
|
||||
ns,
|
||||
children,
|
||||
...options
|
||||
}) => {
|
||||
const [t, i18n, ready] = useTranslation(ns, options);
|
||||
return children(t, {
|
||||
i18n,
|
||||
lng: i18n.language
|
||||
}, ready);
|
||||
};
|
||||
|
||||
function I18nextProvider({
|
||||
i18n,
|
||||
defaultNS,
|
||||
children
|
||||
}) {
|
||||
const value = react.useMemo(() => ({
|
||||
i18n,
|
||||
defaultNS
|
||||
}), [i18n, defaultNS]);
|
||||
return react.createElement(I18nContext.Provider, {
|
||||
value
|
||||
}, children);
|
||||
}
|
||||
|
||||
const useSSR = (initialI18nStore, initialLanguage, props = {}) => {
|
||||
const {
|
||||
i18n: i18nFromProps
|
||||
} = props;
|
||||
const {
|
||||
i18n: i18nFromContext
|
||||
} = react.useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
if (i18n.options?.isClone) return;
|
||||
if (initialI18nStore && !i18n.initializedStoreOnce) {
|
||||
i18n.services.resourceStore.data = initialI18nStore;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
const withSSR = () => function Extend(WrappedComponent) {
|
||||
function I18nextWithSSR({
|
||||
initialI18nStore,
|
||||
initialLanguage,
|
||||
...rest
|
||||
}) {
|
||||
useSSR(initialI18nStore, initialLanguage);
|
||||
return react.createElement(WrappedComponent, {
|
||||
...rest
|
||||
});
|
||||
}
|
||||
I18nextWithSSR.getInitialProps = composeInitialProps(WrappedComponent);
|
||||
I18nextWithSSR.displayName = `withI18nextSSR(${getDisplayName(WrappedComponent)})`;
|
||||
I18nextWithSSR.WrappedComponent = WrappedComponent;
|
||||
return I18nextWithSSR;
|
||||
};
|
||||
|
||||
const date = () => '';
|
||||
const time = () => '';
|
||||
const number = () => '';
|
||||
const select = () => '';
|
||||
const plural = () => '';
|
||||
const selectOrdinal = () => '';
|
||||
|
||||
exports.I18nContext = I18nContext;
|
||||
exports.I18nextProvider = I18nextProvider;
|
||||
exports.Trans = Trans;
|
||||
exports.TransWithoutContext = Trans$1;
|
||||
exports.Translation = Translation;
|
||||
exports.composeInitialProps = composeInitialProps;
|
||||
exports.date = date;
|
||||
exports.getDefaults = getDefaults;
|
||||
exports.getI18n = getI18n;
|
||||
exports.getInitialProps = getInitialProps;
|
||||
exports.initReactI18next = initReactI18next;
|
||||
exports.number = number;
|
||||
exports.plural = plural;
|
||||
exports.select = select;
|
||||
exports.selectOrdinal = selectOrdinal;
|
||||
exports.setDefaults = setDefaults;
|
||||
exports.setI18n = setI18n;
|
||||
exports.time = time;
|
||||
exports.useSSR = useSSR;
|
||||
exports.useTranslation = useTranslation;
|
||||
exports.withSSR = withSSR;
|
||||
exports.withTranslation = withTranslation;
|
||||
|
||||
}));
|
||||
1
node_modules/react-i18next/dist/amd/react-i18next.min.js
generated
vendored
Normal file
1
node_modules/react-i18next/dist/amd/react-i18next.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
21
node_modules/react-i18next/dist/commonjs/I18nextProvider.js
generated
vendored
Normal file
21
node_modules/react-i18next/dist/commonjs/I18nextProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.I18nextProvider = I18nextProvider;
|
||||
var _react = require("react");
|
||||
var _context = require("./context.js");
|
||||
function I18nextProvider({
|
||||
i18n,
|
||||
defaultNS,
|
||||
children
|
||||
}) {
|
||||
const value = (0, _react.useMemo)(() => ({
|
||||
i18n,
|
||||
defaultNS
|
||||
}), [i18n, defaultNS]);
|
||||
return (0, _react.createElement)(_context.I18nContext.Provider, {
|
||||
value
|
||||
}, children);
|
||||
}
|
||||
54
node_modules/react-i18next/dist/commonjs/Trans.js
generated
vendored
Normal file
54
node_modules/react-i18next/dist/commonjs/Trans.js
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Trans = Trans;
|
||||
Object.defineProperty(exports, "nodesToString", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _TransWithoutContext.nodesToString;
|
||||
}
|
||||
});
|
||||
var _react = require("react");
|
||||
var _TransWithoutContext = require("./TransWithoutContext.js");
|
||||
var _context = require("./context.js");
|
||||
function Trans({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions = {},
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns,
|
||||
i18n: i18nFromProps,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
}) {
|
||||
const {
|
||||
i18n: i18nFromContext,
|
||||
defaultNS: defaultNSFromContext
|
||||
} = (0, _react.useContext)(_context.I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || (0, _context.getI18n)();
|
||||
const t = tFromProps || i18n?.t.bind(i18n);
|
||||
return (0, _TransWithoutContext.Trans)({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions,
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns: ns || t?.ns || defaultNSFromContext || i18n?.options?.defaultNS,
|
||||
i18n,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
});
|
||||
}
|
||||
330
node_modules/react-i18next/dist/commonjs/TransWithoutContext.js
generated
vendored
Normal file
330
node_modules/react-i18next/dist/commonjs/TransWithoutContext.js
generated
vendored
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Trans = Trans;
|
||||
exports.nodesToString = void 0;
|
||||
var _react = require("react");
|
||||
var _htmlParseStringify = _interopRequireDefault(require("html-parse-stringify"));
|
||||
var _utils = require("./utils.js");
|
||||
var _defaults = require("./defaults.js");
|
||||
var _i18nInstance = require("./i18nInstance.js");
|
||||
const hasChildren = (node, checkLength) => {
|
||||
if (!node) return false;
|
||||
const base = node.props?.children ?? node.children;
|
||||
if (checkLength) return base.length > 0;
|
||||
return !!base;
|
||||
};
|
||||
const getChildren = node => {
|
||||
if (!node) return [];
|
||||
const children = node.props?.children ?? node.children;
|
||||
return node.props?.i18nIsDynamicList ? getAsArray(children) : children;
|
||||
};
|
||||
const hasValidReactChildren = children => Array.isArray(children) && children.every(_react.isValidElement);
|
||||
const getAsArray = data => Array.isArray(data) ? data : [data];
|
||||
const mergeProps = (source, target) => {
|
||||
const newTarget = {
|
||||
...target
|
||||
};
|
||||
newTarget.props = Object.assign(source.props, target.props);
|
||||
return newTarget;
|
||||
};
|
||||
const nodesToString = (children, i18nOptions, i18n, i18nKey) => {
|
||||
if (!children) return '';
|
||||
let stringNode = '';
|
||||
const childrenArray = getAsArray(children);
|
||||
const keepArray = i18nOptions?.transSupportBasicHtmlNodes ? i18nOptions.transKeepBasicHtmlNodesFor ?? [] : [];
|
||||
childrenArray.forEach((child, childIndex) => {
|
||||
if ((0, _utils.isString)(child)) {
|
||||
stringNode += `${child}`;
|
||||
return;
|
||||
}
|
||||
if ((0, _react.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) {
|
||||
stringNode += `<${type}/>`;
|
||||
return;
|
||||
}
|
||||
if (!childChildren && (!shouldKeepChild || childPropsCount) || props.i18nIsDynamicList) {
|
||||
stringNode += `<${childIndex}></${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (shouldKeepChild && childPropsCount === 1 && (0, _utils.isString)(childChildren)) {
|
||||
stringNode += `<${type}>${childChildren}</${type}>`;
|
||||
return;
|
||||
}
|
||||
const content = nodesToString(childChildren, i18nOptions, i18n, i18nKey);
|
||||
stringNode += `<${childIndex}>${content}</${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (child === null) {
|
||||
(0, _utils.warn)(i18n, 'TRANS_NULL_VALUE', `Passed in a null value as child`, {
|
||||
i18nKey
|
||||
});
|
||||
return;
|
||||
}
|
||||
if ((0, _utils.isObject)(child)) {
|
||||
const {
|
||||
format,
|
||||
...clone
|
||||
} = child;
|
||||
const keys = Object.keys(clone);
|
||||
if (keys.length === 1) {
|
||||
const value = format ? `${keys[0]}, ${format}` : keys[0];
|
||||
stringNode += `{{${value}}}`;
|
||||
return;
|
||||
}
|
||||
(0, _utils.warn)(i18n, 'TRANS_INVALID_OBJ', `Invalid child - Object should only have keys {{ value, format }} (format is optional).`, {
|
||||
i18nKey,
|
||||
child
|
||||
});
|
||||
return;
|
||||
}
|
||||
(0, _utils.warn)(i18n, 'TRANS_INVALID_VAR', `Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.`, {
|
||||
i18nKey,
|
||||
child
|
||||
});
|
||||
});
|
||||
return stringNode;
|
||||
};
|
||||
exports.nodesToString = nodesToString;
|
||||
const renderNodes = (children, knownComponentsMap, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
|
||||
if (targetString === '') return [];
|
||||
const keepArray = i18nOptions.transKeepBasicHtmlNodesFor || [];
|
||||
const emptyChildrenButNeedsHandling = targetString && new RegExp(keepArray.map(keep => `<${keep}`).join('|')).test(targetString);
|
||||
if (!children && !knownComponentsMap && !emptyChildrenButNeedsHandling && !shouldUnescape) return [targetString];
|
||||
const data = knownComponentsMap ?? {};
|
||||
const getData = childs => {
|
||||
const childrenArray = getAsArray(childs);
|
||||
childrenArray.forEach(child => {
|
||||
if ((0, _utils.isString)(child)) return;
|
||||
if (hasChildren(child)) getData(getChildren(child));else if ((0, _utils.isObject)(child) && !(0, _react.isValidElement)(child)) Object.assign(data, child);
|
||||
});
|
||||
};
|
||||
getData(children);
|
||||
const ast = _htmlParseStringify.default.parse(`<0>${targetString}</0>`);
|
||||
const opts = {
|
||||
...data,
|
||||
...combinedTOpts
|
||||
};
|
||||
const renderInner = (child, node, rootReactNode) => {
|
||||
const childs = getChildren(child);
|
||||
const mappedChildren = mapAST(childs, node.children, rootReactNode);
|
||||
return hasValidReactChildren(childs) && mappedChildren.length === 0 || child.props?.i18nIsDynamicList ? childs : mappedChildren;
|
||||
};
|
||||
const pushTranslatedJSX = (child, inner, mem, i, isVoid) => {
|
||||
if (child.dummy) {
|
||||
child.children = inner;
|
||||
mem.push((0, _react.cloneElement)(child, {
|
||||
key: i
|
||||
}, isVoid ? undefined : inner));
|
||||
} else {
|
||||
mem.push(..._react.Children.map([child], c => {
|
||||
const props = {
|
||||
...c.props
|
||||
};
|
||||
delete props.i18nIsDynamicList;
|
||||
return (0, _react.createElement)(c.type, {
|
||||
...props,
|
||||
key: i,
|
||||
ref: c.props.ref ?? c.ref
|
||||
}, isVoid ? null : inner);
|
||||
}));
|
||||
}
|
||||
};
|
||||
const mapAST = (reactNode, astNode, rootReactNode) => {
|
||||
const reactNodes = getAsArray(reactNode);
|
||||
const astNodes = getAsArray(astNode);
|
||||
return astNodes.reduce((mem, node, i) => {
|
||||
const translationContent = node.children?.[0]?.content && i18n.services.interpolator.interpolate(node.children[0].content, opts, i18n.language);
|
||||
if (node.type === 'tag') {
|
||||
let tmp = reactNodes[parseInt(node.name, 10)];
|
||||
if (!tmp && knownComponentsMap) tmp = knownComponentsMap[node.name];
|
||||
if (rootReactNode.length === 1 && !tmp) tmp = rootReactNode[0][node.name];
|
||||
if (!tmp) tmp = {};
|
||||
const child = Object.keys(node.attrs).length !== 0 ? mergeProps({
|
||||
props: node.attrs
|
||||
}, tmp) : tmp;
|
||||
const isElement = (0, _react.isValidElement)(child);
|
||||
const isValidTranslationWithChildren = isElement && hasChildren(node, true) && !node.voidElement;
|
||||
const isEmptyTransWithHTML = emptyChildrenButNeedsHandling && (0, _utils.isObject)(child) && child.dummy && !isElement;
|
||||
const isKnownComponent = (0, _utils.isObject)(knownComponentsMap) && Object.hasOwnProperty.call(knownComponentsMap, node.name);
|
||||
if ((0, _utils.isString)(child)) {
|
||||
const value = i18n.services.interpolator.interpolate(child, opts, i18n.language);
|
||||
mem.push(value);
|
||||
} else if (hasChildren(child) || isValidTranslationWithChildren) {
|
||||
const inner = renderInner(child, node, rootReactNode);
|
||||
pushTranslatedJSX(child, inner, mem, i);
|
||||
} else if (isEmptyTransWithHTML) {
|
||||
const inner = mapAST(reactNodes, 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((0, _react.createElement)(node.name, {
|
||||
key: `${node.name}-${i}`
|
||||
}));
|
||||
} else {
|
||||
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
||||
mem.push((0, _react.createElement)(node.name, {
|
||||
key: `${node.name}-${i}`
|
||||
}, inner));
|
||||
}
|
||||
} else if (node.voidElement) {
|
||||
mem.push(`<${node.name} />`);
|
||||
} else {
|
||||
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
||||
mem.push(`<${node.name}>${inner}</${node.name}>`);
|
||||
}
|
||||
} else if ((0, _utils.isObject)(child) && !isElement) {
|
||||
const content = node.children[0] ? translationContent : null;
|
||||
if (content) mem.push(content);
|
||||
} else {
|
||||
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((0, _react.createElement)(wrapTextNodes, {
|
||||
key: `${node.name}-${i}`
|
||||
}, content));
|
||||
} else {
|
||||
mem.push(content);
|
||||
}
|
||||
}
|
||||
return mem;
|
||||
}, []);
|
||||
};
|
||||
const result = mapAST([{
|
||||
dummy: true,
|
||||
children: children || []
|
||||
}], ast, getAsArray(children || []));
|
||||
return getChildren(result[0]);
|
||||
};
|
||||
const fixComponentProps = (component, index, translation) => {
|
||||
const componentKey = component.key || index;
|
||||
const comp = (0, _react.cloneElement)(component, {
|
||||
key: componentKey
|
||||
});
|
||||
if (!comp.props || !comp.props.children || translation.indexOf(`${index}/>`) < 0 && translation.indexOf(`${index} />`) < 0) {
|
||||
return comp;
|
||||
}
|
||||
function Componentized() {
|
||||
return (0, _react.createElement)(_react.Fragment, null, comp);
|
||||
}
|
||||
return (0, _react.createElement)(Componentized, {
|
||||
key: componentKey
|
||||
});
|
||||
};
|
||||
const generateArrayComponents = (components, translation) => components.map((c, index) => fixComponentProps(c, index, translation));
|
||||
const generateObjectComponents = (components, translation) => {
|
||||
const componentMap = {};
|
||||
Object.keys(components).forEach(c => {
|
||||
Object.assign(componentMap, {
|
||||
[c]: fixComponentProps(components[c], c, translation)
|
||||
});
|
||||
});
|
||||
return componentMap;
|
||||
};
|
||||
const generateComponents = (components, translation, i18n, i18nKey) => {
|
||||
if (!components) return null;
|
||||
if (Array.isArray(components)) {
|
||||
return generateArrayComponents(components, translation);
|
||||
}
|
||||
if ((0, _utils.isObject)(components)) {
|
||||
return generateObjectComponents(components, translation);
|
||||
}
|
||||
(0, _utils.warnOnce)(i18n, 'TRANS_INVALID_COMPONENTS', `<Trans /> "components" prop expects an object or array`, {
|
||||
i18nKey
|
||||
});
|
||||
return null;
|
||||
};
|
||||
const isComponentsMap = object => {
|
||||
if (!(0, _utils.isObject)(object)) return false;
|
||||
if (Array.isArray(object)) return false;
|
||||
return Object.keys(object).reduce((acc, key) => acc && Number.isNaN(Number.parseFloat(key)), true);
|
||||
};
|
||||
function Trans({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions = {},
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns,
|
||||
i18n: i18nFromProps,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
}) {
|
||||
const i18n = i18nFromProps || (0, _i18nInstance.getI18n)();
|
||||
if (!i18n) {
|
||||
(0, _utils.warnOnce)(i18n, 'NO_I18NEXT_INSTANCE', `Trans: You need to pass in an i18next instance using i18nextReactModule`, {
|
||||
i18nKey
|
||||
});
|
||||
return children;
|
||||
}
|
||||
const t = tFromProps || i18n.t.bind(i18n) || (k => k);
|
||||
const reactI18nextOptions = {
|
||||
...(0, _defaults.getDefaults)(),
|
||||
...i18n.options?.react
|
||||
};
|
||||
let namespaces = ns || t.ns || i18n.options?.defaultNS;
|
||||
namespaces = (0, _utils.isString)(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
const nodeAsString = nodesToString(children, reactI18nextOptions, i18n, i18nKey);
|
||||
const defaultValue = defaults || nodeAsString || reactI18nextOptions.transEmptyNodeValue || i18nKey;
|
||||
const {
|
||||
hashTransKey
|
||||
} = reactI18nextOptions;
|
||||
const key = i18nKey || (hashTransKey ? hashTransKey(nodeAsString || defaultValue) : nodeAsString || defaultValue);
|
||||
if (i18n.options?.interpolation?.defaultVariables) {
|
||||
values = values && Object.keys(values).length > 0 ? {
|
||||
...values,
|
||||
...i18n.options.interpolation.defaultVariables
|
||||
} : {
|
||||
...i18n.options.interpolation.defaultVariables
|
||||
};
|
||||
}
|
||||
const interpolationOverride = values || count !== undefined && !i18n.options?.interpolation?.alwaysFormat || !children ? tOptions.interpolation : {
|
||||
interpolation: {
|
||||
...tOptions.interpolation,
|
||||
prefix: '#$?',
|
||||
suffix: '?$#'
|
||||
}
|
||||
};
|
||||
const combinedTOpts = {
|
||||
...tOptions,
|
||||
context: context || tOptions.context,
|
||||
count,
|
||||
...values,
|
||||
...interpolationOverride,
|
||||
defaultValue,
|
||||
ns: namespaces
|
||||
};
|
||||
const translation = key ? t(key, combinedTOpts) : defaultValue;
|
||||
const generatedComponents = generateComponents(components, translation, i18n, i18nKey);
|
||||
let indexedChildren = generatedComponents || children;
|
||||
let componentsMap = null;
|
||||
if (isComponentsMap(generatedComponents)) {
|
||||
componentsMap = generatedComponents;
|
||||
indexedChildren = children;
|
||||
}
|
||||
const content = renderNodes(indexedChildren, componentsMap, translation, i18n, reactI18nextOptions, combinedTOpts, shouldUnescape);
|
||||
const useAsParent = parent ?? reactI18nextOptions.defaultTransParent;
|
||||
return useAsParent ? (0, _react.createElement)(useAsParent, additionalProps, content) : content;
|
||||
}
|
||||
19
node_modules/react-i18next/dist/commonjs/Translation.js
generated
vendored
Normal file
19
node_modules/react-i18next/dist/commonjs/Translation.js
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Translation = void 0;
|
||||
var _useTranslation = require("./useTranslation.js");
|
||||
const Translation = ({
|
||||
ns,
|
||||
children,
|
||||
...options
|
||||
}) => {
|
||||
const [t, i18n, ready] = (0, _useTranslation.useTranslation)(ns, options);
|
||||
return children(t, {
|
||||
i18n,
|
||||
lng: i18n.language
|
||||
}, ready);
|
||||
};
|
||||
exports.Translation = Translation;
|
||||
81
node_modules/react-i18next/dist/commonjs/context.js
generated
vendored
Normal file
81
node_modules/react-i18next/dist/commonjs/context.js
generated
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.composeInitialProps = exports.ReportNamespaces = exports.I18nContext = void 0;
|
||||
Object.defineProperty(exports, "getDefaults", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _defaults.getDefaults;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "getI18n", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _i18nInstance.getI18n;
|
||||
}
|
||||
});
|
||||
exports.getInitialProps = void 0;
|
||||
Object.defineProperty(exports, "initReactI18next", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _initReactI18next.initReactI18next;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "setDefaults", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _defaults.setDefaults;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "setI18n", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _i18nInstance.setI18n;
|
||||
}
|
||||
});
|
||||
var _react = require("react");
|
||||
var _defaults = require("./defaults.js");
|
||||
var _i18nInstance = require("./i18nInstance.js");
|
||||
var _initReactI18next = require("./initReactI18next.js");
|
||||
const I18nContext = exports.I18nContext = (0, _react.createContext)();
|
||||
class ReportNamespaces {
|
||||
constructor() {
|
||||
this.usedNamespaces = {};
|
||||
}
|
||||
addUsedNamespaces(namespaces) {
|
||||
namespaces.forEach(ns => {
|
||||
if (!this.usedNamespaces[ns]) this.usedNamespaces[ns] = true;
|
||||
});
|
||||
}
|
||||
getUsedNamespaces() {
|
||||
return Object.keys(this.usedNamespaces);
|
||||
}
|
||||
}
|
||||
exports.ReportNamespaces = ReportNamespaces;
|
||||
const composeInitialProps = ForComponent => async ctx => {
|
||||
const componentsInitialProps = (await ForComponent.getInitialProps?.(ctx)) ?? {};
|
||||
const i18nInitialProps = getInitialProps();
|
||||
return {
|
||||
...componentsInitialProps,
|
||||
...i18nInitialProps
|
||||
};
|
||||
};
|
||||
exports.composeInitialProps = composeInitialProps;
|
||||
const getInitialProps = () => {
|
||||
const i18n = (0, _i18nInstance.getI18n)();
|
||||
const namespaces = 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;
|
||||
};
|
||||
exports.getInitialProps = getInitialProps;
|
||||
26
node_modules/react-i18next/dist/commonjs/defaults.js
generated
vendored
Normal file
26
node_modules/react-i18next/dist/commonjs/defaults.js
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.setDefaults = exports.getDefaults = void 0;
|
||||
var _unescape = require("./unescape.js");
|
||||
let defaultOptions = {
|
||||
bindI18n: 'languageChanged',
|
||||
bindI18nStore: '',
|
||||
transEmptyNodeValue: '',
|
||||
transSupportBasicHtmlNodes: true,
|
||||
transWrapTextNodes: '',
|
||||
transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p'],
|
||||
useSuspense: true,
|
||||
unescape: _unescape.unescape
|
||||
};
|
||||
const setDefaults = (options = {}) => {
|
||||
defaultOptions = {
|
||||
...defaultOptions,
|
||||
...options
|
||||
};
|
||||
};
|
||||
exports.setDefaults = setDefaults;
|
||||
const getDefaults = () => defaultOptions;
|
||||
exports.getDefaults = getDefaults;
|
||||
13
node_modules/react-i18next/dist/commonjs/i18nInstance.js
generated
vendored
Normal file
13
node_modules/react-i18next/dist/commonjs/i18nInstance.js
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.setI18n = exports.getI18n = void 0;
|
||||
let i18nInstance;
|
||||
const setI18n = instance => {
|
||||
i18nInstance = instance;
|
||||
};
|
||||
exports.setI18n = setI18n;
|
||||
const getI18n = () => i18nInstance;
|
||||
exports.getI18n = getI18n;
|
||||
128
node_modules/react-i18next/dist/commonjs/index.js
generated
vendored
Normal file
128
node_modules/react-i18next/dist/commonjs/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "I18nContext", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _context.I18nContext;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "I18nextProvider", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _I18nextProvider.I18nextProvider;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Trans", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _Trans.Trans;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "TransWithoutContext", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _TransWithoutContext.Trans;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Translation", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _Translation.Translation;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "composeInitialProps", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _context.composeInitialProps;
|
||||
}
|
||||
});
|
||||
exports.date = void 0;
|
||||
Object.defineProperty(exports, "getDefaults", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _defaults.getDefaults;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "getI18n", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _i18nInstance.getI18n;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "getInitialProps", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _context.getInitialProps;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "initReactI18next", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _initReactI18next.initReactI18next;
|
||||
}
|
||||
});
|
||||
exports.selectOrdinal = exports.select = exports.plural = exports.number = void 0;
|
||||
Object.defineProperty(exports, "setDefaults", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _defaults.setDefaults;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "setI18n", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _i18nInstance.setI18n;
|
||||
}
|
||||
});
|
||||
exports.time = void 0;
|
||||
Object.defineProperty(exports, "useSSR", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _useSSR.useSSR;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "useTranslation", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _useTranslation.useTranslation;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "withSSR", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _withSSR.withSSR;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "withTranslation", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _withTranslation.withTranslation;
|
||||
}
|
||||
});
|
||||
var _Trans = require("./Trans.js");
|
||||
var _TransWithoutContext = require("./TransWithoutContext.js");
|
||||
var _useTranslation = require("./useTranslation.js");
|
||||
var _withTranslation = require("./withTranslation.js");
|
||||
var _Translation = require("./Translation.js");
|
||||
var _I18nextProvider = require("./I18nextProvider.js");
|
||||
var _withSSR = require("./withSSR.js");
|
||||
var _useSSR = require("./useSSR.js");
|
||||
var _initReactI18next = require("./initReactI18next.js");
|
||||
var _defaults = require("./defaults.js");
|
||||
var _i18nInstance = require("./i18nInstance.js");
|
||||
var _context = require("./context.js");
|
||||
const date = () => '';
|
||||
exports.date = date;
|
||||
const time = () => '';
|
||||
exports.time = time;
|
||||
const number = () => '';
|
||||
exports.number = number;
|
||||
const select = () => '';
|
||||
exports.select = select;
|
||||
const plural = () => '';
|
||||
exports.plural = plural;
|
||||
const selectOrdinal = () => '';
|
||||
exports.selectOrdinal = selectOrdinal;
|
||||
15
node_modules/react-i18next/dist/commonjs/initReactI18next.js
generated
vendored
Normal file
15
node_modules/react-i18next/dist/commonjs/initReactI18next.js
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.initReactI18next = void 0;
|
||||
var _defaults = require("./defaults.js");
|
||||
var _i18nInstance = require("./i18nInstance.js");
|
||||
const initReactI18next = exports.initReactI18next = {
|
||||
type: '3rdParty',
|
||||
init(instance) {
|
||||
(0, _defaults.setDefaults)(instance.options.react);
|
||||
(0, _i18nInstance.setI18n)(instance);
|
||||
}
|
||||
};
|
||||
32
node_modules/react-i18next/dist/commonjs/unescape.js
generated
vendored
Normal file
32
node_modules/react-i18next/dist/commonjs/unescape.js
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.unescape = void 0;
|
||||
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];
|
||||
const unescape = text => text.replace(matchHtmlEntity, unescapeHtmlEntity);
|
||||
exports.unescape = unescape;
|
||||
34
node_modules/react-i18next/dist/commonjs/useSSR.js
generated
vendored
Normal file
34
node_modules/react-i18next/dist/commonjs/useSSR.js
generated
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.useSSR = void 0;
|
||||
var _react = require("react");
|
||||
var _context = require("./context.js");
|
||||
const useSSR = (initialI18nStore, initialLanguage, props = {}) => {
|
||||
const {
|
||||
i18n: i18nFromProps
|
||||
} = props;
|
||||
const {
|
||||
i18n: i18nFromContext
|
||||
} = (0, _react.useContext)(_context.I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || (0, _context.getI18n)();
|
||||
if (i18n.options?.isClone) return;
|
||||
if (initialI18nStore && !i18n.initializedStoreOnce) {
|
||||
i18n.services.resourceStore.data = initialI18nStore;
|
||||
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;
|
||||
}
|
||||
};
|
||||
exports.useSSR = useSSR;
|
||||
114
node_modules/react-i18next/dist/commonjs/useTranslation.js
generated
vendored
Normal file
114
node_modules/react-i18next/dist/commonjs/useTranslation.js
generated
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.useTranslation = void 0;
|
||||
var _react = require("react");
|
||||
var _context = require("./context.js");
|
||||
var _utils = require("./utils.js");
|
||||
const usePrevious = (value, ignore) => {
|
||||
const ref = (0, _react.useRef)();
|
||||
(0, _react.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) => (0, _react.useCallback)(alwaysNewT(i18n, language, namespace, keyPrefix), [i18n, language, namespace, keyPrefix]);
|
||||
const useTranslation = (ns, props = {}) => {
|
||||
const {
|
||||
i18n: i18nFromProps
|
||||
} = props;
|
||||
const {
|
||||
i18n: i18nFromContext,
|
||||
defaultNS: defaultNSFromContext
|
||||
} = (0, _react.useContext)(_context.I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || (0, _context.getI18n)();
|
||||
if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new _context.ReportNamespaces();
|
||||
if (!i18n) {
|
||||
(0, _utils.warnOnce)(i18n, 'NO_I18NEXT_INSTANCE', 'useTranslation: You will need to pass in an i18next instance by using initReactI18next');
|
||||
const notReadyT = (k, optsOrDefaultValue) => {
|
||||
if ((0, _utils.isString)(optsOrDefaultValue)) return optsOrDefaultValue;
|
||||
if ((0, _utils.isObject)(optsOrDefaultValue) && (0, _utils.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?.wait) (0, _utils.warnOnce)(i18n, 'DEPRECATED_OPTION', 'useTranslation: It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.');
|
||||
const i18nOptions = {
|
||||
...(0, _context.getDefaults)(),
|
||||
...i18n.options.react,
|
||||
...props
|
||||
};
|
||||
const {
|
||||
useSuspense,
|
||||
keyPrefix
|
||||
} = i18nOptions;
|
||||
let namespaces = ns || defaultNSFromContext || i18n.options?.defaultNS;
|
||||
namespaces = (0, _utils.isString)(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
i18n.reportNamespaces.addUsedNamespaces?.(namespaces);
|
||||
const ready = (i18n.isInitialized || i18n.initializedStoreOnce) && namespaces.every(n => (0, _utils.hasLoadedNamespace)(n, i18n, i18nOptions));
|
||||
const memoGetT = useMemoizedT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
||||
const getT = () => memoGetT;
|
||||
const getNewT = () => alwaysNewT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
||||
const [t, setT] = (0, _react.useState)(getT);
|
||||
let joinedNS = namespaces.join();
|
||||
if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
|
||||
const previousJoinedNS = usePrevious(joinedNS);
|
||||
const isMounted = (0, _react.useRef)(true);
|
||||
(0, _react.useEffect)(() => {
|
||||
const {
|
||||
bindI18n,
|
||||
bindI18nStore
|
||||
} = i18nOptions;
|
||||
isMounted.current = true;
|
||||
if (!ready && !useSuspense) {
|
||||
if (props.lng) {
|
||||
(0, _utils.loadLanguages)(i18n, props.lng, namespaces, () => {
|
||||
if (isMounted.current) setT(getNewT);
|
||||
});
|
||||
} else {
|
||||
(0, _utils.loadNamespaces)(i18n, namespaces, () => {
|
||||
if (isMounted.current) setT(getNewT);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (ready && previousJoinedNS && previousJoinedNS !== joinedNS && isMounted.current) {
|
||||
setT(getNewT);
|
||||
}
|
||||
const boundReset = () => {
|
||||
if (isMounted.current) setT(getNewT);
|
||||
};
|
||||
if (bindI18n) i18n?.on(bindI18n, boundReset);
|
||||
if (bindI18nStore) i18n?.store.on(bindI18nStore, boundReset);
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
if (i18n && bindI18n) bindI18n?.split(' ').forEach(e => i18n.off(e, boundReset));
|
||||
if (bindI18nStore && i18n) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, boundReset));
|
||||
};
|
||||
}, [i18n, joinedNS]);
|
||||
(0, _react.useEffect)(() => {
|
||||
if (isMounted.current && ready) {
|
||||
setT(getT);
|
||||
}
|
||||
}, [i18n, keyPrefix, ready]);
|
||||
const ret = [t, i18n, ready];
|
||||
ret.t = t;
|
||||
ret.i18n = i18n;
|
||||
ret.ready = ready;
|
||||
if (ready) return ret;
|
||||
if (!ready && !useSuspense) return ret;
|
||||
throw new Promise(resolve => {
|
||||
if (props.lng) {
|
||||
(0, _utils.loadLanguages)(i18n, props.lng, namespaces, () => resolve());
|
||||
} else {
|
||||
(0, _utils.loadNamespaces)(i18n, namespaces, () => resolve());
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.useTranslation = useTranslation;
|
||||
76
node_modules/react-i18next/dist/commonjs/utils.js
generated
vendored
Normal file
76
node_modules/react-i18next/dist/commonjs/utils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.warnOnce = exports.warn = exports.loadNamespaces = exports.loadLanguages = exports.isString = exports.isObject = exports.hasLoadedNamespace = exports.getDisplayName = void 0;
|
||||
const warn = (i18n, code, msg, rest) => {
|
||||
const args = [msg, {
|
||||
code,
|
||||
...(rest || {})
|
||||
}];
|
||||
if (i18n?.services?.logger?.forward) {
|
||||
return i18n.services.logger.forward(args, 'warn', 'react-i18next::', true);
|
||||
}
|
||||
if (isString(args[0])) args[0] = `react-i18next:: ${args[0]}`;
|
||||
if (i18n?.services?.logger?.warn) {
|
||||
i18n.services.logger.warn(...args);
|
||||
} else if (console?.warn) {
|
||||
console.warn(...args);
|
||||
}
|
||||
};
|
||||
exports.warn = warn;
|
||||
const alreadyWarned = {};
|
||||
const warnOnce = (i18n, code, msg, rest) => {
|
||||
if (isString(msg) && alreadyWarned[msg]) return;
|
||||
if (isString(msg)) alreadyWarned[msg] = new Date();
|
||||
warn(i18n, code, msg, rest);
|
||||
};
|
||||
exports.warnOnce = warnOnce;
|
||||
const loadedClb = (i18n, cb) => () => {
|
||||
if (i18n.isInitialized) {
|
||||
cb();
|
||||
} else {
|
||||
const initialized = () => {
|
||||
setTimeout(() => {
|
||||
i18n.off('initialized', initialized);
|
||||
}, 0);
|
||||
cb();
|
||||
};
|
||||
i18n.on('initialized', initialized);
|
||||
}
|
||||
};
|
||||
const loadNamespaces = (i18n, ns, cb) => {
|
||||
i18n.loadNamespaces(ns, loadedClb(i18n, cb));
|
||||
};
|
||||
exports.loadNamespaces = loadNamespaces;
|
||||
const loadLanguages = (i18n, lng, ns, cb) => {
|
||||
if (isString(ns)) ns = [ns];
|
||||
if (i18n.options.preload && i18n.options.preload.indexOf(lng) > -1) return loadNamespaces(i18n, ns, cb);
|
||||
ns.forEach(n => {
|
||||
if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
|
||||
});
|
||||
i18n.loadLanguages(lng, loadedClb(i18n, cb));
|
||||
};
|
||||
exports.loadLanguages = loadLanguages;
|
||||
const hasLoadedNamespace = (ns, i18n, options = {}) => {
|
||||
if (!i18n.languages || !i18n.languages.length) {
|
||||
warnOnce(i18n, 'NO_LANGUAGES', 'i18n.languages were undefined or empty', {
|
||||
languages: i18n.languages
|
||||
});
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.hasLoadedNamespace = hasLoadedNamespace;
|
||||
const getDisplayName = Component => Component.displayName || Component.name || (isString(Component) && Component.length > 0 ? Component : 'Unknown');
|
||||
exports.getDisplayName = getDisplayName;
|
||||
const isString = obj => typeof obj === 'string';
|
||||
exports.isString = isString;
|
||||
const isObject = obj => typeof obj === 'object' && obj !== null;
|
||||
exports.isObject = isObject;
|
||||
27
node_modules/react-i18next/dist/commonjs/withSSR.js
generated
vendored
Normal file
27
node_modules/react-i18next/dist/commonjs/withSSR.js
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.withSSR = void 0;
|
||||
var _react = require("react");
|
||||
var _useSSR = require("./useSSR.js");
|
||||
var _context = require("./context.js");
|
||||
var _utils = require("./utils.js");
|
||||
const withSSR = () => function Extend(WrappedComponent) {
|
||||
function I18nextWithSSR({
|
||||
initialI18nStore,
|
||||
initialLanguage,
|
||||
...rest
|
||||
}) {
|
||||
(0, _useSSR.useSSR)(initialI18nStore, initialLanguage);
|
||||
return (0, _react.createElement)(WrappedComponent, {
|
||||
...rest
|
||||
});
|
||||
}
|
||||
I18nextWithSSR.getInitialProps = (0, _context.composeInitialProps)(WrappedComponent);
|
||||
I18nextWithSSR.displayName = `withI18nextSSR(${(0, _utils.getDisplayName)(WrappedComponent)})`;
|
||||
I18nextWithSSR.WrappedComponent = WrappedComponent;
|
||||
return I18nextWithSSR;
|
||||
};
|
||||
exports.withSSR = withSSR;
|
||||
39
node_modules/react-i18next/dist/commonjs/withTranslation.js
generated
vendored
Normal file
39
node_modules/react-i18next/dist/commonjs/withTranslation.js
generated
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.withTranslation = void 0;
|
||||
var _react = require("react");
|
||||
var _useTranslation = require("./useTranslation.js");
|
||||
var _utils = require("./utils.js");
|
||||
const withTranslation = (ns, options = {}) => function Extend(WrappedComponent) {
|
||||
function I18nextWithTranslation({
|
||||
forwardedRef,
|
||||
...rest
|
||||
}) {
|
||||
const [t, i18n, ready] = (0, _useTranslation.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 (0, _react.createElement)(WrappedComponent, passDownProps);
|
||||
}
|
||||
I18nextWithTranslation.displayName = `withI18nextTranslation(${(0, _utils.getDisplayName)(WrappedComponent)})`;
|
||||
I18nextWithTranslation.WrappedComponent = WrappedComponent;
|
||||
const forwardRef = (props, ref) => (0, _react.createElement)(I18nextWithTranslation, Object.assign({}, props, {
|
||||
forwardedRef: ref
|
||||
}));
|
||||
return options.withRef ? (0, _react.forwardRef)(forwardRef) : I18nextWithTranslation;
|
||||
};
|
||||
exports.withTranslation = withTranslation;
|
||||
15
node_modules/react-i18next/dist/es/I18nextProvider.js
generated
vendored
Normal file
15
node_modules/react-i18next/dist/es/I18nextProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
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);
|
||||
}
|
||||
43
node_modules/react-i18next/dist/es/Trans.js
generated
vendored
Normal file
43
node_modules/react-i18next/dist/es/Trans.js
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
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?.t.bind(i18n);
|
||||
return TransWithoutContext({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions,
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns: ns || t?.ns || defaultNSFromContext || i18n?.options?.defaultNS,
|
||||
i18n,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
});
|
||||
}
|
||||
321
node_modules/react-i18next/dist/es/TransWithoutContext.js
generated
vendored
Normal file
321
node_modules/react-i18next/dist/es/TransWithoutContext.js
generated
vendored
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
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?.children ?? node.children;
|
||||
if (checkLength) return base.length > 0;
|
||||
return !!base;
|
||||
};
|
||||
const getChildren = node => {
|
||||
if (!node) return [];
|
||||
const children = node.props?.children ?? node.children;
|
||||
return 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
|
||||
};
|
||||
newTarget.props = Object.assign(source.props, target.props);
|
||||
return newTarget;
|
||||
};
|
||||
export const nodesToString = (children, i18nOptions, i18n, i18nKey) => {
|
||||
if (!children) return '';
|
||||
let stringNode = '';
|
||||
const childrenArray = getAsArray(children);
|
||||
const keepArray = i18nOptions?.transSupportBasicHtmlNodes ? i18nOptions.transKeepBasicHtmlNodesFor ?? [] : [];
|
||||
childrenArray.forEach((child, childIndex) => {
|
||||
if (isString(child)) {
|
||||
stringNode += `${child}`;
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
stringNode += `<${type}/>`;
|
||||
return;
|
||||
}
|
||||
if (!childChildren && (!shouldKeepChild || childPropsCount) || props.i18nIsDynamicList) {
|
||||
stringNode += `<${childIndex}></${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (shouldKeepChild && childPropsCount === 1 && isString(childChildren)) {
|
||||
stringNode += `<${type}>${childChildren}</${type}>`;
|
||||
return;
|
||||
}
|
||||
const content = nodesToString(childChildren, i18nOptions, i18n, i18nKey);
|
||||
stringNode += `<${childIndex}>${content}</${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (child === null) {
|
||||
warn(i18n, 'TRANS_NULL_VALUE', `Passed in a null value as child`, {
|
||||
i18nKey
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isObject(child)) {
|
||||
const {
|
||||
format,
|
||||
...clone
|
||||
} = child;
|
||||
const keys = Object.keys(clone);
|
||||
if (keys.length === 1) {
|
||||
const value = format ? `${keys[0]}, ${format}` : keys[0];
|
||||
stringNode += `{{${value}}}`;
|
||||
return;
|
||||
}
|
||||
warn(i18n, 'TRANS_INVALID_OBJ', `Invalid child - Object should only have keys {{ value, format }} (format is optional).`, {
|
||||
i18nKey,
|
||||
child
|
||||
});
|
||||
return;
|
||||
}
|
||||
warn(i18n, 'TRANS_INVALID_VAR', `Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.`, {
|
||||
i18nKey,
|
||||
child
|
||||
});
|
||||
});
|
||||
return stringNode;
|
||||
};
|
||||
const renderNodes = (children, knownComponentsMap, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
|
||||
if (targetString === '') return [];
|
||||
const keepArray = i18nOptions.transKeepBasicHtmlNodesFor || [];
|
||||
const emptyChildrenButNeedsHandling = targetString && new RegExp(keepArray.map(keep => `<${keep}`).join('|')).test(targetString);
|
||||
if (!children && !knownComponentsMap && !emptyChildrenButNeedsHandling && !shouldUnescape) return [targetString];
|
||||
const data = knownComponentsMap ?? {};
|
||||
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);
|
||||
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);
|
||||
return hasValidReactChildren(childs) && mappedChildren.length === 0 || child.props?.i18nIsDynamicList ? childs : mappedChildren;
|
||||
};
|
||||
const pushTranslatedJSX = (child, inner, mem, i, isVoid) => {
|
||||
if (child.dummy) {
|
||||
child.children = inner;
|
||||
mem.push(cloneElement(child, {
|
||||
key: i
|
||||
}, isVoid ? undefined : inner));
|
||||
} else {
|
||||
mem.push(...Children.map([child], c => {
|
||||
const props = {
|
||||
...c.props
|
||||
};
|
||||
delete props.i18nIsDynamicList;
|
||||
return createElement(c.type, {
|
||||
...props,
|
||||
key: i,
|
||||
ref: c.props.ref ?? c.ref
|
||||
}, isVoid ? null : inner);
|
||||
}));
|
||||
}
|
||||
};
|
||||
const mapAST = (reactNode, astNode, rootReactNode) => {
|
||||
const reactNodes = getAsArray(reactNode);
|
||||
const astNodes = getAsArray(astNode);
|
||||
return astNodes.reduce((mem, node, i) => {
|
||||
const translationContent = node.children?.[0]?.content && i18n.services.interpolator.interpolate(node.children[0].content, opts, i18n.language);
|
||||
if (node.type === 'tag') {
|
||||
let tmp = reactNodes[parseInt(node.name, 10)];
|
||||
if (!tmp && knownComponentsMap) tmp = knownComponentsMap[node.name];
|
||||
if (rootReactNode.length === 1 && !tmp) tmp = rootReactNode[0][node.name];
|
||||
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(knownComponentsMap) && Object.hasOwnProperty.call(knownComponentsMap, node.name);
|
||||
if (isString(child)) {
|
||||
const value = i18n.services.interpolator.interpolate(child, opts, i18n.language);
|
||||
mem.push(value);
|
||||
} else if (hasChildren(child) || isValidTranslationWithChildren) {
|
||||
const inner = renderInner(child, node, rootReactNode);
|
||||
pushTranslatedJSX(child, inner, mem, i);
|
||||
} else if (isEmptyTransWithHTML) {
|
||||
const inner = mapAST(reactNodes, 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, 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, node.children, rootReactNode);
|
||||
mem.push(`<${node.name}>${inner}</${node.name}>`);
|
||||
}
|
||||
} else if (isObject(child) && !isElement) {
|
||||
const content = node.children[0] ? translationContent : null;
|
||||
if (content) mem.push(content);
|
||||
} else {
|
||||
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;
|
||||
}, []);
|
||||
};
|
||||
const result = mapAST([{
|
||||
dummy: true,
|
||||
children: children || []
|
||||
}], ast, getAsArray(children || []));
|
||||
return getChildren(result[0]);
|
||||
};
|
||||
const fixComponentProps = (component, index, translation) => {
|
||||
const componentKey = component.key || index;
|
||||
const comp = cloneElement(component, {
|
||||
key: componentKey
|
||||
});
|
||||
if (!comp.props || !comp.props.children || translation.indexOf(`${index}/>`) < 0 && translation.indexOf(`${index} />`) < 0) {
|
||||
return comp;
|
||||
}
|
||||
function Componentized() {
|
||||
return createElement(Fragment, null, comp);
|
||||
}
|
||||
return createElement(Componentized, {
|
||||
key: componentKey
|
||||
});
|
||||
};
|
||||
const generateArrayComponents = (components, translation) => components.map((c, index) => fixComponentProps(c, index, translation));
|
||||
const generateObjectComponents = (components, translation) => {
|
||||
const componentMap = {};
|
||||
Object.keys(components).forEach(c => {
|
||||
Object.assign(componentMap, {
|
||||
[c]: fixComponentProps(components[c], c, translation)
|
||||
});
|
||||
});
|
||||
return componentMap;
|
||||
};
|
||||
const generateComponents = (components, translation, i18n, i18nKey) => {
|
||||
if (!components) return null;
|
||||
if (Array.isArray(components)) {
|
||||
return generateArrayComponents(components, translation);
|
||||
}
|
||||
if (isObject(components)) {
|
||||
return generateObjectComponents(components, translation);
|
||||
}
|
||||
warnOnce(i18n, 'TRANS_INVALID_COMPONENTS', `<Trans /> "components" prop expects an object or array`, {
|
||||
i18nKey
|
||||
});
|
||||
return null;
|
||||
};
|
||||
const isComponentsMap = object => {
|
||||
if (!isObject(object)) return false;
|
||||
if (Array.isArray(object)) return false;
|
||||
return Object.keys(object).reduce((acc, key) => acc && Number.isNaN(Number.parseFloat(key)), true);
|
||||
};
|
||||
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(i18n, 'NO_I18NEXT_INSTANCE', `Trans: You need to pass in an i18next instance using i18nextReactModule`, {
|
||||
i18nKey
|
||||
});
|
||||
return children;
|
||||
}
|
||||
const t = tFromProps || i18n.t.bind(i18n) || (k => k);
|
||||
const reactI18nextOptions = {
|
||||
...getDefaults(),
|
||||
...i18n.options?.react
|
||||
};
|
||||
let namespaces = ns || t.ns || i18n.options?.defaultNS;
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
const nodeAsString = nodesToString(children, reactI18nextOptions, i18n, i18nKey);
|
||||
const defaultValue = defaults || nodeAsString || reactI18nextOptions.transEmptyNodeValue || i18nKey;
|
||||
const {
|
||||
hashTransKey
|
||||
} = reactI18nextOptions;
|
||||
const key = i18nKey || (hashTransKey ? hashTransKey(nodeAsString || defaultValue) : nodeAsString || defaultValue);
|
||||
if (i18n.options?.interpolation?.defaultVariables) {
|
||||
values = values && Object.keys(values).length > 0 ? {
|
||||
...values,
|
||||
...i18n.options.interpolation.defaultVariables
|
||||
} : {
|
||||
...i18n.options.interpolation.defaultVariables
|
||||
};
|
||||
}
|
||||
const interpolationOverride = values || count !== undefined && !i18n.options?.interpolation?.alwaysFormat || !children ? tOptions.interpolation : {
|
||||
interpolation: {
|
||||
...tOptions.interpolation,
|
||||
prefix: '#$?',
|
||||
suffix: '?$#'
|
||||
}
|
||||
};
|
||||
const combinedTOpts = {
|
||||
...tOptions,
|
||||
context: context || tOptions.context,
|
||||
count,
|
||||
...values,
|
||||
...interpolationOverride,
|
||||
defaultValue,
|
||||
ns: namespaces
|
||||
};
|
||||
const translation = key ? t(key, combinedTOpts) : defaultValue;
|
||||
const generatedComponents = generateComponents(components, translation, i18n, i18nKey);
|
||||
let indexedChildren = generatedComponents || children;
|
||||
let componentsMap = null;
|
||||
if (isComponentsMap(generatedComponents)) {
|
||||
componentsMap = generatedComponents;
|
||||
indexedChildren = children;
|
||||
}
|
||||
const content = renderNodes(indexedChildren, componentsMap, translation, i18n, reactI18nextOptions, combinedTOpts, shouldUnescape);
|
||||
const useAsParent = parent ?? reactI18nextOptions.defaultTransParent;
|
||||
return useAsParent ? createElement(useAsParent, additionalProps, content) : content;
|
||||
}
|
||||
12
node_modules/react-i18next/dist/es/Translation.js
generated
vendored
Normal file
12
node_modules/react-i18next/dist/es/Translation.js
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { useTranslation } from './useTranslation.js';
|
||||
export const Translation = ({
|
||||
ns,
|
||||
children,
|
||||
...options
|
||||
}) => {
|
||||
const [t, i18n, ready] = useTranslation(ns, options);
|
||||
return children(t, {
|
||||
i18n,
|
||||
lng: i18n.language
|
||||
}, ready);
|
||||
};
|
||||
42
node_modules/react-i18next/dist/es/context.js
generated
vendored
Normal file
42
node_modules/react-i18next/dist/es/context.js
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
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() {
|
||||
return Object.keys(this.usedNamespaces);
|
||||
}
|
||||
}
|
||||
export const composeInitialProps = ForComponent => async ctx => {
|
||||
const componentsInitialProps = (await ForComponent.getInitialProps?.(ctx)) ?? {};
|
||||
const i18nInitialProps = getInitialProps();
|
||||
return {
|
||||
...componentsInitialProps,
|
||||
...i18nInitialProps
|
||||
};
|
||||
};
|
||||
export const getInitialProps = () => {
|
||||
const i18n = getI18n();
|
||||
const namespaces = 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;
|
||||
};
|
||||
18
node_modules/react-i18next/dist/es/defaults.js
generated
vendored
Normal file
18
node_modules/react-i18next/dist/es/defaults.js
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { unescape } from './unescape.js';
|
||||
let defaultOptions = {
|
||||
bindI18n: 'languageChanged',
|
||||
bindI18nStore: '',
|
||||
transEmptyNodeValue: '',
|
||||
transSupportBasicHtmlNodes: true,
|
||||
transWrapTextNodes: '',
|
||||
transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p'],
|
||||
useSuspense: true,
|
||||
unescape
|
||||
};
|
||||
export const setDefaults = (options = {}) => {
|
||||
defaultOptions = {
|
||||
...defaultOptions,
|
||||
...options
|
||||
};
|
||||
};
|
||||
export const getDefaults = () => defaultOptions;
|
||||
5
node_modules/react-i18next/dist/es/i18nInstance.js
generated
vendored
Normal file
5
node_modules/react-i18next/dist/es/i18nInstance.js
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
let i18nInstance;
|
||||
export const setI18n = instance => {
|
||||
i18nInstance = instance;
|
||||
};
|
||||
export const getI18n = () => i18nInstance;
|
||||
18
node_modules/react-i18next/dist/es/index.js
generated
vendored
Normal file
18
node_modules/react-i18next/dist/es/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
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';
|
||||
export const date = () => '';
|
||||
export const time = () => '';
|
||||
export const number = () => '';
|
||||
export const select = () => '';
|
||||
export const plural = () => '';
|
||||
export const selectOrdinal = () => '';
|
||||
9
node_modules/react-i18next/dist/es/initReactI18next.js
generated
vendored
Normal file
9
node_modules/react-i18next/dist/es/initReactI18next.js
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { setDefaults } from './defaults.js';
|
||||
import { setI18n } from './i18nInstance.js';
|
||||
export const initReactI18next = {
|
||||
type: '3rdParty',
|
||||
init(instance) {
|
||||
setDefaults(instance.options.react);
|
||||
setI18n(instance);
|
||||
}
|
||||
};
|
||||
1
node_modules/react-i18next/dist/es/package.json
generated
vendored
Normal file
1
node_modules/react-i18next/dist/es/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"type":"module","version":"15.6.1"}
|
||||
25
node_modules/react-i18next/dist/es/unescape.js
generated
vendored
Normal file
25
node_modules/react-i18next/dist/es/unescape.js
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
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);
|
||||
27
node_modules/react-i18next/dist/es/useSSR.js
generated
vendored
Normal file
27
node_modules/react-i18next/dist/es/useSSR.js
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
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();
|
||||
if (i18n.options?.isClone) return;
|
||||
if (initialI18nStore && !i18n.initializedStoreOnce) {
|
||||
i18n.services.resourceStore.data = initialI18nStore;
|
||||
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;
|
||||
}
|
||||
};
|
||||
107
node_modules/react-i18next/dist/es/useTranslation.js
generated
vendored
Normal file
107
node_modules/react-i18next/dist/es/useTranslation.js
generated
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
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 = {}) => {
|
||||
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(i18n, 'NO_I18NEXT_INSTANCE', 'useTranslation: 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?.wait) warnOnce(i18n, 'DEPRECATED_OPTION', 'useTranslation: 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;
|
||||
let namespaces = ns || defaultNSFromContext || i18n.options?.defaultNS;
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
i18n.reportNamespaces.addUsedNamespaces?.(namespaces);
|
||||
const ready = (i18n.isInitialized || i18n.initializedStoreOnce) && namespaces.every(n => hasLoadedNamespace(n, i18n, i18nOptions));
|
||||
const memoGetT = useMemoizedT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
||||
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 (!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);
|
||||
};
|
||||
if (bindI18n) i18n?.on(bindI18n, boundReset);
|
||||
if (bindI18nStore) i18n?.store.on(bindI18nStore, boundReset);
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
if (i18n && bindI18n) bindI18n?.split(' ').forEach(e => i18n.off(e, boundReset));
|
||||
if (bindI18nStore && i18n) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, boundReset));
|
||||
};
|
||||
}, [i18n, joinedNS]);
|
||||
useEffect(() => {
|
||||
if (isMounted.current && ready) {
|
||||
setT(getT);
|
||||
}
|
||||
}, [i18n, keyPrefix, ready]);
|
||||
const ret = [t, i18n, ready];
|
||||
ret.t = t;
|
||||
ret.i18n = i18n;
|
||||
ret.ready = ready;
|
||||
if (ready) return ret;
|
||||
if (!ready && !useSuspense) return ret;
|
||||
throw new Promise(resolve => {
|
||||
if (props.lng) {
|
||||
loadLanguages(i18n, props.lng, namespaces, () => resolve());
|
||||
} else {
|
||||
loadNamespaces(i18n, namespaces, () => resolve());
|
||||
}
|
||||
});
|
||||
};
|
||||
62
node_modules/react-i18next/dist/es/utils.js
generated
vendored
Normal file
62
node_modules/react-i18next/dist/es/utils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
export const warn = (i18n, code, msg, rest) => {
|
||||
const args = [msg, {
|
||||
code,
|
||||
...(rest || {})
|
||||
}];
|
||||
if (i18n?.services?.logger?.forward) {
|
||||
return i18n.services.logger.forward(args, 'warn', 'react-i18next::', true);
|
||||
}
|
||||
if (isString(args[0])) args[0] = `react-i18next:: ${args[0]}`;
|
||||
if (i18n?.services?.logger?.warn) {
|
||||
i18n.services.logger.warn(...args);
|
||||
} else if (console?.warn) {
|
||||
console.warn(...args);
|
||||
}
|
||||
};
|
||||
const alreadyWarned = {};
|
||||
export const warnOnce = (i18n, code, msg, rest) => {
|
||||
if (isString(msg) && alreadyWarned[msg]) return;
|
||||
if (isString(msg)) alreadyWarned[msg] = new Date();
|
||||
warn(i18n, code, msg, rest);
|
||||
};
|
||||
const loadedClb = (i18n, cb) => () => {
|
||||
if (i18n.isInitialized) {
|
||||
cb();
|
||||
} else {
|
||||
const initialized = () => {
|
||||
setTimeout(() => {
|
||||
i18n.off('initialized', initialized);
|
||||
}, 0);
|
||||
cb();
|
||||
};
|
||||
i18n.on('initialized', initialized);
|
||||
}
|
||||
};
|
||||
export const loadNamespaces = (i18n, ns, cb) => {
|
||||
i18n.loadNamespaces(ns, loadedClb(i18n, cb));
|
||||
};
|
||||
export const loadLanguages = (i18n, lng, ns, cb) => {
|
||||
if (isString(ns)) ns = [ns];
|
||||
if (i18n.options.preload && i18n.options.preload.indexOf(lng) > -1) return loadNamespaces(i18n, ns, cb);
|
||||
ns.forEach(n => {
|
||||
if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
|
||||
});
|
||||
i18n.loadLanguages(lng, loadedClb(i18n, cb));
|
||||
};
|
||||
export const hasLoadedNamespace = (ns, i18n, options = {}) => {
|
||||
if (!i18n.languages || !i18n.languages.length) {
|
||||
warnOnce(i18n, 'NO_LANGUAGES', 'i18n.languages were undefined or empty', {
|
||||
languages: i18n.languages
|
||||
});
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
20
node_modules/react-i18next/dist/es/withSSR.js
generated
vendored
Normal file
20
node_modules/react-i18next/dist/es/withSSR.js
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
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;
|
||||
};
|
||||
32
node_modules/react-i18next/dist/es/withTranslation.js
generated
vendored
Normal file
32
node_modules/react-i18next/dist/es/withTranslation.js
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
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) => createElement(I18nextWithTranslation, Object.assign({}, props, {
|
||||
forwardedRef: ref
|
||||
}));
|
||||
return options.withRef ? forwardRefReact(forwardRef) : I18nextWithTranslation;
|
||||
};
|
||||
871
node_modules/react-i18next/dist/umd/react-i18next.js
generated
vendored
Normal file
871
node_modules/react-i18next/dist/umd/react-i18next.js
generated
vendored
Normal file
|
|
@ -0,0 +1,871 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
|
||||
typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactI18next = {}, global.React));
|
||||
})(this, (function (exports, react) { 'use strict';
|
||||
|
||||
function getDefaultExportFromCjs (x) {
|
||||
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
||||
}
|
||||
|
||||
var voidElements = {
|
||||
"area": true,
|
||||
"base": true,
|
||||
"br": true,
|
||||
"col": true,
|
||||
"embed": true,
|
||||
"hr": true,
|
||||
"img": true,
|
||||
"input": true,
|
||||
"link": true,
|
||||
"meta": true,
|
||||
"param": true,
|
||||
"source": true,
|
||||
"track": true,
|
||||
"wbr": true
|
||||
};
|
||||
|
||||
var e = /*@__PURE__*/getDefaultExportFromCjs(voidElements);
|
||||
|
||||
var t = /\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?(".*?"|'.*?')/g;
|
||||
function n(n) {
|
||||
var r = {
|
||||
type: "tag",
|
||||
name: "",
|
||||
voidElement: false,
|
||||
attrs: {},
|
||||
children: []
|
||||
},
|
||||
i = n.match(/<\/?([^\s]+?)[/\s>]/);
|
||||
if (i && (r.name = i[1], (e[i[1]] || "/" === n.charAt(n.length - 2)) && (r.voidElement = true), r.name.startsWith("!--"))) {
|
||||
var s = n.indexOf("--\x3e");
|
||||
return {
|
||||
type: "comment",
|
||||
comment: -1 !== s ? n.slice(4, s) : ""
|
||||
};
|
||||
}
|
||||
for (var a = new RegExp(t), c = null; null !== (c = a.exec(n));) if (c[0].trim()) if (c[1]) {
|
||||
var o = c[1].trim(),
|
||||
l = [o, ""];
|
||||
o.indexOf("=") > -1 && (l = o.split("=")), r.attrs[l[0]] = l[1], a.lastIndex--;
|
||||
} else c[2] && (r.attrs[c[2]] = c[3].trim().substring(1, c[3].length - 1));
|
||||
return r;
|
||||
}
|
||||
var r = /<[a-zA-Z0-9\-\!\/](?:"[^"]*"|'[^']*'|[^'">])*>/g,
|
||||
i = /^\s*$/,
|
||||
s = Object.create(null);
|
||||
function a(e, t) {
|
||||
switch (t.type) {
|
||||
case "text":
|
||||
return e + t.content;
|
||||
case "tag":
|
||||
return e += "<" + t.name + (t.attrs ? function (e) {
|
||||
var t = [];
|
||||
for (var n in e) t.push(n + '="' + e[n] + '"');
|
||||
return t.length ? " " + t.join(" ") : "";
|
||||
}(t.attrs) : "") + (t.voidElement ? "/>" : ">"), t.voidElement ? e : e + t.children.reduce(a, "") + "</" + t.name + ">";
|
||||
case "comment":
|
||||
return e + "\x3c!--" + t.comment + "--\x3e";
|
||||
}
|
||||
}
|
||||
var c = {
|
||||
parse: function (e, t) {
|
||||
t || (t = {}), t.components || (t.components = s);
|
||||
var a,
|
||||
c = [],
|
||||
o = [],
|
||||
l = -1,
|
||||
m = false;
|
||||
if (0 !== e.indexOf("<")) {
|
||||
var u = e.indexOf("<");
|
||||
c.push({
|
||||
type: "text",
|
||||
content: -1 === u ? e : e.substring(0, u)
|
||||
});
|
||||
}
|
||||
return e.replace(r, function (r, s) {
|
||||
if (m) {
|
||||
if (r !== "</" + a.name + ">") return;
|
||||
m = false;
|
||||
}
|
||||
var u,
|
||||
f = "/" !== r.charAt(1),
|
||||
h = r.startsWith("\x3c!--"),
|
||||
p = s + r.length,
|
||||
d = e.charAt(p);
|
||||
if (h) {
|
||||
var v = n(r);
|
||||
return l < 0 ? (c.push(v), c) : ((u = o[l]).children.push(v), c);
|
||||
}
|
||||
if (f && (l++, "tag" === (a = n(r)).type && t.components[a.name] && (a.type = "component", m = true), a.voidElement || m || !d || "<" === d || a.children.push({
|
||||
type: "text",
|
||||
content: e.slice(p, e.indexOf("<", p))
|
||||
}), 0 === l && c.push(a), (u = o[l - 1]) && u.children.push(a), o[l] = a), (!f || a.voidElement) && (l > -1 && (a.voidElement || a.name === r.slice(2, -1)) && (l--, a = -1 === l ? c : o[l]), !m && "<" !== d && d)) {
|
||||
u = -1 === l ? c : o[l].children;
|
||||
var x = e.indexOf("<", p),
|
||||
g = e.slice(p, -1 === x ? void 0 : x);
|
||||
i.test(g) && (g = " "), (x > -1 && l + u.length >= 0 || " " !== g) && u.push({
|
||||
type: "text",
|
||||
content: g
|
||||
});
|
||||
}
|
||||
}), c;
|
||||
},
|
||||
stringify: function (e) {
|
||||
return e.reduce(function (e, t) {
|
||||
return e + a("", t);
|
||||
}, "");
|
||||
}
|
||||
};
|
||||
|
||||
const warn = (i18n, code, msg, rest) => {
|
||||
const args = [msg, {
|
||||
code,
|
||||
...(rest || {})
|
||||
}];
|
||||
if (i18n?.services?.logger?.forward) {
|
||||
return i18n.services.logger.forward(args, 'warn', 'react-i18next::', true);
|
||||
}
|
||||
if (isString(args[0])) args[0] = `react-i18next:: ${args[0]}`;
|
||||
if (i18n?.services?.logger?.warn) {
|
||||
i18n.services.logger.warn(...args);
|
||||
} else if (console?.warn) {
|
||||
console.warn(...args);
|
||||
}
|
||||
};
|
||||
const alreadyWarned = {};
|
||||
const warnOnce = (i18n, code, msg, rest) => {
|
||||
if (isString(msg) && alreadyWarned[msg]) return;
|
||||
if (isString(msg)) alreadyWarned[msg] = new Date();
|
||||
warn(i18n, code, msg, rest);
|
||||
};
|
||||
const loadedClb = (i18n, cb) => () => {
|
||||
if (i18n.isInitialized) {
|
||||
cb();
|
||||
} else {
|
||||
const initialized = () => {
|
||||
setTimeout(() => {
|
||||
i18n.off('initialized', initialized);
|
||||
}, 0);
|
||||
cb();
|
||||
};
|
||||
i18n.on('initialized', initialized);
|
||||
}
|
||||
};
|
||||
const loadNamespaces = (i18n, ns, cb) => {
|
||||
i18n.loadNamespaces(ns, loadedClb(i18n, cb));
|
||||
};
|
||||
const loadLanguages = (i18n, lng, ns, cb) => {
|
||||
if (isString(ns)) ns = [ns];
|
||||
if (i18n.options.preload && i18n.options.preload.indexOf(lng) > -1) return loadNamespaces(i18n, ns, cb);
|
||||
ns.forEach(n => {
|
||||
if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
|
||||
});
|
||||
i18n.loadLanguages(lng, loadedClb(i18n, cb));
|
||||
};
|
||||
const hasLoadedNamespace = (ns, i18n, options = {}) => {
|
||||
if (!i18n.languages || !i18n.languages.length) {
|
||||
warnOnce(i18n, 'NO_LANGUAGES', 'i18n.languages were undefined or empty', {
|
||||
languages: i18n.languages
|
||||
});
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
});
|
||||
};
|
||||
const getDisplayName = Component => Component.displayName || Component.name || (isString(Component) && Component.length > 0 ? Component : 'Unknown');
|
||||
const isString = obj => typeof obj === 'string';
|
||||
const isObject = obj => typeof obj === 'object' && obj !== null;
|
||||
|
||||
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];
|
||||
const unescape = text => text.replace(matchHtmlEntity, unescapeHtmlEntity);
|
||||
|
||||
let defaultOptions = {
|
||||
bindI18n: 'languageChanged',
|
||||
bindI18nStore: '',
|
||||
transEmptyNodeValue: '',
|
||||
transSupportBasicHtmlNodes: true,
|
||||
transWrapTextNodes: '',
|
||||
transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p'],
|
||||
useSuspense: true,
|
||||
unescape
|
||||
};
|
||||
const setDefaults = (options = {}) => {
|
||||
defaultOptions = {
|
||||
...defaultOptions,
|
||||
...options
|
||||
};
|
||||
};
|
||||
const getDefaults = () => defaultOptions;
|
||||
|
||||
let i18nInstance;
|
||||
const setI18n = instance => {
|
||||
i18nInstance = instance;
|
||||
};
|
||||
const getI18n = () => i18nInstance;
|
||||
|
||||
const hasChildren = (node, checkLength) => {
|
||||
if (!node) return false;
|
||||
const base = node.props?.children ?? node.children;
|
||||
if (checkLength) return base.length > 0;
|
||||
return !!base;
|
||||
};
|
||||
const getChildren = node => {
|
||||
if (!node) return [];
|
||||
const children = node.props?.children ?? node.children;
|
||||
return node.props?.i18nIsDynamicList ? getAsArray(children) : children;
|
||||
};
|
||||
const hasValidReactChildren = children => Array.isArray(children) && children.every(react.isValidElement);
|
||||
const getAsArray = data => Array.isArray(data) ? data : [data];
|
||||
const mergeProps = (source, target) => {
|
||||
const newTarget = {
|
||||
...target
|
||||
};
|
||||
newTarget.props = Object.assign(source.props, target.props);
|
||||
return newTarget;
|
||||
};
|
||||
const nodesToString = (children, i18nOptions, i18n, i18nKey) => {
|
||||
if (!children) return '';
|
||||
let stringNode = '';
|
||||
const childrenArray = getAsArray(children);
|
||||
const keepArray = i18nOptions?.transSupportBasicHtmlNodes ? i18nOptions.transKeepBasicHtmlNodesFor ?? [] : [];
|
||||
childrenArray.forEach((child, childIndex) => {
|
||||
if (isString(child)) {
|
||||
stringNode += `${child}`;
|
||||
return;
|
||||
}
|
||||
if (react.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) {
|
||||
stringNode += `<${type}/>`;
|
||||
return;
|
||||
}
|
||||
if (!childChildren && (!shouldKeepChild || childPropsCount) || props.i18nIsDynamicList) {
|
||||
stringNode += `<${childIndex}></${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (shouldKeepChild && childPropsCount === 1 && isString(childChildren)) {
|
||||
stringNode += `<${type}>${childChildren}</${type}>`;
|
||||
return;
|
||||
}
|
||||
const content = nodesToString(childChildren, i18nOptions, i18n, i18nKey);
|
||||
stringNode += `<${childIndex}>${content}</${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (child === null) {
|
||||
warn(i18n, 'TRANS_NULL_VALUE', `Passed in a null value as child`, {
|
||||
i18nKey
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isObject(child)) {
|
||||
const {
|
||||
format,
|
||||
...clone
|
||||
} = child;
|
||||
const keys = Object.keys(clone);
|
||||
if (keys.length === 1) {
|
||||
const value = format ? `${keys[0]}, ${format}` : keys[0];
|
||||
stringNode += `{{${value}}}`;
|
||||
return;
|
||||
}
|
||||
warn(i18n, 'TRANS_INVALID_OBJ', `Invalid child - Object should only have keys {{ value, format }} (format is optional).`, {
|
||||
i18nKey,
|
||||
child
|
||||
});
|
||||
return;
|
||||
}
|
||||
warn(i18n, 'TRANS_INVALID_VAR', `Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.`, {
|
||||
i18nKey,
|
||||
child
|
||||
});
|
||||
});
|
||||
return stringNode;
|
||||
};
|
||||
const renderNodes = (children, knownComponentsMap, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
|
||||
if (targetString === '') return [];
|
||||
const keepArray = i18nOptions.transKeepBasicHtmlNodesFor || [];
|
||||
const emptyChildrenButNeedsHandling = targetString && new RegExp(keepArray.map(keep => `<${keep}`).join('|')).test(targetString);
|
||||
if (!children && !knownComponentsMap && !emptyChildrenButNeedsHandling && !shouldUnescape) return [targetString];
|
||||
const data = knownComponentsMap ?? {};
|
||||
const getData = childs => {
|
||||
const childrenArray = getAsArray(childs);
|
||||
childrenArray.forEach(child => {
|
||||
if (isString(child)) return;
|
||||
if (hasChildren(child)) getData(getChildren(child));else if (isObject(child) && !react.isValidElement(child)) Object.assign(data, child);
|
||||
});
|
||||
};
|
||||
getData(children);
|
||||
const ast = c.parse(`<0>${targetString}</0>`);
|
||||
const opts = {
|
||||
...data,
|
||||
...combinedTOpts
|
||||
};
|
||||
const renderInner = (child, node, rootReactNode) => {
|
||||
const childs = getChildren(child);
|
||||
const mappedChildren = mapAST(childs, node.children, rootReactNode);
|
||||
return hasValidReactChildren(childs) && mappedChildren.length === 0 || child.props?.i18nIsDynamicList ? childs : mappedChildren;
|
||||
};
|
||||
const pushTranslatedJSX = (child, inner, mem, i, isVoid) => {
|
||||
if (child.dummy) {
|
||||
child.children = inner;
|
||||
mem.push(react.cloneElement(child, {
|
||||
key: i
|
||||
}, isVoid ? undefined : inner));
|
||||
} else {
|
||||
mem.push(...react.Children.map([child], c => {
|
||||
const props = {
|
||||
...c.props
|
||||
};
|
||||
delete props.i18nIsDynamicList;
|
||||
return react.createElement(c.type, {
|
||||
...props,
|
||||
key: i,
|
||||
ref: c.props.ref ?? c.ref
|
||||
}, isVoid ? null : inner);
|
||||
}));
|
||||
}
|
||||
};
|
||||
const mapAST = (reactNode, astNode, rootReactNode) => {
|
||||
const reactNodes = getAsArray(reactNode);
|
||||
const astNodes = getAsArray(astNode);
|
||||
return astNodes.reduce((mem, node, i) => {
|
||||
const translationContent = node.children?.[0]?.content && i18n.services.interpolator.interpolate(node.children[0].content, opts, i18n.language);
|
||||
if (node.type === 'tag') {
|
||||
let tmp = reactNodes[parseInt(node.name, 10)];
|
||||
if (!tmp && knownComponentsMap) tmp = knownComponentsMap[node.name];
|
||||
if (rootReactNode.length === 1 && !tmp) tmp = rootReactNode[0][node.name];
|
||||
if (!tmp) tmp = {};
|
||||
const child = Object.keys(node.attrs).length !== 0 ? mergeProps({
|
||||
props: node.attrs
|
||||
}, tmp) : tmp;
|
||||
const isElement = react.isValidElement(child);
|
||||
const isValidTranslationWithChildren = isElement && hasChildren(node, true) && !node.voidElement;
|
||||
const isEmptyTransWithHTML = emptyChildrenButNeedsHandling && isObject(child) && child.dummy && !isElement;
|
||||
const isKnownComponent = isObject(knownComponentsMap) && Object.hasOwnProperty.call(knownComponentsMap, node.name);
|
||||
if (isString(child)) {
|
||||
const value = i18n.services.interpolator.interpolate(child, opts, i18n.language);
|
||||
mem.push(value);
|
||||
} else if (hasChildren(child) || isValidTranslationWithChildren) {
|
||||
const inner = renderInner(child, node, rootReactNode);
|
||||
pushTranslatedJSX(child, inner, mem, i);
|
||||
} else if (isEmptyTransWithHTML) {
|
||||
const inner = mapAST(reactNodes, 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(react.createElement(node.name, {
|
||||
key: `${node.name}-${i}`
|
||||
}));
|
||||
} else {
|
||||
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
||||
mem.push(react.createElement(node.name, {
|
||||
key: `${node.name}-${i}`
|
||||
}, inner));
|
||||
}
|
||||
} else if (node.voidElement) {
|
||||
mem.push(`<${node.name} />`);
|
||||
} else {
|
||||
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
||||
mem.push(`<${node.name}>${inner}</${node.name}>`);
|
||||
}
|
||||
} else if (isObject(child) && !isElement) {
|
||||
const content = node.children[0] ? translationContent : null;
|
||||
if (content) mem.push(content);
|
||||
} else {
|
||||
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(react.createElement(wrapTextNodes, {
|
||||
key: `${node.name}-${i}`
|
||||
}, content));
|
||||
} else {
|
||||
mem.push(content);
|
||||
}
|
||||
}
|
||||
return mem;
|
||||
}, []);
|
||||
};
|
||||
const result = mapAST([{
|
||||
dummy: true,
|
||||
children: children || []
|
||||
}], ast, getAsArray(children || []));
|
||||
return getChildren(result[0]);
|
||||
};
|
||||
const fixComponentProps = (component, index, translation) => {
|
||||
const componentKey = component.key || index;
|
||||
const comp = react.cloneElement(component, {
|
||||
key: componentKey
|
||||
});
|
||||
if (!comp.props || !comp.props.children || translation.indexOf(`${index}/>`) < 0 && translation.indexOf(`${index} />`) < 0) {
|
||||
return comp;
|
||||
}
|
||||
function Componentized() {
|
||||
return react.createElement(react.Fragment, null, comp);
|
||||
}
|
||||
return react.createElement(Componentized, {
|
||||
key: componentKey
|
||||
});
|
||||
};
|
||||
const generateArrayComponents = (components, translation) => components.map((c, index) => fixComponentProps(c, index, translation));
|
||||
const generateObjectComponents = (components, translation) => {
|
||||
const componentMap = {};
|
||||
Object.keys(components).forEach(c => {
|
||||
Object.assign(componentMap, {
|
||||
[c]: fixComponentProps(components[c], c, translation)
|
||||
});
|
||||
});
|
||||
return componentMap;
|
||||
};
|
||||
const generateComponents = (components, translation, i18n, i18nKey) => {
|
||||
if (!components) return null;
|
||||
if (Array.isArray(components)) {
|
||||
return generateArrayComponents(components, translation);
|
||||
}
|
||||
if (isObject(components)) {
|
||||
return generateObjectComponents(components, translation);
|
||||
}
|
||||
warnOnce(i18n, 'TRANS_INVALID_COMPONENTS', `<Trans /> "components" prop expects an object or array`, {
|
||||
i18nKey
|
||||
});
|
||||
return null;
|
||||
};
|
||||
const isComponentsMap = object => {
|
||||
if (!isObject(object)) return false;
|
||||
if (Array.isArray(object)) return false;
|
||||
return Object.keys(object).reduce((acc, key) => acc && Number.isNaN(Number.parseFloat(key)), true);
|
||||
};
|
||||
function Trans$1({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions = {},
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns,
|
||||
i18n: i18nFromProps,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
}) {
|
||||
const i18n = i18nFromProps || getI18n();
|
||||
if (!i18n) {
|
||||
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', `Trans: You need to pass in an i18next instance using i18nextReactModule`, {
|
||||
i18nKey
|
||||
});
|
||||
return children;
|
||||
}
|
||||
const t = tFromProps || i18n.t.bind(i18n) || (k => k);
|
||||
const reactI18nextOptions = {
|
||||
...getDefaults(),
|
||||
...i18n.options?.react
|
||||
};
|
||||
let namespaces = ns || t.ns || i18n.options?.defaultNS;
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
const nodeAsString = nodesToString(children, reactI18nextOptions, i18n, i18nKey);
|
||||
const defaultValue = defaults || nodeAsString || reactI18nextOptions.transEmptyNodeValue || i18nKey;
|
||||
const {
|
||||
hashTransKey
|
||||
} = reactI18nextOptions;
|
||||
const key = i18nKey || (hashTransKey ? hashTransKey(nodeAsString || defaultValue) : nodeAsString || defaultValue);
|
||||
if (i18n.options?.interpolation?.defaultVariables) {
|
||||
values = values && Object.keys(values).length > 0 ? {
|
||||
...values,
|
||||
...i18n.options.interpolation.defaultVariables
|
||||
} : {
|
||||
...i18n.options.interpolation.defaultVariables
|
||||
};
|
||||
}
|
||||
const interpolationOverride = values || count !== undefined && !i18n.options?.interpolation?.alwaysFormat || !children ? tOptions.interpolation : {
|
||||
interpolation: {
|
||||
...tOptions.interpolation,
|
||||
prefix: '#$?',
|
||||
suffix: '?$#'
|
||||
}
|
||||
};
|
||||
const combinedTOpts = {
|
||||
...tOptions,
|
||||
context: context || tOptions.context,
|
||||
count,
|
||||
...values,
|
||||
...interpolationOverride,
|
||||
defaultValue,
|
||||
ns: namespaces
|
||||
};
|
||||
const translation = key ? t(key, combinedTOpts) : defaultValue;
|
||||
const generatedComponents = generateComponents(components, translation, i18n, i18nKey);
|
||||
let indexedChildren = generatedComponents || children;
|
||||
let componentsMap = null;
|
||||
if (isComponentsMap(generatedComponents)) {
|
||||
componentsMap = generatedComponents;
|
||||
indexedChildren = children;
|
||||
}
|
||||
const content = renderNodes(indexedChildren, componentsMap, translation, i18n, reactI18nextOptions, combinedTOpts, shouldUnescape);
|
||||
const useAsParent = parent ?? reactI18nextOptions.defaultTransParent;
|
||||
return useAsParent ? react.createElement(useAsParent, additionalProps, content) : content;
|
||||
}
|
||||
|
||||
const initReactI18next = {
|
||||
type: '3rdParty',
|
||||
init(instance) {
|
||||
setDefaults(instance.options.react);
|
||||
setI18n(instance);
|
||||
}
|
||||
};
|
||||
|
||||
const I18nContext = react.createContext();
|
||||
class ReportNamespaces {
|
||||
constructor() {
|
||||
this.usedNamespaces = {};
|
||||
}
|
||||
addUsedNamespaces(namespaces) {
|
||||
namespaces.forEach(ns => {
|
||||
if (!this.usedNamespaces[ns]) this.usedNamespaces[ns] = true;
|
||||
});
|
||||
}
|
||||
getUsedNamespaces() {
|
||||
return Object.keys(this.usedNamespaces);
|
||||
}
|
||||
}
|
||||
const composeInitialProps = ForComponent => async ctx => {
|
||||
const componentsInitialProps = (await ForComponent.getInitialProps?.(ctx)) ?? {};
|
||||
const i18nInitialProps = getInitialProps();
|
||||
return {
|
||||
...componentsInitialProps,
|
||||
...i18nInitialProps
|
||||
};
|
||||
};
|
||||
const getInitialProps = () => {
|
||||
const i18n = getI18n();
|
||||
const namespaces = 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;
|
||||
};
|
||||
|
||||
function Trans({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions = {},
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns,
|
||||
i18n: i18nFromProps,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
}) {
|
||||
const {
|
||||
i18n: i18nFromContext,
|
||||
defaultNS: defaultNSFromContext
|
||||
} = react.useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
const t = tFromProps || i18n?.t.bind(i18n);
|
||||
return Trans$1({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions,
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns: ns || t?.ns || defaultNSFromContext || i18n?.options?.defaultNS,
|
||||
i18n,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
});
|
||||
}
|
||||
|
||||
const usePrevious = (value, ignore) => {
|
||||
const ref = react.useRef();
|
||||
react.useEffect(() => {
|
||||
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) => react.useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [i18n, language, namespace, keyPrefix]);
|
||||
const useTranslation = (ns, props = {}) => {
|
||||
const {
|
||||
i18n: i18nFromProps
|
||||
} = props;
|
||||
const {
|
||||
i18n: i18nFromContext,
|
||||
defaultNS: defaultNSFromContext
|
||||
} = react.useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
|
||||
if (!i18n) {
|
||||
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', 'useTranslation: 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?.wait) warnOnce(i18n, 'DEPRECATED_OPTION', 'useTranslation: 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;
|
||||
let namespaces = ns || defaultNSFromContext || i18n.options?.defaultNS;
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
i18n.reportNamespaces.addUsedNamespaces?.(namespaces);
|
||||
const ready = (i18n.isInitialized || i18n.initializedStoreOnce) && namespaces.every(n => hasLoadedNamespace(n, i18n, i18nOptions));
|
||||
const memoGetT = useMemoizedT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
||||
const getT = () => memoGetT;
|
||||
const getNewT = () => alwaysNewT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
||||
const [t, setT] = react.useState(getT);
|
||||
let joinedNS = namespaces.join();
|
||||
if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
|
||||
const previousJoinedNS = usePrevious(joinedNS);
|
||||
const isMounted = react.useRef(true);
|
||||
react.useEffect(() => {
|
||||
const {
|
||||
bindI18n,
|
||||
bindI18nStore
|
||||
} = i18nOptions;
|
||||
isMounted.current = true;
|
||||
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);
|
||||
};
|
||||
if (bindI18n) i18n?.on(bindI18n, boundReset);
|
||||
if (bindI18nStore) i18n?.store.on(bindI18nStore, boundReset);
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
if (i18n && bindI18n) bindI18n?.split(' ').forEach(e => i18n.off(e, boundReset));
|
||||
if (bindI18nStore && i18n) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, boundReset));
|
||||
};
|
||||
}, [i18n, joinedNS]);
|
||||
react.useEffect(() => {
|
||||
if (isMounted.current && ready) {
|
||||
setT(getT);
|
||||
}
|
||||
}, [i18n, keyPrefix, ready]);
|
||||
const ret = [t, i18n, ready];
|
||||
ret.t = t;
|
||||
ret.i18n = i18n;
|
||||
ret.ready = ready;
|
||||
if (ready) return ret;
|
||||
if (!ready && !useSuspense) return ret;
|
||||
throw new Promise(resolve => {
|
||||
if (props.lng) {
|
||||
loadLanguages(i18n, props.lng, namespaces, () => resolve());
|
||||
} else {
|
||||
loadNamespaces(i18n, namespaces, () => resolve());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
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 react.createElement(WrappedComponent, passDownProps);
|
||||
}
|
||||
I18nextWithTranslation.displayName = `withI18nextTranslation(${getDisplayName(WrappedComponent)})`;
|
||||
I18nextWithTranslation.WrappedComponent = WrappedComponent;
|
||||
const forwardRef = (props, ref) => react.createElement(I18nextWithTranslation, Object.assign({}, props, {
|
||||
forwardedRef: ref
|
||||
}));
|
||||
return options.withRef ? react.forwardRef(forwardRef) : I18nextWithTranslation;
|
||||
};
|
||||
|
||||
const Translation = ({
|
||||
ns,
|
||||
children,
|
||||
...options
|
||||
}) => {
|
||||
const [t, i18n, ready] = useTranslation(ns, options);
|
||||
return children(t, {
|
||||
i18n,
|
||||
lng: i18n.language
|
||||
}, ready);
|
||||
};
|
||||
|
||||
function I18nextProvider({
|
||||
i18n,
|
||||
defaultNS,
|
||||
children
|
||||
}) {
|
||||
const value = react.useMemo(() => ({
|
||||
i18n,
|
||||
defaultNS
|
||||
}), [i18n, defaultNS]);
|
||||
return react.createElement(I18nContext.Provider, {
|
||||
value
|
||||
}, children);
|
||||
}
|
||||
|
||||
const useSSR = (initialI18nStore, initialLanguage, props = {}) => {
|
||||
const {
|
||||
i18n: i18nFromProps
|
||||
} = props;
|
||||
const {
|
||||
i18n: i18nFromContext
|
||||
} = react.useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
if (i18n.options?.isClone) return;
|
||||
if (initialI18nStore && !i18n.initializedStoreOnce) {
|
||||
i18n.services.resourceStore.data = initialI18nStore;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
const withSSR = () => function Extend(WrappedComponent) {
|
||||
function I18nextWithSSR({
|
||||
initialI18nStore,
|
||||
initialLanguage,
|
||||
...rest
|
||||
}) {
|
||||
useSSR(initialI18nStore, initialLanguage);
|
||||
return react.createElement(WrappedComponent, {
|
||||
...rest
|
||||
});
|
||||
}
|
||||
I18nextWithSSR.getInitialProps = composeInitialProps(WrappedComponent);
|
||||
I18nextWithSSR.displayName = `withI18nextSSR(${getDisplayName(WrappedComponent)})`;
|
||||
I18nextWithSSR.WrappedComponent = WrappedComponent;
|
||||
return I18nextWithSSR;
|
||||
};
|
||||
|
||||
const date = () => '';
|
||||
const time = () => '';
|
||||
const number = () => '';
|
||||
const select = () => '';
|
||||
const plural = () => '';
|
||||
const selectOrdinal = () => '';
|
||||
|
||||
exports.I18nContext = I18nContext;
|
||||
exports.I18nextProvider = I18nextProvider;
|
||||
exports.Trans = Trans;
|
||||
exports.TransWithoutContext = Trans$1;
|
||||
exports.Translation = Translation;
|
||||
exports.composeInitialProps = composeInitialProps;
|
||||
exports.date = date;
|
||||
exports.getDefaults = getDefaults;
|
||||
exports.getI18n = getI18n;
|
||||
exports.getInitialProps = getInitialProps;
|
||||
exports.initReactI18next = initReactI18next;
|
||||
exports.number = number;
|
||||
exports.plural = plural;
|
||||
exports.select = select;
|
||||
exports.selectOrdinal = selectOrdinal;
|
||||
exports.setDefaults = setDefaults;
|
||||
exports.setI18n = setI18n;
|
||||
exports.time = time;
|
||||
exports.useSSR = useSSR;
|
||||
exports.useTranslation = useTranslation;
|
||||
exports.withSSR = withSSR;
|
||||
exports.withTranslation = withTranslation;
|
||||
|
||||
}));
|
||||
1
node_modules/react-i18next/dist/umd/react-i18next.min.js
generated
vendored
Normal file
1
node_modules/react-i18next/dist/umd/react-i18next.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
3
node_modules/react-i18next/helpers.d.ts
generated
vendored
Normal file
3
node_modules/react-i18next/helpers.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// Internal Helpers
|
||||
export type $Tuple<T> = readonly [T?, ...T[]];
|
||||
export type $Subtract<T extends K, K> = Omit<T, keyof K>;
|
||||
1
node_modules/react-i18next/icu.macro.d.mts
generated
vendored
Normal file
1
node_modules/react-i18next/icu.macro.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './icu.macro.js';
|
||||
103
node_modules/react-i18next/icu.macro.d.ts
generated
vendored
Normal file
103
node_modules/react-i18next/icu.macro.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
import { ReactElement } from 'react';
|
||||
import { Trans } from './index.js';
|
||||
import type { Namespace, TypeOptions, i18n, ParseKeys } from 'i18next';
|
||||
|
||||
export { Trans };
|
||||
|
||||
type _DefaultNamespace = TypeOptions['defaultNS'];
|
||||
declare module 'react-i18next/icu.macro' {
|
||||
export interface PluralSubProps<
|
||||
Key extends ParseKeys<Ns, {}, ''>,
|
||||
Ns extends Namespace = _DefaultNamespace,
|
||||
> {
|
||||
children?: never;
|
||||
i18nKey?: Key;
|
||||
i18n?: i18n;
|
||||
ns?: Ns;
|
||||
count: number;
|
||||
values?: {};
|
||||
zero?: string | ReactElement;
|
||||
one?: string | ReactElement;
|
||||
two?: string | ReactElement;
|
||||
few?: string | ReactElement;
|
||||
many?: string | ReactElement;
|
||||
other: string | ReactElement;
|
||||
}
|
||||
|
||||
type PluralProps<
|
||||
T,
|
||||
Key extends ParseKeys<Ns, {}, ''>,
|
||||
Ns extends Namespace = _DefaultNamespace,
|
||||
> = {
|
||||
[P in keyof T]: P extends keyof PluralSubProps<Key, Ns>
|
||||
? // support the standard properties of Plural
|
||||
PluralSubProps<Key, Ns>[P]
|
||||
: // this supports infinite $0={..} or $123={..}
|
||||
// technically it also supports $-1={..} and $2.3={..} but we don't need to
|
||||
// worry since that's invalid syntax.
|
||||
P extends `$${number}`
|
||||
? string | ReactElement
|
||||
: never;
|
||||
};
|
||||
|
||||
interface SelectSubProps {
|
||||
[key: string]: string | ReactElement;
|
||||
}
|
||||
|
||||
interface NoChildren {
|
||||
children?: never;
|
||||
}
|
||||
|
||||
interface SelectRequiredProps<
|
||||
Key extends ParseKeys<Ns, {}, ''>,
|
||||
Ns extends Namespace = _DefaultNamespace,
|
||||
> extends NoChildren {
|
||||
i18nKey?: Key;
|
||||
i18n?: i18n;
|
||||
ns?: Ns;
|
||||
other: string | ReactElement;
|
||||
}
|
||||
|
||||
// defining it this way ensures that `other` is always defined, but allows
|
||||
// unlimited other select types.
|
||||
type SelectProps<
|
||||
Key extends ParseKeys<Ns, {}, ''>,
|
||||
Ns extends Namespace = _DefaultNamespace,
|
||||
> = SelectSubProps & SelectRequiredProps<Key, Ns>;
|
||||
|
||||
function Plural<T, Key extends ParseKeys<Ns, {}, ''>, Ns extends Namespace = _DefaultNamespace>(
|
||||
props: PluralProps<T, Key, Ns> & NoChildren,
|
||||
): ReactElement;
|
||||
|
||||
function SelectOrdinal<
|
||||
T,
|
||||
Key extends ParseKeys<Ns, {}, ''>,
|
||||
Ns extends Namespace = _DefaultNamespace,
|
||||
>(props: PluralProps<T, Key, Ns> & NoChildren): ReactElement;
|
||||
|
||||
function Select<Key extends ParseKeys<Ns, {}, ''>, Ns extends Namespace = _DefaultNamespace>(
|
||||
props: SelectProps<Key, Ns>,
|
||||
): ReactElement;
|
||||
|
||||
function date(strings: TemplateStringsArray, variable: Date): string;
|
||||
function time(strings: TemplateStringsArray, variable: Date): string;
|
||||
function number(strings: TemplateStringsArray, variable: number): string;
|
||||
|
||||
type ValidInterpolations = ReactElement | string;
|
||||
|
||||
function plural(
|
||||
strings: TemplateStringsArray,
|
||||
variable: number,
|
||||
...args: ValidInterpolations[]
|
||||
): string;
|
||||
function selectOrdinal(
|
||||
strings: TemplateStringsArray,
|
||||
variable: number,
|
||||
...args: ValidInterpolations[]
|
||||
): string;
|
||||
function select(
|
||||
strings: TemplateStringsArray,
|
||||
variable: string,
|
||||
...args: ValidInterpolations[]
|
||||
): string;
|
||||
}
|
||||
729
node_modules/react-i18next/icu.macro.js
generated
vendored
Normal file
729
node_modules/react-i18next/icu.macro.js
generated
vendored
Normal file
|
|
@ -0,0 +1,729 @@
|
|||
const { createMacro } = require('babel-plugin-macros');
|
||||
|
||||
// copy to:
|
||||
// https://astexplorer.net/#/gist/642aebbb9e449e959f4ad8907b4adf3a/4a65742e2a3e926eb55eaa3d657d1472b9ac7970
|
||||
module.exports = createMacro(ICUMacro);
|
||||
|
||||
function ICUMacro({ references, state, babel }) {
|
||||
const {
|
||||
Trans = [],
|
||||
Plural = [],
|
||||
Select = [],
|
||||
SelectOrdinal = [],
|
||||
number = [],
|
||||
date = [],
|
||||
select = [],
|
||||
selectOrdinal = [],
|
||||
plural = [],
|
||||
time = [],
|
||||
} = references;
|
||||
|
||||
// assert we have the react-i18next Trans component imported
|
||||
addNeededImports(state, babel, references);
|
||||
|
||||
// transform Plural and SelectOrdinal
|
||||
[...Plural, ...SelectOrdinal].forEach((referencePath) => {
|
||||
if (referencePath.parentPath.type === 'JSXOpeningElement') {
|
||||
pluralAsJSX(
|
||||
referencePath.parentPath,
|
||||
{
|
||||
attributes: referencePath.parentPath.get('attributes'),
|
||||
children: referencePath.parentPath.parentPath.get('children'),
|
||||
},
|
||||
babel,
|
||||
);
|
||||
} else {
|
||||
// throw a helpful error message or something :)
|
||||
}
|
||||
});
|
||||
|
||||
// transform Select
|
||||
Select.forEach((referencePath) => {
|
||||
if (referencePath.parentPath.type === 'JSXOpeningElement') {
|
||||
selectAsJSX(
|
||||
referencePath.parentPath,
|
||||
{
|
||||
attributes: referencePath.parentPath.get('attributes'),
|
||||
children: referencePath.parentPath.parentPath.get('children'),
|
||||
},
|
||||
babel,
|
||||
);
|
||||
} else {
|
||||
// throw a helpful error message or something :)
|
||||
}
|
||||
});
|
||||
|
||||
// transform Trans
|
||||
Trans.forEach((referencePath) => {
|
||||
if (referencePath.parentPath.type === 'JSXOpeningElement') {
|
||||
transAsJSX(
|
||||
referencePath.parentPath,
|
||||
{
|
||||
attributes: referencePath.parentPath.get('attributes'),
|
||||
children: referencePath.parentPath.parentPath.get('children'),
|
||||
},
|
||||
babel,
|
||||
state,
|
||||
);
|
||||
} else {
|
||||
// throw a helpful error message or something :)
|
||||
}
|
||||
});
|
||||
|
||||
// check for number`` and others outside of <Trans>
|
||||
Object.entries({
|
||||
number,
|
||||
date,
|
||||
time,
|
||||
select,
|
||||
plural,
|
||||
selectOrdinal,
|
||||
}).forEach(([name, node]) => {
|
||||
node.forEach((item) => {
|
||||
let f = item.parentPath;
|
||||
while (f) {
|
||||
if (babel.types.isJSXElement(f)) {
|
||||
if (f.node.openingElement.name.name === 'Trans') {
|
||||
// this is a valid use of number/date/time/etc.
|
||||
return;
|
||||
}
|
||||
}
|
||||
f = f.parentPath;
|
||||
}
|
||||
throw new Error(
|
||||
`"${name}\`\`" can only be used inside <Trans> in "${item.node.loc.filename}" on line ${item.node.loc.start.line}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function pluralAsJSX(parentPath, { attributes }, babel) {
|
||||
const t = babel.types;
|
||||
const toObjectProperty = (name, value) =>
|
||||
t.objectProperty(t.identifier(name), t.identifier(name), false, !value);
|
||||
|
||||
// plural or selectordinal
|
||||
const nodeName = parentPath.node.name.name.toLocaleLowerCase();
|
||||
|
||||
// will need to merge count attribute with existing values attribute in some cases
|
||||
const existingValuesAttribute = findAttribute('values', attributes);
|
||||
const existingValues = existingValuesAttribute
|
||||
? existingValuesAttribute.node.value.expression.properties
|
||||
: [];
|
||||
|
||||
let componentStartIndex = 0;
|
||||
const extracted = attributes.reduce(
|
||||
(mem, attr) => {
|
||||
if (attr.node.name.name === 'i18nKey') {
|
||||
// copy the i18nKey
|
||||
mem.attributesToCopy.push(attr.node);
|
||||
} else if (attr.node.name.name === 'count') {
|
||||
// take the count for element
|
||||
let exprName = attr.node.value.expression.name;
|
||||
if (!exprName) {
|
||||
exprName = 'count';
|
||||
}
|
||||
if (exprName === 'count') {
|
||||
// if the prop expression name is also "count", copy it instead: <Plural count={count} --> <Trans count={count}
|
||||
mem.attributesToCopy.push(attr.node);
|
||||
} else {
|
||||
mem.values.unshift(toObjectProperty(exprName));
|
||||
}
|
||||
mem.defaults = `{${exprName}, ${nodeName}, ${mem.defaults}`;
|
||||
} else if (attr.node.name.name === 'values') {
|
||||
// skip the values attribute, as it has already been processed into mem from existingValues
|
||||
} else if (attr.node.value.type === 'StringLiteral') {
|
||||
// take any string node as plural option
|
||||
let pluralForm = attr.node.name.name;
|
||||
if (pluralForm.indexOf('$') === 0) pluralForm = pluralForm.replace('$', '=');
|
||||
mem.defaults = `${mem.defaults} ${pluralForm} {${attr.node.value.value}}`;
|
||||
} else if (attr.node.value.type === 'JSXExpressionContainer') {
|
||||
// convert any Trans component to plural option extracting any values and components
|
||||
const children = attr.node.value.expression.children || [];
|
||||
const thisTrans = processTrans(children, babel, componentStartIndex);
|
||||
|
||||
let pluralForm = attr.node.name.name;
|
||||
if (pluralForm.indexOf('$') === 0) pluralForm = pluralForm.replace('$', '=');
|
||||
|
||||
mem.defaults = `${mem.defaults} ${pluralForm} {${thisTrans.defaults}}`;
|
||||
mem.components = mem.components.concat(thisTrans.components);
|
||||
|
||||
componentStartIndex += thisTrans.components.length;
|
||||
}
|
||||
return mem;
|
||||
},
|
||||
{ attributesToCopy: [], values: existingValues, components: [], defaults: '' },
|
||||
);
|
||||
|
||||
// replace the node with the new Trans
|
||||
parentPath.replaceWith(buildTransElement(extracted, extracted.attributesToCopy, t, true));
|
||||
}
|
||||
|
||||
function selectAsJSX(parentPath, { attributes }, babel) {
|
||||
const t = babel.types;
|
||||
const toObjectProperty = (name, value) =>
|
||||
t.objectProperty(t.identifier(name), t.identifier(name), false, !value);
|
||||
|
||||
// will need to merge switch attribute with existing values attribute
|
||||
const existingValuesAttribute = findAttribute('values', attributes);
|
||||
const existingValues = existingValuesAttribute
|
||||
? existingValuesAttribute.node.value.expression.properties
|
||||
: [];
|
||||
|
||||
let componentStartIndex = 0;
|
||||
|
||||
const extracted = attributes.reduce(
|
||||
(mem, attr) => {
|
||||
if (attr.node.name.name === 'i18nKey') {
|
||||
// copy the i18nKey
|
||||
mem.attributesToCopy.push(attr.node);
|
||||
} else if (attr.node.name.name === 'switch') {
|
||||
// take the switch for select element
|
||||
let exprName = attr.node.value.expression.name;
|
||||
if (!exprName) {
|
||||
exprName = 'selectKey';
|
||||
mem.values.unshift(t.objectProperty(t.identifier(exprName), attr.node.value.expression));
|
||||
} else {
|
||||
mem.values.unshift(toObjectProperty(exprName));
|
||||
}
|
||||
mem.defaults = `{${exprName}, select, ${mem.defaults}`;
|
||||
} else if (attr.node.name.name === 'values') {
|
||||
// skip the values attribute, as it has already been processed into mem as existingValues
|
||||
} else if (attr.node.value.type === 'StringLiteral') {
|
||||
// take any string node as select option
|
||||
mem.defaults = `${mem.defaults} ${attr.node.name.name} {${attr.node.value.value}}`;
|
||||
} else if (attr.node.value.type === 'JSXExpressionContainer') {
|
||||
// convert any Trans component to select option extracting any values and components
|
||||
const children = attr.node.value.expression.children || [];
|
||||
const thisTrans = processTrans(children, babel, componentStartIndex);
|
||||
|
||||
mem.defaults = `${mem.defaults} ${attr.node.name.name} {${thisTrans.defaults}}`;
|
||||
mem.components = mem.components.concat(thisTrans.components);
|
||||
|
||||
componentStartIndex += thisTrans.components.length;
|
||||
}
|
||||
return mem;
|
||||
},
|
||||
{ attributesToCopy: [], values: existingValues, components: [], defaults: '' },
|
||||
);
|
||||
|
||||
// replace the node with the new Trans
|
||||
parentPath.replaceWith(buildTransElement(extracted, extracted.attributesToCopy, t, true));
|
||||
}
|
||||
|
||||
function transAsJSX(parentPath, { attributes, children }, babel, { filename }) {
|
||||
const defaultsAttr = findAttribute('defaults', attributes);
|
||||
const componentsAttr = findAttribute('components', attributes);
|
||||
// if there is "defaults" attribute and no "components" attribute, parse defaults and extract from the parsed defaults instead of children
|
||||
// if a "components" attribute has been provided, we assume they have already constructed a valid "defaults" and it does not need to be parsed
|
||||
const parseDefaults = defaultsAttr && !componentsAttr;
|
||||
|
||||
let extracted;
|
||||
if (parseDefaults) {
|
||||
const defaultsExpression = defaultsAttr.node.value.value;
|
||||
const parsed = babel.parse(`<>${defaultsExpression}</>`, {
|
||||
presets: ['@babel/react'],
|
||||
filename,
|
||||
}).program.body[0].expression.children;
|
||||
|
||||
extracted = processTrans(parsed, babel);
|
||||
} else {
|
||||
extracted = processTrans(children, babel);
|
||||
}
|
||||
|
||||
let clonedAttributes = cloneExistingAttributes(attributes);
|
||||
if (parseDefaults) {
|
||||
// remove existing defaults so it can be replaced later with the new parsed defaults
|
||||
clonedAttributes = clonedAttributes.filter((node) => node.name.name !== 'defaults');
|
||||
}
|
||||
|
||||
// replace the node with the new Trans
|
||||
const replacePath = children.length ? children[0].parentPath : parentPath;
|
||||
replacePath.replaceWith(
|
||||
buildTransElement(extracted, clonedAttributes, babel.types, false, !!children.length),
|
||||
);
|
||||
}
|
||||
|
||||
function buildTransElement(
|
||||
extracted,
|
||||
finalAttributes,
|
||||
t,
|
||||
closeDefaults = false,
|
||||
wasElementWithChildren = false,
|
||||
) {
|
||||
const nodeName = t.jSXIdentifier('Trans');
|
||||
|
||||
// plural, select open { but do not close it while reduce
|
||||
if (closeDefaults) extracted.defaults += '}';
|
||||
|
||||
// convert arrays into needed expressions
|
||||
extracted.components = t.arrayExpression(extracted.components);
|
||||
extracted.values = t.objectExpression(extracted.values);
|
||||
|
||||
// add generated Trans attributes
|
||||
if (!attributeExistsAlready('defaults', finalAttributes))
|
||||
if (extracted.defaults.includes(`"`)) {
|
||||
// wrap defaults that contain double quotes in brackets
|
||||
finalAttributes.push(
|
||||
t.jSXAttribute(
|
||||
t.jSXIdentifier('defaults'),
|
||||
t.jSXExpressionContainer(t.StringLiteral(extracted.defaults)),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
finalAttributes.push(
|
||||
t.jSXAttribute(t.jSXIdentifier('defaults'), t.StringLiteral(extracted.defaults)),
|
||||
);
|
||||
}
|
||||
|
||||
if (!attributeExistsAlready('components', finalAttributes))
|
||||
finalAttributes.push(
|
||||
t.jSXAttribute(t.jSXIdentifier('components'), t.jSXExpressionContainer(extracted.components)),
|
||||
);
|
||||
if (!attributeExistsAlready('values', finalAttributes))
|
||||
finalAttributes.push(
|
||||
t.jSXAttribute(t.jSXIdentifier('values'), t.jSXExpressionContainer(extracted.values)),
|
||||
);
|
||||
|
||||
// create selfclosing Trans component
|
||||
const openElement = t.jSXOpeningElement(nodeName, finalAttributes, true);
|
||||
if (!wasElementWithChildren) return openElement;
|
||||
|
||||
return t.jSXElement(openElement, null, [], true);
|
||||
}
|
||||
|
||||
function cloneExistingAttributes(attributes) {
|
||||
return attributes.reduce((mem, attr) => {
|
||||
mem.push(attr.node);
|
||||
return mem;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function findAttribute(name, attributes) {
|
||||
return attributes.find((child) => {
|
||||
const ele = child.node ? child.node : child;
|
||||
return ele.name.name === name;
|
||||
});
|
||||
}
|
||||
|
||||
function attributeExistsAlready(name, attributes) {
|
||||
return !!findAttribute(name, attributes);
|
||||
}
|
||||
|
||||
function processTrans(children, babel, componentStartIndex = 0) {
|
||||
const res = {};
|
||||
|
||||
res.defaults = mergeChildren(children, babel, componentStartIndex);
|
||||
res.components = getComponents(children, babel);
|
||||
res.values = getValues(children, babel);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const leadingNewLineAndWhitespace = /^\n\s+/g;
|
||||
const trailingNewLineAndWhitespace = /\n\s+$/g;
|
||||
function trimIndent(text) {
|
||||
const newText = text
|
||||
.replace(leadingNewLineAndWhitespace, '')
|
||||
.replace(trailingNewLineAndWhitespace, '');
|
||||
return newText;
|
||||
}
|
||||
|
||||
/**
|
||||
* add comma-delimited expressions like `{ val, number }`
|
||||
*/
|
||||
function mergeCommaExpressions(ele) {
|
||||
if (ele.expression && ele.expression.expressions) {
|
||||
return `{${ele.expression.expressions
|
||||
.reduce((m, i) => {
|
||||
m.push(i.name || i.value);
|
||||
return m;
|
||||
}, [])
|
||||
.join(', ')}}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* this is for supporting complex icu type interpolations
|
||||
* date`${variable}` and number`{${varName}, ::percent}`
|
||||
* also, plural`{${count}, one { ... } other { ... }}
|
||||
*/
|
||||
function mergeTaggedTemplateExpressions(ele, componentFoundIndex, t, babel) {
|
||||
if (t.isTaggedTemplateExpression(ele.expression)) {
|
||||
const [, text, index] = getTextAndInterpolatedVariables(
|
||||
ele.expression.tag.name,
|
||||
ele.expression,
|
||||
componentFoundIndex,
|
||||
babel,
|
||||
);
|
||||
return [text, index];
|
||||
}
|
||||
return ['', componentFoundIndex];
|
||||
}
|
||||
|
||||
function mergeChildren(children, babel, componentStartIndex = 0) {
|
||||
const t = babel.types;
|
||||
let componentFoundIndex = componentStartIndex;
|
||||
|
||||
return children.reduce((mem, child) => {
|
||||
const ele = child.node ? child.node : child;
|
||||
let result = mem;
|
||||
|
||||
// add text, but trim indentation whitespace
|
||||
if (t.isJSXText(ele) && ele.value) result += trimIndent(ele.value);
|
||||
// add ?!? forgot
|
||||
if (ele.expression && ele.expression.value) result += ele.expression.value;
|
||||
// add `{ val }`
|
||||
if (ele.expression && ele.expression.name) result += `{${ele.expression.name}}`;
|
||||
// add `{ val, number }`
|
||||
result += mergeCommaExpressions(ele);
|
||||
const [nextText, newIndex] = mergeTaggedTemplateExpressions(ele, componentFoundIndex, t, babel);
|
||||
result += nextText;
|
||||
componentFoundIndex = newIndex;
|
||||
// add <strong>...</strong> with replace to <0>inner string</0>
|
||||
if (t.isJSXElement(ele)) {
|
||||
result += `<${componentFoundIndex}>${mergeChildren(
|
||||
ele.children,
|
||||
babel,
|
||||
)}</${componentFoundIndex}>`;
|
||||
componentFoundIndex += 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}, '');
|
||||
}
|
||||
|
||||
const extractTaggedTemplateValues = (ele, babel, toObjectProperty) => {
|
||||
// date`${variable}` and so on
|
||||
if (ele.expression && ele.expression.type === 'TaggedTemplateExpression') {
|
||||
const [variables] = getTextAndInterpolatedVariables(
|
||||
ele.expression.tag.name,
|
||||
ele.expression,
|
||||
0,
|
||||
babel,
|
||||
);
|
||||
return variables.map((vari) => toObjectProperty(vari));
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Extract the names of interpolated value as object properties to pass to Trans
|
||||
*/
|
||||
function getValues(children, babel) {
|
||||
const t = babel.types;
|
||||
const toObjectProperty = (name, value) =>
|
||||
t.objectProperty(t.identifier(name), t.identifier(name), false, !value);
|
||||
|
||||
return children.reduce((mem, child) => {
|
||||
const ele = child.node ? child.node : child;
|
||||
let result = mem;
|
||||
|
||||
// add `{ var }` to values
|
||||
if (ele.expression && ele.expression.name) mem.push(toObjectProperty(ele.expression.name));
|
||||
// add `{ var, number }` to values
|
||||
if (ele.expression && ele.expression.expressions)
|
||||
result.push(
|
||||
toObjectProperty(ele.expression.expressions[0].name || ele.expression.expressions[0].value),
|
||||
);
|
||||
// add `{ var: 'bar' }` to values
|
||||
if (ele.expression && ele.expression.properties)
|
||||
result = result.concat(ele.expression.properties);
|
||||
// date`${variable}` and so on
|
||||
result = result.concat(extractTaggedTemplateValues(ele, babel, toObjectProperty));
|
||||
// recursive add inner elements stuff to values
|
||||
if (t.isJSXElement(ele)) {
|
||||
result = result.concat(getValues(ele.children, babel));
|
||||
}
|
||||
|
||||
return result;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common logic for adding a child element of Trans to the list of components to hydrate the translation
|
||||
* @param {JSXElement} jsxElement
|
||||
* @param {JSXElement[]} mem
|
||||
*/
|
||||
const processJSXElement = (jsxElement, mem, t) => {
|
||||
const clone = t.clone(jsxElement);
|
||||
clone.children = clone.children.reduce((clonedMem, clonedChild) => {
|
||||
const clonedEle = clonedChild.node ? clonedChild.node : clonedChild;
|
||||
|
||||
// clean out invalid definitions by replacing `{ catchDate, date, short }` with `{ catchDate }`
|
||||
if (clonedEle.expression && clonedEle.expression.expressions)
|
||||
clonedEle.expression.expressions = [clonedEle.expression.expressions[0]];
|
||||
|
||||
clonedMem.push(clonedChild);
|
||||
return clonedMem;
|
||||
}, []);
|
||||
|
||||
mem.push(jsxElement);
|
||||
};
|
||||
|
||||
/**
|
||||
* Extract the React components to pass to Trans as components
|
||||
*/
|
||||
function getComponents(children, babel) {
|
||||
const t = babel.types;
|
||||
|
||||
return children.reduce((mem, child) => {
|
||||
const ele = child.node ? child.node : child;
|
||||
|
||||
if (t.isJSXExpressionContainer(ele)) {
|
||||
// check for date`` and so on
|
||||
if (t.isTaggedTemplateExpression(ele.expression)) {
|
||||
ele.expression.quasi.expressions.forEach((expr) => {
|
||||
// check for sub-expressions. This can happen with plural`` or select`` or selectOrdinal``
|
||||
// these can have nested components
|
||||
if (t.isTaggedTemplateExpression(expr) && expr.quasi.expressions.length) {
|
||||
mem.push(...getComponents(expr.quasi.expressions, babel));
|
||||
}
|
||||
if (!t.isJSXElement(expr)) {
|
||||
// ignore anything that is not a component
|
||||
return;
|
||||
}
|
||||
processJSXElement(expr, mem, t);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (t.isJSXElement(ele)) {
|
||||
processJSXElement(ele, mem, t);
|
||||
}
|
||||
|
||||
return mem;
|
||||
}, []);
|
||||
}
|
||||
|
||||
const icuInterpolators = ['date', 'time', 'number', 'plural', 'select', 'selectOrdinal'];
|
||||
const importsToAdd = ['Trans'];
|
||||
|
||||
/**
|
||||
* helper split out of addNeededImports to make codeclimate happy
|
||||
*
|
||||
* This does the work of amending an existing import from "react-i18next", or
|
||||
* creating a new one if it doesn't exist
|
||||
*/
|
||||
function addImports(state, existingImport, allImportsToAdd, t) {
|
||||
// append imports to existing or add a new react-i18next import for the Trans and icu tagged template literals
|
||||
if (existingImport) {
|
||||
allImportsToAdd.forEach((name) => {
|
||||
if (
|
||||
existingImport.specifiers.findIndex(
|
||||
(specifier) => specifier.imported && specifier.imported.name === name,
|
||||
) === -1
|
||||
) {
|
||||
existingImport.specifiers.push(t.importSpecifier(t.identifier(name), t.identifier(name)));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
state.file.path.node.body.unshift(
|
||||
t.importDeclaration(
|
||||
allImportsToAdd.map((name) => t.importSpecifier(t.identifier(name), t.identifier(name))),
|
||||
t.stringLiteral('react-i18next'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add `import { Trans, number, date, <etc.> } from "react-i18next"` as needed
|
||||
*/
|
||||
function addNeededImports(state, babel, references) {
|
||||
const t = babel.types;
|
||||
|
||||
// check if there is an existing react-i18next import
|
||||
const existingImport = state.file.path.node.body.find(
|
||||
(importNode) =>
|
||||
t.isImportDeclaration(importNode) && importNode.source.value === 'react-i18next',
|
||||
);
|
||||
// check for any of the tagged template literals that are used in the source, and add them
|
||||
const usedRefs = Object.keys(references).filter((importName) => {
|
||||
if (!icuInterpolators.includes(importName)) {
|
||||
return false;
|
||||
}
|
||||
return references[importName].length;
|
||||
});
|
||||
|
||||
// combine Trans + any tagged template literals
|
||||
const allImportsToAdd = importsToAdd.concat(usedRefs);
|
||||
|
||||
addImports(state, existingImport, allImportsToAdd, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* iterate over a node detected inside a tagged template literal
|
||||
*
|
||||
* This is a helper function for `extractVariableNamesFromQuasiNodes` defined below
|
||||
*
|
||||
* this is called using reduce as a way of tricking what would be `.map()`
|
||||
* into passing in the parameters needed to both modify `componentFoundIndex`,
|
||||
* `stringOutput`, and `interpolatedVariableNames`
|
||||
* and to pass in the dependencies babel, and type. Type is the template type.
|
||||
* For "date``" the type will be `date`. for "number``" the type is `number`, etc.
|
||||
*/
|
||||
const extractNestedTemplatesAndComponents = (
|
||||
{ componentFoundIndex: lastIndex, babel, stringOutput, type, interpolatedVariableNames },
|
||||
node,
|
||||
) => {
|
||||
let componentFoundIndex = lastIndex;
|
||||
if (node.type === 'JSXElement') {
|
||||
// perform the interpolation of components just as we do in a normal Trans setting
|
||||
const subText = `<${componentFoundIndex}>${mergeChildren(
|
||||
node.children,
|
||||
babel,
|
||||
)}</${componentFoundIndex}>`;
|
||||
componentFoundIndex += 1;
|
||||
stringOutput.push(subText);
|
||||
} else if (node.type === 'TaggedTemplateExpression') {
|
||||
// a nested date``/number``/plural`` etc., extract whatever is inside of it
|
||||
const [variableNames, childText, newIndex] = getTextAndInterpolatedVariables(
|
||||
node.tag.name,
|
||||
node,
|
||||
componentFoundIndex,
|
||||
babel,
|
||||
);
|
||||
interpolatedVariableNames.push(...variableNames);
|
||||
componentFoundIndex = newIndex;
|
||||
stringOutput.push(childText);
|
||||
} else if (node.type === 'Identifier') {
|
||||
// turn date`${thing}` into `thing, date`
|
||||
stringOutput.push(`${node.name}, ${type}`);
|
||||
} else if (node.type === 'TemplateElement') {
|
||||
// convert all whitespace into a single space for the text in the tagged template literal
|
||||
stringOutput.push(node.value.cooked.replace(/\s+/g, ' '));
|
||||
} else {
|
||||
// unknown node type, ignore
|
||||
}
|
||||
return { componentFoundIndex, babel, stringOutput, type, interpolatedVariableNames };
|
||||
};
|
||||
|
||||
/**
|
||||
* filter the list of nodes within a tagged template literal to the 4 types we can process,
|
||||
* and ignore anything else.
|
||||
*
|
||||
* this is a helper function for `extractVariableNamesFromQuasiNodes`
|
||||
*/
|
||||
const filterNodes = (node) => {
|
||||
if (node.type === 'Identifier') {
|
||||
// if the node has a name, keep it
|
||||
return node.name;
|
||||
}
|
||||
if (node.type === 'JSXElement' || node.type === 'TaggedTemplateExpression') {
|
||||
// always keep interpolated elements or other tagged template literals like a nested date`` inside a plural``
|
||||
return true;
|
||||
}
|
||||
if (node.type === 'TemplateElement') {
|
||||
// return the "cooked" (escaped) text for the text in the template literal (`, ::percent` in number`${varname}, ::percent`)
|
||||
return node.value.cooked;
|
||||
}
|
||||
// unknown node type, ignore
|
||||
return false;
|
||||
};
|
||||
|
||||
const errorOnInvalidQuasiNodes = (primaryNode) => {
|
||||
const noInterpolationError = !primaryNode.quasi.expressions.length;
|
||||
const wrongOrderError = primaryNode.quasi.quasis[0].value.raw.length;
|
||||
const message = `${primaryNode.tag.name} argument must be interpolated ${
|
||||
noInterpolationError ? 'in' : 'at the beginning of'
|
||||
} "${primaryNode.tag.name}\`\`" in "${primaryNode.loc.filename}" on line ${
|
||||
primaryNode.loc.start.line
|
||||
}`;
|
||||
if (noInterpolationError || wrongOrderError) {
|
||||
throw new Error(message);
|
||||
}
|
||||
};
|
||||
|
||||
const extractNodeVariableNames = (varNode, babel) => {
|
||||
const interpolatedVariableNames = [];
|
||||
if (varNode.type === 'JSXElement') {
|
||||
// extract inner interpolated variables and add to the list
|
||||
interpolatedVariableNames.push(
|
||||
...getValues(varNode.children, babel).map((value) => value.value.name),
|
||||
);
|
||||
} else if (varNode.type === 'Identifier') {
|
||||
// the name of the interpolated variable
|
||||
interpolatedVariableNames.push(varNode.name);
|
||||
}
|
||||
return interpolatedVariableNames;
|
||||
};
|
||||
|
||||
const extractVariableNamesFromQuasiNodes = (primaryNode, babel) => {
|
||||
errorOnInvalidQuasiNodes(primaryNode);
|
||||
// this will contain all the nodes to convert to the ICU messageformat text
|
||||
// at first they are unsorted, but will be ordered correctly at the end of the function
|
||||
const text = [];
|
||||
// the variable names. These are converted to object references as required for the Trans values
|
||||
// in getValues() (toObjectProperty helper function)
|
||||
const interpolatedVariableNames = [];
|
||||
primaryNode.quasi.expressions.forEach((varNode) => {
|
||||
if (
|
||||
!babel.types.isIdentifier(varNode) &&
|
||||
!babel.types.isTaggedTemplateExpression(varNode) &&
|
||||
!babel.types.isJSXElement(varNode)
|
||||
) {
|
||||
throw new Error(
|
||||
`Must pass a variable, not an expression to "${primaryNode.tag.name}\`\`" in "${primaryNode.loc.filename}" on line ${primaryNode.loc.start.line}`,
|
||||
);
|
||||
}
|
||||
text.push(varNode);
|
||||
interpolatedVariableNames.push(...extractNodeVariableNames(varNode, babel));
|
||||
});
|
||||
primaryNode.quasi.quasis.forEach((quasiNode) => {
|
||||
// these are the text surrounding the variable interpolation
|
||||
// so in date`${varname}, short` it would be `''` and `, short`.
|
||||
// (the empty string before `${varname}` and the stuff after it)
|
||||
text.push(quasiNode);
|
||||
});
|
||||
return { text, interpolatedVariableNames };
|
||||
};
|
||||
|
||||
const throwOnInvalidType = (type, primaryNode) => {
|
||||
if (!icuInterpolators.includes(type)) {
|
||||
throw new Error(
|
||||
`Unsupported tagged template literal "${type}", must be one of date, time, number, plural, select, selectOrdinal in "${primaryNode.loc.filename}" on line ${primaryNode.loc.start.line}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the new text to use, and any interpolated variables
|
||||
*
|
||||
* This is used to process tagged template literals like date`${variable}` and number`${num}, ::percent`
|
||||
*
|
||||
* for the data example, it will return text of `{variable, date}` with a variable of `variable`
|
||||
* for the number example, it will return text of `{num, number, ::percent}` with a variable of `num`
|
||||
* @param {string} type the name of the tagged template (`date`, `number`, `plural`, etc. - any valid complex ICU type)
|
||||
* @param {TaggedTemplateExpression} primaryNode the template expression node
|
||||
* @param {int} index starting index number of components to be used for interpolations like <0>
|
||||
* @param {*} babel
|
||||
*/
|
||||
function getTextAndInterpolatedVariables(type, primaryNode, index, babel) {
|
||||
throwOnInvalidType(type, primaryNode);
|
||||
const componentFoundIndex = index;
|
||||
const { text, interpolatedVariableNames } = extractVariableNamesFromQuasiNodes(
|
||||
primaryNode,
|
||||
babel,
|
||||
);
|
||||
const { stringOutput, componentFoundIndex: newIndex } = text
|
||||
.filter(filterNodes)
|
||||
// sort by the order they appear in the source code
|
||||
.sort((a, b) => {
|
||||
if (a.start > b.start) return 1;
|
||||
return -1;
|
||||
})
|
||||
.reduce(extractNestedTemplatesAndComponents, {
|
||||
babel,
|
||||
componentFoundIndex,
|
||||
stringOutput: [],
|
||||
type,
|
||||
interpolatedVariableNames,
|
||||
});
|
||||
return [
|
||||
interpolatedVariableNames,
|
||||
`{${stringOutput.join('')}}`,
|
||||
// return the new component interpolation index
|
||||
newIndex,
|
||||
];
|
||||
}
|
||||
1
node_modules/react-i18next/index.d.mts
generated
vendored
Normal file
1
node_modules/react-i18next/index.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './index.js';
|
||||
184
node_modules/react-i18next/index.d.ts
generated
vendored
Normal file
184
node_modules/react-i18next/index.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
import type { $Subtract, $Tuple } from './helpers.js';
|
||||
import type {
|
||||
ReactOptions,
|
||||
i18n,
|
||||
Resource,
|
||||
FlatNamespace,
|
||||
Namespace,
|
||||
TypeOptions,
|
||||
TFunction,
|
||||
KeyPrefix,
|
||||
} from 'i18next';
|
||||
import * as React from 'react';
|
||||
import { Trans, TransProps, ErrorCode, ErrorArgs } from './TransWithoutContext.js';
|
||||
export { initReactI18next } from './initReactI18next.js';
|
||||
|
||||
export const TransWithoutContext: typeof Trans;
|
||||
export { Trans, TransProps, ErrorArgs, ErrorCode };
|
||||
|
||||
export function setDefaults(options: ReactOptions): void;
|
||||
export function getDefaults(): ReactOptions;
|
||||
export function setI18n(instance: i18n): void;
|
||||
export function getI18n(): i18n;
|
||||
export function composeInitialProps(ForComponent: any): (ctx: unknown) => Promise<any>;
|
||||
export function getInitialProps(): {
|
||||
initialI18nStore: {
|
||||
[ns: string]: {};
|
||||
};
|
||||
initialLanguage: string;
|
||||
};
|
||||
|
||||
export interface ReportNamespaces {
|
||||
addUsedNamespaces(namespaces: Namespace): void;
|
||||
getUsedNamespaces(): string[];
|
||||
}
|
||||
|
||||
declare module 'i18next' {
|
||||
// interface i18n {
|
||||
// reportNamespaces?: ReportNamespaces;
|
||||
// }
|
||||
interface CustomInstanceExtensions {
|
||||
reportNamespaces?: ReportNamespaces;
|
||||
}
|
||||
}
|
||||
|
||||
type ObjectOrNever = TypeOptions['allowObjectInHTMLChildren'] extends true
|
||||
? Record<string, unknown>
|
||||
: never;
|
||||
|
||||
type ReactI18NextChildren = React.ReactNode | ObjectOrNever;
|
||||
|
||||
declare module 'react' {
|
||||
namespace JSX {
|
||||
interface IntrinsicAttributes {
|
||||
i18nIsDynamicList?: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
interface HTMLAttributes<T> {
|
||||
// This union is inspired by the typings for React.ReactNode. We do this to fix "This JSX tag's 'children' prop
|
||||
// expects a single child of type 'ReactI18NextChildren', but multiple children were provided":
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5a1e9f91ed0143adede394adb3f540e650455f71/types/react/index.d.ts#L268
|
||||
children?: ReactI18NextChildren | Iterable<ReactI18NextChildren>;
|
||||
}
|
||||
}
|
||||
|
||||
type _DefaultNamespace = TypeOptions['defaultNS'];
|
||||
|
||||
export function useSSR(initialI18nStore: Resource, initialLanguage: string): void;
|
||||
|
||||
export interface UseTranslationOptions<KPrefix> {
|
||||
i18n?: i18n;
|
||||
useSuspense?: boolean;
|
||||
keyPrefix?: KPrefix;
|
||||
bindI18n?: string | false;
|
||||
nsMode?: 'fallback' | 'default';
|
||||
lng?: string;
|
||||
// other of these options might also work: https://github.com/i18next/i18next/blob/master/index.d.ts#L127
|
||||
}
|
||||
|
||||
export type UseTranslationResponse<Ns extends Namespace, KPrefix> = [
|
||||
t: TFunction<Ns, KPrefix>,
|
||||
i18n: i18n,
|
||||
ready: boolean,
|
||||
] & {
|
||||
t: TFunction<Ns, KPrefix>;
|
||||
i18n: i18n;
|
||||
ready: boolean;
|
||||
};
|
||||
|
||||
// Workaround to make code completion to work when suggesting namespaces.
|
||||
// This is a typescript limitation when using generics with default values,
|
||||
// it'll be addressed in this issue: https://github.com/microsoft/TypeScript/issues/52516
|
||||
export type FallbackNs<Ns> = Ns extends undefined
|
||||
? _DefaultNamespace
|
||||
: Ns extends Namespace
|
||||
? Ns
|
||||
: _DefaultNamespace;
|
||||
|
||||
export function useTranslation<
|
||||
const Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined,
|
||||
const KPrefix extends KeyPrefix<FallbackNs<Ns>> = undefined,
|
||||
>(
|
||||
ns?: Ns,
|
||||
options?: UseTranslationOptions<KPrefix>,
|
||||
): UseTranslationResponse<FallbackNs<Ns>, KPrefix>;
|
||||
|
||||
// Need to see usage to improve this
|
||||
export function withSSR(): <Props>(WrappedComponent: React.ComponentType<Props>) => {
|
||||
({
|
||||
initialI18nStore,
|
||||
initialLanguage,
|
||||
...rest
|
||||
}: {
|
||||
initialI18nStore: Resource;
|
||||
initialLanguage: string;
|
||||
} & Props): React.FunctionComponentElement<Props>;
|
||||
getInitialProps: (ctx: unknown) => Promise<any>;
|
||||
};
|
||||
|
||||
export interface WithTranslation<
|
||||
Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined,
|
||||
KPrefix extends KeyPrefix<FallbackNs<Ns>> = undefined,
|
||||
> {
|
||||
t: TFunction<FallbackNs<Ns>, KPrefix>;
|
||||
i18n: i18n;
|
||||
tReady: boolean;
|
||||
}
|
||||
|
||||
export interface WithTranslationProps {
|
||||
i18n?: i18n;
|
||||
useSuspense?: boolean;
|
||||
}
|
||||
|
||||
export function withTranslation<
|
||||
Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined,
|
||||
KPrefix extends KeyPrefix<FallbackNs<Ns>> = undefined,
|
||||
>(
|
||||
ns?: Ns,
|
||||
options?: {
|
||||
withRef?: boolean;
|
||||
keyPrefix?: KPrefix;
|
||||
},
|
||||
): <
|
||||
C extends React.ComponentType<React.ComponentProps<any> & WithTranslationProps>,
|
||||
ResolvedProps = React.JSX.LibraryManagedAttributes<
|
||||
C,
|
||||
$Subtract<React.ComponentProps<C>, WithTranslationProps>
|
||||
>,
|
||||
>(
|
||||
component: C,
|
||||
) => React.ComponentType<Omit<ResolvedProps, keyof WithTranslation<Ns>> & WithTranslationProps>;
|
||||
|
||||
export interface I18nextProviderProps {
|
||||
children?: React.ReactNode;
|
||||
i18n: i18n;
|
||||
defaultNS?: string | string[];
|
||||
}
|
||||
|
||||
export const I18nextProvider: React.FunctionComponent<I18nextProviderProps>;
|
||||
export const I18nContext: React.Context<{ i18n: i18n }>;
|
||||
|
||||
export interface TranslationProps<
|
||||
Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined,
|
||||
KPrefix extends KeyPrefix<FallbackNs<Ns>> = undefined,
|
||||
> {
|
||||
children: (
|
||||
t: TFunction<FallbackNs<Ns>, KPrefix>,
|
||||
options: {
|
||||
i18n: i18n;
|
||||
lng: string;
|
||||
},
|
||||
ready: boolean,
|
||||
) => React.ReactNode;
|
||||
ns?: Ns;
|
||||
i18n?: i18n;
|
||||
useSuspense?: boolean;
|
||||
keyPrefix?: KPrefix;
|
||||
nsMode?: 'fallback' | 'default';
|
||||
}
|
||||
|
||||
export function Translation<
|
||||
Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined,
|
||||
KPrefix extends KeyPrefix<FallbackNs<Ns>> = undefined,
|
||||
>(props: TranslationProps<Ns, KPrefix>): any;
|
||||
1
node_modules/react-i18next/initReactI18next.d.mts
generated
vendored
Normal file
1
node_modules/react-i18next/initReactI18next.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './initReactI18next.js';
|
||||
3
node_modules/react-i18next/initReactI18next.d.ts
generated
vendored
Normal file
3
node_modules/react-i18next/initReactI18next.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { ThirdPartyModule } from 'i18next';
|
||||
|
||||
export const initReactI18next: ThirdPartyModule;
|
||||
4
node_modules/react-i18next/lint-staged.config.mjs
generated
vendored
Normal file
4
node_modules/react-i18next/lint-staged.config.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export default {
|
||||
'!*.?(c|m){js,ts}?(x)': ['prettier --write --ignore-unknown'],
|
||||
'*.?(c|m){js,ts}?(x)': ['prettier --write --ignore-unknown', 'eslint --cache --fix --env-info'],
|
||||
};
|
||||
167
node_modules/react-i18next/package.json
generated
vendored
Normal file
167
node_modules/react-i18next/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
{
|
||||
"name": "react-i18next",
|
||||
"version": "15.6.1",
|
||||
"description": "Internationalization for react done right. Using the i18next i18n ecosystem.",
|
||||
"main": "dist/commonjs/index.js",
|
||||
"types": "./index.d.mts",
|
||||
"jsnext:main": "dist/es/index.js",
|
||||
"module": "dist/es/index.js",
|
||||
"keywords": [
|
||||
"i18next",
|
||||
"internationalization",
|
||||
"i18n",
|
||||
"translation",
|
||||
"localization",
|
||||
"l10n",
|
||||
"globalization",
|
||||
"react",
|
||||
"reactjs"
|
||||
],
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"types": {
|
||||
"require": "./index.d.ts",
|
||||
"import": "./index.d.mts"
|
||||
},
|
||||
"module": "./dist/es/index.js",
|
||||
"import": "./dist/es/index.js",
|
||||
"require": "./dist/commonjs/index.js",
|
||||
"default": "./dist/es/index.js"
|
||||
},
|
||||
"./TransWithoutContext": {
|
||||
"types": {
|
||||
"require": "./TransWithoutContext.d.ts",
|
||||
"import": "./TransWithoutContext.d.mts"
|
||||
},
|
||||
"module": "./dist/es/TransWithoutContext.js",
|
||||
"import": "./dist/es/TransWithoutContext.js",
|
||||
"require": "./dist/commonjs/TransWithoutContext.js",
|
||||
"default": "./dist/es/TransWithoutContext.js"
|
||||
},
|
||||
"./initReactI18next": {
|
||||
"types": {
|
||||
"require": "./initReactI18next.d.ts",
|
||||
"import": "./initReactI18next.d.mts"
|
||||
},
|
||||
"module": "./dist/es/initReactI18next.js",
|
||||
"import": "./dist/es/initReactI18next.js",
|
||||
"require": "./dist/commonjs/initReactI18next.js",
|
||||
"default": "./dist/es/initReactI18next.js"
|
||||
},
|
||||
"./icu.macro": {
|
||||
"types": {
|
||||
"require": "./icu.macro..d.ts",
|
||||
"import": "./icu.macro..d.mts"
|
||||
},
|
||||
"default": "./icu.macro.js"
|
||||
}
|
||||
},
|
||||
"homepage": "https://github.com/i18next/react-i18next",
|
||||
"bugs": "https://github.com/i18next/react-i18next/issues",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/i18next/react-i18next.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.27.6",
|
||||
"html-parse-stringify": "^3.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"i18next": ">= 23.2.3",
|
||||
"react": ">= 16.8.0",
|
||||
"typescript": "^5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
},
|
||||
"react-native": {
|
||||
"optional": true
|
||||
},
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.28.0",
|
||||
"@babel/core": "^7.28.0",
|
||||
"@babel/eslint-parser": "^7.28.0",
|
||||
"@babel/plugin-proposal-async-generator-functions": "^7.20.7",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.27.1",
|
||||
"@babel/plugin-transform-runtime": "^7.28.0",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.28.0",
|
||||
"@babel/preset-react": "^7.27.1",
|
||||
"@babel/register": "^7.27.1",
|
||||
"@rollup/plugin-babel": "^6.0.4",
|
||||
"@rollup/plugin-commonjs": "^26.0.3",
|
||||
"@rollup/plugin-node-resolve": "^15.3.1",
|
||||
"@rollup/plugin-replace": "^5.0.7",
|
||||
"@rollup/plugin-terser": "0.4.4",
|
||||
"@testing-library/dom": "^10.4.0",
|
||||
"@testing-library/jest-dom": "^6.4.8",
|
||||
"@testing-library/react": "^16.1.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/react": "^19.1.0",
|
||||
"@vitest/coverage-v8": "^2.0.5",
|
||||
"all-contributors-cli": "^6.26.1",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"babel-plugin-tester": "^11.0.4",
|
||||
"coveralls": "^3.1.1",
|
||||
"cpy-cli": "^5.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-airbnb": "19.0.4",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-jest-dom": "^5.5.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-testing-library": "^6.5.0",
|
||||
"happy-dom": "^14.12.3",
|
||||
"husky": "^9.1.7",
|
||||
"i18next": "^25.3.0",
|
||||
"lint-staged": "^15.5.2",
|
||||
"mkdirp": "^3.0.1",
|
||||
"prettier": "^3.6.2",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-test-renderer": "^19.1.0",
|
||||
"rimraf": "^6.0.1",
|
||||
"rollup": "^4.44.1",
|
||||
"typescript": "~5.5.4",
|
||||
"vitest": "^2.0.5",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf dist && mkdirp dist",
|
||||
"lint": "eslint --cache .",
|
||||
"lint:fix": "eslint --cache --fix .",
|
||||
"format": "prettier . --check",
|
||||
"format:fix": "prettier . --write --list-different",
|
||||
"copy": "cpy ./dist/umd/react-i18next.min.js ./dist/umd/react-i18next.js . --flat && echo '{\"type\":\"module\"}' > dist/es/package.json",
|
||||
"build:es": "cross-env BABEL_ENV=ESNext babel src --out-dir dist/es",
|
||||
"build:cjs": "babel src --out-dir dist/commonjs",
|
||||
"build:umd": "rollup -c rollup.config.mjs --format umd && rollup -c rollup.config.mjs --format umd --uglify",
|
||||
"build:amd": "rollup -c rollup.config.mjs --format amd && rollup -c rollup.config.mjs --format amd --uglify",
|
||||
"build:iife": "rollup -c rollup.config.mjs --format iife && rollup -c rollup.config.mjs --format iife --uglify",
|
||||
"build": "npm run clean && npm run build:cjs && npm run build:es && npm run build:umd && npm run build:amd && npm run copy",
|
||||
"fix_dist_package": "node -e 'console.log(`{\"type\":\"module\",\"version\":\"${process.env.npm_package_version}\"}`)' > dist/es/package.json",
|
||||
"preversion": "npm run build && git push",
|
||||
"postversion": "npm run fix_dist_package && git push && git push --tags",
|
||||
"test": "vitest",
|
||||
"test:coverage": "npm run test -- --coverage --run",
|
||||
"test:typescript": "vitest --workspace vitest.workspace.typescript.mts",
|
||||
"contributors:add": "all-contributors add",
|
||||
"contributors:generate": "all-contributors generate",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"author": "Jan Mühlemann <jan.muehlemann@gmail.com> (https://github.com/jamuhl)",
|
||||
"license": "MIT",
|
||||
"lock": false,
|
||||
"sideEffects": false,
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
||||
871
node_modules/react-i18next/react-i18next.js
generated
vendored
Normal file
871
node_modules/react-i18next/react-i18next.js
generated
vendored
Normal file
|
|
@ -0,0 +1,871 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
|
||||
typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactI18next = {}, global.React));
|
||||
})(this, (function (exports, react) { 'use strict';
|
||||
|
||||
function getDefaultExportFromCjs (x) {
|
||||
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
||||
}
|
||||
|
||||
var voidElements = {
|
||||
"area": true,
|
||||
"base": true,
|
||||
"br": true,
|
||||
"col": true,
|
||||
"embed": true,
|
||||
"hr": true,
|
||||
"img": true,
|
||||
"input": true,
|
||||
"link": true,
|
||||
"meta": true,
|
||||
"param": true,
|
||||
"source": true,
|
||||
"track": true,
|
||||
"wbr": true
|
||||
};
|
||||
|
||||
var e = /*@__PURE__*/getDefaultExportFromCjs(voidElements);
|
||||
|
||||
var t = /\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?(".*?"|'.*?')/g;
|
||||
function n(n) {
|
||||
var r = {
|
||||
type: "tag",
|
||||
name: "",
|
||||
voidElement: false,
|
||||
attrs: {},
|
||||
children: []
|
||||
},
|
||||
i = n.match(/<\/?([^\s]+?)[/\s>]/);
|
||||
if (i && (r.name = i[1], (e[i[1]] || "/" === n.charAt(n.length - 2)) && (r.voidElement = true), r.name.startsWith("!--"))) {
|
||||
var s = n.indexOf("--\x3e");
|
||||
return {
|
||||
type: "comment",
|
||||
comment: -1 !== s ? n.slice(4, s) : ""
|
||||
};
|
||||
}
|
||||
for (var a = new RegExp(t), c = null; null !== (c = a.exec(n));) if (c[0].trim()) if (c[1]) {
|
||||
var o = c[1].trim(),
|
||||
l = [o, ""];
|
||||
o.indexOf("=") > -1 && (l = o.split("=")), r.attrs[l[0]] = l[1], a.lastIndex--;
|
||||
} else c[2] && (r.attrs[c[2]] = c[3].trim().substring(1, c[3].length - 1));
|
||||
return r;
|
||||
}
|
||||
var r = /<[a-zA-Z0-9\-\!\/](?:"[^"]*"|'[^']*'|[^'">])*>/g,
|
||||
i = /^\s*$/,
|
||||
s = Object.create(null);
|
||||
function a(e, t) {
|
||||
switch (t.type) {
|
||||
case "text":
|
||||
return e + t.content;
|
||||
case "tag":
|
||||
return e += "<" + t.name + (t.attrs ? function (e) {
|
||||
var t = [];
|
||||
for (var n in e) t.push(n + '="' + e[n] + '"');
|
||||
return t.length ? " " + t.join(" ") : "";
|
||||
}(t.attrs) : "") + (t.voidElement ? "/>" : ">"), t.voidElement ? e : e + t.children.reduce(a, "") + "</" + t.name + ">";
|
||||
case "comment":
|
||||
return e + "\x3c!--" + t.comment + "--\x3e";
|
||||
}
|
||||
}
|
||||
var c = {
|
||||
parse: function (e, t) {
|
||||
t || (t = {}), t.components || (t.components = s);
|
||||
var a,
|
||||
c = [],
|
||||
o = [],
|
||||
l = -1,
|
||||
m = false;
|
||||
if (0 !== e.indexOf("<")) {
|
||||
var u = e.indexOf("<");
|
||||
c.push({
|
||||
type: "text",
|
||||
content: -1 === u ? e : e.substring(0, u)
|
||||
});
|
||||
}
|
||||
return e.replace(r, function (r, s) {
|
||||
if (m) {
|
||||
if (r !== "</" + a.name + ">") return;
|
||||
m = false;
|
||||
}
|
||||
var u,
|
||||
f = "/" !== r.charAt(1),
|
||||
h = r.startsWith("\x3c!--"),
|
||||
p = s + r.length,
|
||||
d = e.charAt(p);
|
||||
if (h) {
|
||||
var v = n(r);
|
||||
return l < 0 ? (c.push(v), c) : ((u = o[l]).children.push(v), c);
|
||||
}
|
||||
if (f && (l++, "tag" === (a = n(r)).type && t.components[a.name] && (a.type = "component", m = true), a.voidElement || m || !d || "<" === d || a.children.push({
|
||||
type: "text",
|
||||
content: e.slice(p, e.indexOf("<", p))
|
||||
}), 0 === l && c.push(a), (u = o[l - 1]) && u.children.push(a), o[l] = a), (!f || a.voidElement) && (l > -1 && (a.voidElement || a.name === r.slice(2, -1)) && (l--, a = -1 === l ? c : o[l]), !m && "<" !== d && d)) {
|
||||
u = -1 === l ? c : o[l].children;
|
||||
var x = e.indexOf("<", p),
|
||||
g = e.slice(p, -1 === x ? void 0 : x);
|
||||
i.test(g) && (g = " "), (x > -1 && l + u.length >= 0 || " " !== g) && u.push({
|
||||
type: "text",
|
||||
content: g
|
||||
});
|
||||
}
|
||||
}), c;
|
||||
},
|
||||
stringify: function (e) {
|
||||
return e.reduce(function (e, t) {
|
||||
return e + a("", t);
|
||||
}, "");
|
||||
}
|
||||
};
|
||||
|
||||
const warn = (i18n, code, msg, rest) => {
|
||||
const args = [msg, {
|
||||
code,
|
||||
...(rest || {})
|
||||
}];
|
||||
if (i18n?.services?.logger?.forward) {
|
||||
return i18n.services.logger.forward(args, 'warn', 'react-i18next::', true);
|
||||
}
|
||||
if (isString(args[0])) args[0] = `react-i18next:: ${args[0]}`;
|
||||
if (i18n?.services?.logger?.warn) {
|
||||
i18n.services.logger.warn(...args);
|
||||
} else if (console?.warn) {
|
||||
console.warn(...args);
|
||||
}
|
||||
};
|
||||
const alreadyWarned = {};
|
||||
const warnOnce = (i18n, code, msg, rest) => {
|
||||
if (isString(msg) && alreadyWarned[msg]) return;
|
||||
if (isString(msg)) alreadyWarned[msg] = new Date();
|
||||
warn(i18n, code, msg, rest);
|
||||
};
|
||||
const loadedClb = (i18n, cb) => () => {
|
||||
if (i18n.isInitialized) {
|
||||
cb();
|
||||
} else {
|
||||
const initialized = () => {
|
||||
setTimeout(() => {
|
||||
i18n.off('initialized', initialized);
|
||||
}, 0);
|
||||
cb();
|
||||
};
|
||||
i18n.on('initialized', initialized);
|
||||
}
|
||||
};
|
||||
const loadNamespaces = (i18n, ns, cb) => {
|
||||
i18n.loadNamespaces(ns, loadedClb(i18n, cb));
|
||||
};
|
||||
const loadLanguages = (i18n, lng, ns, cb) => {
|
||||
if (isString(ns)) ns = [ns];
|
||||
if (i18n.options.preload && i18n.options.preload.indexOf(lng) > -1) return loadNamespaces(i18n, ns, cb);
|
||||
ns.forEach(n => {
|
||||
if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
|
||||
});
|
||||
i18n.loadLanguages(lng, loadedClb(i18n, cb));
|
||||
};
|
||||
const hasLoadedNamespace = (ns, i18n, options = {}) => {
|
||||
if (!i18n.languages || !i18n.languages.length) {
|
||||
warnOnce(i18n, 'NO_LANGUAGES', 'i18n.languages were undefined or empty', {
|
||||
languages: i18n.languages
|
||||
});
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
});
|
||||
};
|
||||
const getDisplayName = Component => Component.displayName || Component.name || (isString(Component) && Component.length > 0 ? Component : 'Unknown');
|
||||
const isString = obj => typeof obj === 'string';
|
||||
const isObject = obj => typeof obj === 'object' && obj !== null;
|
||||
|
||||
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];
|
||||
const unescape = text => text.replace(matchHtmlEntity, unescapeHtmlEntity);
|
||||
|
||||
let defaultOptions = {
|
||||
bindI18n: 'languageChanged',
|
||||
bindI18nStore: '',
|
||||
transEmptyNodeValue: '',
|
||||
transSupportBasicHtmlNodes: true,
|
||||
transWrapTextNodes: '',
|
||||
transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p'],
|
||||
useSuspense: true,
|
||||
unescape
|
||||
};
|
||||
const setDefaults = (options = {}) => {
|
||||
defaultOptions = {
|
||||
...defaultOptions,
|
||||
...options
|
||||
};
|
||||
};
|
||||
const getDefaults = () => defaultOptions;
|
||||
|
||||
let i18nInstance;
|
||||
const setI18n = instance => {
|
||||
i18nInstance = instance;
|
||||
};
|
||||
const getI18n = () => i18nInstance;
|
||||
|
||||
const hasChildren = (node, checkLength) => {
|
||||
if (!node) return false;
|
||||
const base = node.props?.children ?? node.children;
|
||||
if (checkLength) return base.length > 0;
|
||||
return !!base;
|
||||
};
|
||||
const getChildren = node => {
|
||||
if (!node) return [];
|
||||
const children = node.props?.children ?? node.children;
|
||||
return node.props?.i18nIsDynamicList ? getAsArray(children) : children;
|
||||
};
|
||||
const hasValidReactChildren = children => Array.isArray(children) && children.every(react.isValidElement);
|
||||
const getAsArray = data => Array.isArray(data) ? data : [data];
|
||||
const mergeProps = (source, target) => {
|
||||
const newTarget = {
|
||||
...target
|
||||
};
|
||||
newTarget.props = Object.assign(source.props, target.props);
|
||||
return newTarget;
|
||||
};
|
||||
const nodesToString = (children, i18nOptions, i18n, i18nKey) => {
|
||||
if (!children) return '';
|
||||
let stringNode = '';
|
||||
const childrenArray = getAsArray(children);
|
||||
const keepArray = i18nOptions?.transSupportBasicHtmlNodes ? i18nOptions.transKeepBasicHtmlNodesFor ?? [] : [];
|
||||
childrenArray.forEach((child, childIndex) => {
|
||||
if (isString(child)) {
|
||||
stringNode += `${child}`;
|
||||
return;
|
||||
}
|
||||
if (react.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) {
|
||||
stringNode += `<${type}/>`;
|
||||
return;
|
||||
}
|
||||
if (!childChildren && (!shouldKeepChild || childPropsCount) || props.i18nIsDynamicList) {
|
||||
stringNode += `<${childIndex}></${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (shouldKeepChild && childPropsCount === 1 && isString(childChildren)) {
|
||||
stringNode += `<${type}>${childChildren}</${type}>`;
|
||||
return;
|
||||
}
|
||||
const content = nodesToString(childChildren, i18nOptions, i18n, i18nKey);
|
||||
stringNode += `<${childIndex}>${content}</${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (child === null) {
|
||||
warn(i18n, 'TRANS_NULL_VALUE', `Passed in a null value as child`, {
|
||||
i18nKey
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isObject(child)) {
|
||||
const {
|
||||
format,
|
||||
...clone
|
||||
} = child;
|
||||
const keys = Object.keys(clone);
|
||||
if (keys.length === 1) {
|
||||
const value = format ? `${keys[0]}, ${format}` : keys[0];
|
||||
stringNode += `{{${value}}}`;
|
||||
return;
|
||||
}
|
||||
warn(i18n, 'TRANS_INVALID_OBJ', `Invalid child - Object should only have keys {{ value, format }} (format is optional).`, {
|
||||
i18nKey,
|
||||
child
|
||||
});
|
||||
return;
|
||||
}
|
||||
warn(i18n, 'TRANS_INVALID_VAR', `Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.`, {
|
||||
i18nKey,
|
||||
child
|
||||
});
|
||||
});
|
||||
return stringNode;
|
||||
};
|
||||
const renderNodes = (children, knownComponentsMap, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
|
||||
if (targetString === '') return [];
|
||||
const keepArray = i18nOptions.transKeepBasicHtmlNodesFor || [];
|
||||
const emptyChildrenButNeedsHandling = targetString && new RegExp(keepArray.map(keep => `<${keep}`).join('|')).test(targetString);
|
||||
if (!children && !knownComponentsMap && !emptyChildrenButNeedsHandling && !shouldUnescape) return [targetString];
|
||||
const data = knownComponentsMap ?? {};
|
||||
const getData = childs => {
|
||||
const childrenArray = getAsArray(childs);
|
||||
childrenArray.forEach(child => {
|
||||
if (isString(child)) return;
|
||||
if (hasChildren(child)) getData(getChildren(child));else if (isObject(child) && !react.isValidElement(child)) Object.assign(data, child);
|
||||
});
|
||||
};
|
||||
getData(children);
|
||||
const ast = c.parse(`<0>${targetString}</0>`);
|
||||
const opts = {
|
||||
...data,
|
||||
...combinedTOpts
|
||||
};
|
||||
const renderInner = (child, node, rootReactNode) => {
|
||||
const childs = getChildren(child);
|
||||
const mappedChildren = mapAST(childs, node.children, rootReactNode);
|
||||
return hasValidReactChildren(childs) && mappedChildren.length === 0 || child.props?.i18nIsDynamicList ? childs : mappedChildren;
|
||||
};
|
||||
const pushTranslatedJSX = (child, inner, mem, i, isVoid) => {
|
||||
if (child.dummy) {
|
||||
child.children = inner;
|
||||
mem.push(react.cloneElement(child, {
|
||||
key: i
|
||||
}, isVoid ? undefined : inner));
|
||||
} else {
|
||||
mem.push(...react.Children.map([child], c => {
|
||||
const props = {
|
||||
...c.props
|
||||
};
|
||||
delete props.i18nIsDynamicList;
|
||||
return react.createElement(c.type, {
|
||||
...props,
|
||||
key: i,
|
||||
ref: c.props.ref ?? c.ref
|
||||
}, isVoid ? null : inner);
|
||||
}));
|
||||
}
|
||||
};
|
||||
const mapAST = (reactNode, astNode, rootReactNode) => {
|
||||
const reactNodes = getAsArray(reactNode);
|
||||
const astNodes = getAsArray(astNode);
|
||||
return astNodes.reduce((mem, node, i) => {
|
||||
const translationContent = node.children?.[0]?.content && i18n.services.interpolator.interpolate(node.children[0].content, opts, i18n.language);
|
||||
if (node.type === 'tag') {
|
||||
let tmp = reactNodes[parseInt(node.name, 10)];
|
||||
if (!tmp && knownComponentsMap) tmp = knownComponentsMap[node.name];
|
||||
if (rootReactNode.length === 1 && !tmp) tmp = rootReactNode[0][node.name];
|
||||
if (!tmp) tmp = {};
|
||||
const child = Object.keys(node.attrs).length !== 0 ? mergeProps({
|
||||
props: node.attrs
|
||||
}, tmp) : tmp;
|
||||
const isElement = react.isValidElement(child);
|
||||
const isValidTranslationWithChildren = isElement && hasChildren(node, true) && !node.voidElement;
|
||||
const isEmptyTransWithHTML = emptyChildrenButNeedsHandling && isObject(child) && child.dummy && !isElement;
|
||||
const isKnownComponent = isObject(knownComponentsMap) && Object.hasOwnProperty.call(knownComponentsMap, node.name);
|
||||
if (isString(child)) {
|
||||
const value = i18n.services.interpolator.interpolate(child, opts, i18n.language);
|
||||
mem.push(value);
|
||||
} else if (hasChildren(child) || isValidTranslationWithChildren) {
|
||||
const inner = renderInner(child, node, rootReactNode);
|
||||
pushTranslatedJSX(child, inner, mem, i);
|
||||
} else if (isEmptyTransWithHTML) {
|
||||
const inner = mapAST(reactNodes, 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(react.createElement(node.name, {
|
||||
key: `${node.name}-${i}`
|
||||
}));
|
||||
} else {
|
||||
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
||||
mem.push(react.createElement(node.name, {
|
||||
key: `${node.name}-${i}`
|
||||
}, inner));
|
||||
}
|
||||
} else if (node.voidElement) {
|
||||
mem.push(`<${node.name} />`);
|
||||
} else {
|
||||
const inner = mapAST(reactNodes, node.children, rootReactNode);
|
||||
mem.push(`<${node.name}>${inner}</${node.name}>`);
|
||||
}
|
||||
} else if (isObject(child) && !isElement) {
|
||||
const content = node.children[0] ? translationContent : null;
|
||||
if (content) mem.push(content);
|
||||
} else {
|
||||
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(react.createElement(wrapTextNodes, {
|
||||
key: `${node.name}-${i}`
|
||||
}, content));
|
||||
} else {
|
||||
mem.push(content);
|
||||
}
|
||||
}
|
||||
return mem;
|
||||
}, []);
|
||||
};
|
||||
const result = mapAST([{
|
||||
dummy: true,
|
||||
children: children || []
|
||||
}], ast, getAsArray(children || []));
|
||||
return getChildren(result[0]);
|
||||
};
|
||||
const fixComponentProps = (component, index, translation) => {
|
||||
const componentKey = component.key || index;
|
||||
const comp = react.cloneElement(component, {
|
||||
key: componentKey
|
||||
});
|
||||
if (!comp.props || !comp.props.children || translation.indexOf(`${index}/>`) < 0 && translation.indexOf(`${index} />`) < 0) {
|
||||
return comp;
|
||||
}
|
||||
function Componentized() {
|
||||
return react.createElement(react.Fragment, null, comp);
|
||||
}
|
||||
return react.createElement(Componentized, {
|
||||
key: componentKey
|
||||
});
|
||||
};
|
||||
const generateArrayComponents = (components, translation) => components.map((c, index) => fixComponentProps(c, index, translation));
|
||||
const generateObjectComponents = (components, translation) => {
|
||||
const componentMap = {};
|
||||
Object.keys(components).forEach(c => {
|
||||
Object.assign(componentMap, {
|
||||
[c]: fixComponentProps(components[c], c, translation)
|
||||
});
|
||||
});
|
||||
return componentMap;
|
||||
};
|
||||
const generateComponents = (components, translation, i18n, i18nKey) => {
|
||||
if (!components) return null;
|
||||
if (Array.isArray(components)) {
|
||||
return generateArrayComponents(components, translation);
|
||||
}
|
||||
if (isObject(components)) {
|
||||
return generateObjectComponents(components, translation);
|
||||
}
|
||||
warnOnce(i18n, 'TRANS_INVALID_COMPONENTS', `<Trans /> "components" prop expects an object or array`, {
|
||||
i18nKey
|
||||
});
|
||||
return null;
|
||||
};
|
||||
const isComponentsMap = object => {
|
||||
if (!isObject(object)) return false;
|
||||
if (Array.isArray(object)) return false;
|
||||
return Object.keys(object).reduce((acc, key) => acc && Number.isNaN(Number.parseFloat(key)), true);
|
||||
};
|
||||
function Trans$1({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions = {},
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns,
|
||||
i18n: i18nFromProps,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
}) {
|
||||
const i18n = i18nFromProps || getI18n();
|
||||
if (!i18n) {
|
||||
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', `Trans: You need to pass in an i18next instance using i18nextReactModule`, {
|
||||
i18nKey
|
||||
});
|
||||
return children;
|
||||
}
|
||||
const t = tFromProps || i18n.t.bind(i18n) || (k => k);
|
||||
const reactI18nextOptions = {
|
||||
...getDefaults(),
|
||||
...i18n.options?.react
|
||||
};
|
||||
let namespaces = ns || t.ns || i18n.options?.defaultNS;
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
const nodeAsString = nodesToString(children, reactI18nextOptions, i18n, i18nKey);
|
||||
const defaultValue = defaults || nodeAsString || reactI18nextOptions.transEmptyNodeValue || i18nKey;
|
||||
const {
|
||||
hashTransKey
|
||||
} = reactI18nextOptions;
|
||||
const key = i18nKey || (hashTransKey ? hashTransKey(nodeAsString || defaultValue) : nodeAsString || defaultValue);
|
||||
if (i18n.options?.interpolation?.defaultVariables) {
|
||||
values = values && Object.keys(values).length > 0 ? {
|
||||
...values,
|
||||
...i18n.options.interpolation.defaultVariables
|
||||
} : {
|
||||
...i18n.options.interpolation.defaultVariables
|
||||
};
|
||||
}
|
||||
const interpolationOverride = values || count !== undefined && !i18n.options?.interpolation?.alwaysFormat || !children ? tOptions.interpolation : {
|
||||
interpolation: {
|
||||
...tOptions.interpolation,
|
||||
prefix: '#$?',
|
||||
suffix: '?$#'
|
||||
}
|
||||
};
|
||||
const combinedTOpts = {
|
||||
...tOptions,
|
||||
context: context || tOptions.context,
|
||||
count,
|
||||
...values,
|
||||
...interpolationOverride,
|
||||
defaultValue,
|
||||
ns: namespaces
|
||||
};
|
||||
const translation = key ? t(key, combinedTOpts) : defaultValue;
|
||||
const generatedComponents = generateComponents(components, translation, i18n, i18nKey);
|
||||
let indexedChildren = generatedComponents || children;
|
||||
let componentsMap = null;
|
||||
if (isComponentsMap(generatedComponents)) {
|
||||
componentsMap = generatedComponents;
|
||||
indexedChildren = children;
|
||||
}
|
||||
const content = renderNodes(indexedChildren, componentsMap, translation, i18n, reactI18nextOptions, combinedTOpts, shouldUnescape);
|
||||
const useAsParent = parent ?? reactI18nextOptions.defaultTransParent;
|
||||
return useAsParent ? react.createElement(useAsParent, additionalProps, content) : content;
|
||||
}
|
||||
|
||||
const initReactI18next = {
|
||||
type: '3rdParty',
|
||||
init(instance) {
|
||||
setDefaults(instance.options.react);
|
||||
setI18n(instance);
|
||||
}
|
||||
};
|
||||
|
||||
const I18nContext = react.createContext();
|
||||
class ReportNamespaces {
|
||||
constructor() {
|
||||
this.usedNamespaces = {};
|
||||
}
|
||||
addUsedNamespaces(namespaces) {
|
||||
namespaces.forEach(ns => {
|
||||
if (!this.usedNamespaces[ns]) this.usedNamespaces[ns] = true;
|
||||
});
|
||||
}
|
||||
getUsedNamespaces() {
|
||||
return Object.keys(this.usedNamespaces);
|
||||
}
|
||||
}
|
||||
const composeInitialProps = ForComponent => async ctx => {
|
||||
const componentsInitialProps = (await ForComponent.getInitialProps?.(ctx)) ?? {};
|
||||
const i18nInitialProps = getInitialProps();
|
||||
return {
|
||||
...componentsInitialProps,
|
||||
...i18nInitialProps
|
||||
};
|
||||
};
|
||||
const getInitialProps = () => {
|
||||
const i18n = getI18n();
|
||||
const namespaces = 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;
|
||||
};
|
||||
|
||||
function Trans({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions = {},
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns,
|
||||
i18n: i18nFromProps,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
}) {
|
||||
const {
|
||||
i18n: i18nFromContext,
|
||||
defaultNS: defaultNSFromContext
|
||||
} = react.useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
const t = tFromProps || i18n?.t.bind(i18n);
|
||||
return Trans$1({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions,
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
ns: ns || t?.ns || defaultNSFromContext || i18n?.options?.defaultNS,
|
||||
i18n,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps
|
||||
});
|
||||
}
|
||||
|
||||
const usePrevious = (value, ignore) => {
|
||||
const ref = react.useRef();
|
||||
react.useEffect(() => {
|
||||
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) => react.useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [i18n, language, namespace, keyPrefix]);
|
||||
const useTranslation = (ns, props = {}) => {
|
||||
const {
|
||||
i18n: i18nFromProps
|
||||
} = props;
|
||||
const {
|
||||
i18n: i18nFromContext,
|
||||
defaultNS: defaultNSFromContext
|
||||
} = react.useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
|
||||
if (!i18n) {
|
||||
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', 'useTranslation: 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?.wait) warnOnce(i18n, 'DEPRECATED_OPTION', 'useTranslation: 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;
|
||||
let namespaces = ns || defaultNSFromContext || i18n.options?.defaultNS;
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
i18n.reportNamespaces.addUsedNamespaces?.(namespaces);
|
||||
const ready = (i18n.isInitialized || i18n.initializedStoreOnce) && namespaces.every(n => hasLoadedNamespace(n, i18n, i18nOptions));
|
||||
const memoGetT = useMemoizedT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
||||
const getT = () => memoGetT;
|
||||
const getNewT = () => alwaysNewT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
||||
const [t, setT] = react.useState(getT);
|
||||
let joinedNS = namespaces.join();
|
||||
if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
|
||||
const previousJoinedNS = usePrevious(joinedNS);
|
||||
const isMounted = react.useRef(true);
|
||||
react.useEffect(() => {
|
||||
const {
|
||||
bindI18n,
|
||||
bindI18nStore
|
||||
} = i18nOptions;
|
||||
isMounted.current = true;
|
||||
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);
|
||||
};
|
||||
if (bindI18n) i18n?.on(bindI18n, boundReset);
|
||||
if (bindI18nStore) i18n?.store.on(bindI18nStore, boundReset);
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
if (i18n && bindI18n) bindI18n?.split(' ').forEach(e => i18n.off(e, boundReset));
|
||||
if (bindI18nStore && i18n) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, boundReset));
|
||||
};
|
||||
}, [i18n, joinedNS]);
|
||||
react.useEffect(() => {
|
||||
if (isMounted.current && ready) {
|
||||
setT(getT);
|
||||
}
|
||||
}, [i18n, keyPrefix, ready]);
|
||||
const ret = [t, i18n, ready];
|
||||
ret.t = t;
|
||||
ret.i18n = i18n;
|
||||
ret.ready = ready;
|
||||
if (ready) return ret;
|
||||
if (!ready && !useSuspense) return ret;
|
||||
throw new Promise(resolve => {
|
||||
if (props.lng) {
|
||||
loadLanguages(i18n, props.lng, namespaces, () => resolve());
|
||||
} else {
|
||||
loadNamespaces(i18n, namespaces, () => resolve());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
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 react.createElement(WrappedComponent, passDownProps);
|
||||
}
|
||||
I18nextWithTranslation.displayName = `withI18nextTranslation(${getDisplayName(WrappedComponent)})`;
|
||||
I18nextWithTranslation.WrappedComponent = WrappedComponent;
|
||||
const forwardRef = (props, ref) => react.createElement(I18nextWithTranslation, Object.assign({}, props, {
|
||||
forwardedRef: ref
|
||||
}));
|
||||
return options.withRef ? react.forwardRef(forwardRef) : I18nextWithTranslation;
|
||||
};
|
||||
|
||||
const Translation = ({
|
||||
ns,
|
||||
children,
|
||||
...options
|
||||
}) => {
|
||||
const [t, i18n, ready] = useTranslation(ns, options);
|
||||
return children(t, {
|
||||
i18n,
|
||||
lng: i18n.language
|
||||
}, ready);
|
||||
};
|
||||
|
||||
function I18nextProvider({
|
||||
i18n,
|
||||
defaultNS,
|
||||
children
|
||||
}) {
|
||||
const value = react.useMemo(() => ({
|
||||
i18n,
|
||||
defaultNS
|
||||
}), [i18n, defaultNS]);
|
||||
return react.createElement(I18nContext.Provider, {
|
||||
value
|
||||
}, children);
|
||||
}
|
||||
|
||||
const useSSR = (initialI18nStore, initialLanguage, props = {}) => {
|
||||
const {
|
||||
i18n: i18nFromProps
|
||||
} = props;
|
||||
const {
|
||||
i18n: i18nFromContext
|
||||
} = react.useContext(I18nContext) || {};
|
||||
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
||||
if (i18n.options?.isClone) return;
|
||||
if (initialI18nStore && !i18n.initializedStoreOnce) {
|
||||
i18n.services.resourceStore.data = initialI18nStore;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
const withSSR = () => function Extend(WrappedComponent) {
|
||||
function I18nextWithSSR({
|
||||
initialI18nStore,
|
||||
initialLanguage,
|
||||
...rest
|
||||
}) {
|
||||
useSSR(initialI18nStore, initialLanguage);
|
||||
return react.createElement(WrappedComponent, {
|
||||
...rest
|
||||
});
|
||||
}
|
||||
I18nextWithSSR.getInitialProps = composeInitialProps(WrappedComponent);
|
||||
I18nextWithSSR.displayName = `withI18nextSSR(${getDisplayName(WrappedComponent)})`;
|
||||
I18nextWithSSR.WrappedComponent = WrappedComponent;
|
||||
return I18nextWithSSR;
|
||||
};
|
||||
|
||||
const date = () => '';
|
||||
const time = () => '';
|
||||
const number = () => '';
|
||||
const select = () => '';
|
||||
const plural = () => '';
|
||||
const selectOrdinal = () => '';
|
||||
|
||||
exports.I18nContext = I18nContext;
|
||||
exports.I18nextProvider = I18nextProvider;
|
||||
exports.Trans = Trans;
|
||||
exports.TransWithoutContext = Trans$1;
|
||||
exports.Translation = Translation;
|
||||
exports.composeInitialProps = composeInitialProps;
|
||||
exports.date = date;
|
||||
exports.getDefaults = getDefaults;
|
||||
exports.getI18n = getI18n;
|
||||
exports.getInitialProps = getInitialProps;
|
||||
exports.initReactI18next = initReactI18next;
|
||||
exports.number = number;
|
||||
exports.plural = plural;
|
||||
exports.select = select;
|
||||
exports.selectOrdinal = selectOrdinal;
|
||||
exports.setDefaults = setDefaults;
|
||||
exports.setI18n = setI18n;
|
||||
exports.time = time;
|
||||
exports.useSSR = useSSR;
|
||||
exports.useTranslation = useTranslation;
|
||||
exports.withSSR = withSSR;
|
||||
exports.withTranslation = withTranslation;
|
||||
|
||||
}));
|
||||
1
node_modules/react-i18next/react-i18next.min.js
generated
vendored
Normal file
1
node_modules/react-i18next/react-i18next.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
7
node_modules/react-i18next/src/I18nextProvider.js
generated
vendored
Normal file
7
node_modules/react-i18next/src/I18nextProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
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);
|
||||
}
|
||||
45
node_modules/react-i18next/src/Trans.js
generated
vendored
Normal file
45
node_modules/react-i18next/src/Trans.js
generated
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
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?.t.bind(i18n);
|
||||
|
||||
return TransWithoutContext({
|
||||
children,
|
||||
count,
|
||||
parent,
|
||||
i18nKey,
|
||||
context,
|
||||
tOptions,
|
||||
values,
|
||||
defaults,
|
||||
components,
|
||||
// prepare having a namespace
|
||||
ns: ns || t?.ns || defaultNSFromContext || i18n?.options?.defaultNS,
|
||||
i18n,
|
||||
t: tFromProps,
|
||||
shouldUnescape,
|
||||
...additionalProps,
|
||||
});
|
||||
}
|
||||
479
node_modules/react-i18next/src/TransWithoutContext.js
generated
vendored
Normal file
479
node_modules/react-i18next/src/TransWithoutContext.js
generated
vendored
Normal file
|
|
@ -0,0 +1,479 @@
|
|||
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?.children ?? node.children;
|
||||
if (checkLength) return base.length > 0;
|
||||
return !!base;
|
||||
};
|
||||
|
||||
const getChildren = (node) => {
|
||||
if (!node) return [];
|
||||
const children = node.props?.children ?? node.children;
|
||||
return 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, i18n, i18nKey) => {
|
||||
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 ?? [])
|
||||
: [];
|
||||
|
||||
// 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}`;
|
||||
return;
|
||||
}
|
||||
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}/>`;
|
||||
return;
|
||||
}
|
||||
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}>`;
|
||||
return;
|
||||
}
|
||||
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}>`;
|
||||
return;
|
||||
}
|
||||
// regular case mapping the inner children
|
||||
const content = nodesToString(childChildren, i18nOptions, i18n, i18nKey);
|
||||
stringNode += `<${childIndex}>${content}</${childIndex}>`;
|
||||
return;
|
||||
}
|
||||
if (child === null) {
|
||||
warn(i18n, 'TRANS_NULL_VALUE', `Passed in a null value as child`, { i18nKey });
|
||||
return;
|
||||
}
|
||||
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}}}`;
|
||||
return;
|
||||
}
|
||||
warn(
|
||||
i18n,
|
||||
'TRANS_INVALID_OBJ',
|
||||
`Invalid child - Object should only have keys {{ value, format }} (format is optional).`,
|
||||
{ i18nKey, child },
|
||||
);
|
||||
return;
|
||||
}
|
||||
warn(
|
||||
i18n,
|
||||
'TRANS_INVALID_VAR',
|
||||
`Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.`,
|
||||
{ i18nKey, child },
|
||||
);
|
||||
});
|
||||
|
||||
return stringNode;
|
||||
};
|
||||
|
||||
const renderNodes = (
|
||||
children,
|
||||
knownComponentsMap,
|
||||
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 && !knownComponentsMap && !emptyChildrenButNeedsHandling && !shouldUnescape)
|
||||
return [targetString];
|
||||
|
||||
// v2 -> interpolates upfront no need for "some <0>{{var}}</0>"" -> will be just "some {{var}}" in translation file
|
||||
const data = knownComponentsMap ?? {};
|
||||
|
||||
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?.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.props.ref ?? c.ref, // ref is a prop in react >= v19
|
||||
},
|
||||
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?.[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)];
|
||||
if (!tmp && knownComponentsMap) tmp = knownComponentsMap[node.name];
|
||||
|
||||
// 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(knownComponentsMap) && Object.hasOwnProperty.call(knownComponentsMap, 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]);
|
||||
};
|
||||
|
||||
const fixComponentProps = (component, index, translation) => {
|
||||
const componentKey = component.key || index;
|
||||
const comp = cloneElement(component, { key: componentKey });
|
||||
if (
|
||||
!comp.props ||
|
||||
!comp.props.children ||
|
||||
(translation.indexOf(`${index}/>`) < 0 && translation.indexOf(`${index} />`) < 0)
|
||||
) {
|
||||
return comp;
|
||||
}
|
||||
|
||||
function Componentized() {
|
||||
// <>{comp}</>
|
||||
return createElement(Fragment, null, comp);
|
||||
}
|
||||
// <Componentized />
|
||||
return createElement(Componentized, { key: componentKey });
|
||||
};
|
||||
|
||||
const generateArrayComponents = (components, translation) =>
|
||||
components.map((c, index) => fixComponentProps(c, index, translation));
|
||||
|
||||
const generateObjectComponents = (components, translation) => {
|
||||
const componentMap = {};
|
||||
|
||||
Object.keys(components).forEach((c) => {
|
||||
Object.assign(componentMap, {
|
||||
[c]: fixComponentProps(components[c], c, translation),
|
||||
});
|
||||
});
|
||||
|
||||
return componentMap;
|
||||
};
|
||||
|
||||
const generateComponents = (components, translation, i18n, i18nKey) => {
|
||||
if (!components) return null;
|
||||
|
||||
// components could be either an array or an object
|
||||
|
||||
if (Array.isArray(components)) {
|
||||
return generateArrayComponents(components, translation);
|
||||
}
|
||||
|
||||
if (isObject(components)) {
|
||||
return generateObjectComponents(components, translation);
|
||||
}
|
||||
|
||||
// if components is not an array or an object, warn the user
|
||||
// and return null
|
||||
warnOnce(
|
||||
i18n,
|
||||
'TRANS_INVALID_COMPONENTS',
|
||||
`<Trans /> "components" prop expects an object or array`,
|
||||
{ i18nKey },
|
||||
);
|
||||
return null;
|
||||
};
|
||||
|
||||
// A component map is an object like: { Button: <button> }, but not an object like { 1: <button> }
|
||||
const isComponentsMap = (object) => {
|
||||
if (!isObject(object)) return false;
|
||||
if (Array.isArray(object)) return false;
|
||||
return Object.keys(object).reduce(
|
||||
(acc, key) => acc && Number.isNaN(Number.parseFloat(key)),
|
||||
true,
|
||||
);
|
||||
};
|
||||
|
||||
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(
|
||||
i18n,
|
||||
'NO_I18NEXT_INSTANCE',
|
||||
`Trans: You need to pass in an i18next instance using i18nextReactModule`,
|
||||
{ i18nKey },
|
||||
);
|
||||
return children;
|
||||
}
|
||||
|
||||
const t = tFromProps || i18n.t.bind(i18n) || ((k) => k);
|
||||
|
||||
const reactI18nextOptions = { ...getDefaults(), ...i18n.options?.react };
|
||||
|
||||
// prepare having a namespace
|
||||
let namespaces = ns || t.ns || i18n.options?.defaultNS;
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
|
||||
const nodeAsString = nodesToString(children, reactI18nextOptions, i18n, i18nKey);
|
||||
const defaultValue =
|
||||
defaults || nodeAsString || reactI18nextOptions.transEmptyNodeValue || i18nKey;
|
||||
const { hashTransKey } = reactI18nextOptions;
|
||||
const key =
|
||||
i18nKey ||
|
||||
(hashTransKey ? hashTransKey(nodeAsString || defaultValue) : nodeAsString || defaultValue);
|
||||
if (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 && !i18n.options?.interpolation?.alwaysFormat) || // https://github.com/i18next/react-i18next/issues/1719 + https://github.com/i18next/react-i18next/issues/1801
|
||||
!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;
|
||||
|
||||
const generatedComponents = generateComponents(components, translation, i18n, i18nKey);
|
||||
let indexedChildren = generatedComponents || children;
|
||||
let componentsMap = null;
|
||||
if (isComponentsMap(generatedComponents)) {
|
||||
componentsMap = generatedComponents;
|
||||
indexedChildren = children;
|
||||
}
|
||||
|
||||
const content = renderNodes(
|
||||
indexedChildren,
|
||||
componentsMap,
|
||||
translation,
|
||||
i18n,
|
||||
reactI18nextOptions,
|
||||
combinedTOpts,
|
||||
shouldUnescape,
|
||||
);
|
||||
|
||||
// allows user to pass `null` to `parent`
|
||||
// and override `defaultTransParent` if is present
|
||||
const useAsParent = parent ?? reactI18nextOptions.defaultTransParent;
|
||||
|
||||
return useAsParent ? createElement(useAsParent, additionalProps, content) : content;
|
||||
}
|
||||
14
node_modules/react-i18next/src/Translation.js
generated
vendored
Normal file
14
node_modules/react-i18next/src/Translation.js
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { useTranslation } from './useTranslation.js';
|
||||
|
||||
export const Translation = ({ ns, children, ...options }) => {
|
||||
const [t, i18n, ready] = useTranslation(ns, options);
|
||||
|
||||
return children(
|
||||
t,
|
||||
{
|
||||
i18n,
|
||||
lng: i18n.language,
|
||||
},
|
||||
ready,
|
||||
);
|
||||
};
|
||||
54
node_modules/react-i18next/src/context.js
generated
vendored
Normal file
54
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() {
|
||||
return Object.keys(this.usedNamespaces);
|
||||
}
|
||||
}
|
||||
|
||||
export const composeInitialProps = (ForComponent) => async (ctx) => {
|
||||
const componentsInitialProps = (await ForComponent.getInitialProps?.(ctx)) ?? {};
|
||||
|
||||
const i18nInitialProps = getInitialProps();
|
||||
|
||||
return {
|
||||
...componentsInitialProps,
|
||||
...i18nInitialProps,
|
||||
};
|
||||
};
|
||||
|
||||
export const getInitialProps = () => {
|
||||
const i18n = getI18n();
|
||||
const namespaces = 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
node_modules/react-i18next/src/defaults.js
generated
vendored
Normal file
20
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
node_modules/react-i18next/src/i18nInstance.js
generated
vendored
Normal file
7
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
node_modules/react-i18next/src/index.js
generated
vendored
Normal file
22
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
node_modules/react-i18next/src/initReactI18next.js
generated
vendored
Normal file
11
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
node_modules/react-i18next/src/unescape.js
generated
vendored
Normal file
31
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
node_modules/react-i18next/src/useSSR.js
generated
vendored
Normal file
33
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?.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;
|
||||
}
|
||||
};
|
||||
171
node_modules/react-i18next/src/useTranslation.js
generated
vendored
Normal file
171
node_modules/react-i18next/src/useTranslation.js
generated
vendored
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
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(
|
||||
i18n,
|
||||
'NO_I18NEXT_INSTANCE',
|
||||
'useTranslation: 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?.wait)
|
||||
warnOnce(
|
||||
i18n,
|
||||
'DEPRECATED_OPTION',
|
||||
'useTranslation: 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?.defaultNS;
|
||||
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
||||
|
||||
// report namespaces as used
|
||||
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?.on(bindI18n, boundReset);
|
||||
if (bindI18nStore) i18n?.store.on(bindI18nStore, boundReset);
|
||||
|
||||
// unbinding on unmount
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
if (i18n && bindI18n) 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());
|
||||
}
|
||||
});
|
||||
};
|
||||
93
node_modules/react-i18next/src/utils.js
generated
vendored
Normal file
93
node_modules/react-i18next/src/utils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/** @type {(i18n:any,code:import('../TransWithoutContext').ErrorCode,msg?:string, rest?:{[key:string]: any})=>void} */
|
||||
export const warn = (i18n, code, msg, rest) => {
|
||||
const args = [msg, { code, ...(rest || {}) }];
|
||||
if (i18n?.services?.logger?.forward) {
|
||||
return i18n.services.logger.forward(args, 'warn', 'react-i18next::', true);
|
||||
}
|
||||
if (isString(args[0])) args[0] = `react-i18next:: ${args[0]}`;
|
||||
if (i18n?.services?.logger?.warn) {
|
||||
i18n.services.logger.warn(...args);
|
||||
} else if (console?.warn) {
|
||||
console.warn(...args);
|
||||
}
|
||||
};
|
||||
const alreadyWarned = {};
|
||||
/** @type {typeof warn} */
|
||||
export const warnOnce = (i18n, code, msg, rest) => {
|
||||
if (isString(msg) && alreadyWarned[msg]) return;
|
||||
if (isString(msg)) alreadyWarned[msg] = new Date();
|
||||
warn(i18n, code, msg, rest);
|
||||
};
|
||||
|
||||
// not needed right now
|
||||
//
|
||||
// export const deprecated = (i18n, ...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(i18n, ...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];
|
||||
if (i18n.options.preload && i18n.options.preload.indexOf(lng) > -1)
|
||||
return loadNamespaces(i18n, ns, cb);
|
||||
ns.forEach((n) => {
|
||||
if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
|
||||
});
|
||||
i18n.loadLanguages(lng, loadedClb(i18n, cb));
|
||||
};
|
||||
|
||||
export const hasLoadedNamespace = (ns, i18n, options = {}) => {
|
||||
if (!i18n.languages || !i18n.languages.length) {
|
||||
warnOnce(i18n, 'NO_LANGUAGES', 'i18n.languages were undefined or empty', {
|
||||
languages: i18n.languages,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
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
node_modules/react-i18next/src/withSSR.js
generated
vendored
Normal file
21
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
node_modules/react-i18next/src/withTranslation.js
generated
vendored
Normal file
35
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;
|
||||
};
|
||||
52
node_modules/react-i18next/vitest.workspace.typescript.mts
generated
vendored
Normal file
52
node_modules/react-i18next/vitest.workspace.typescript.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import { readdirSync } from 'node:fs';
|
||||
import { defineWorkspace } from 'vitest/config';
|
||||
import type { UserProjectConfigExport } from 'vitest/config';
|
||||
|
||||
export default defineWorkspace(
|
||||
/**
|
||||
* If you need to test multiple typescript configurations (like misc) simply create a file named tsconfig.{customName}.json
|
||||
* and this script will automatically create a new workspace named with the dirName followed by `customName`
|
||||
*/
|
||||
readdirSync('./test/typescript', { withFileTypes: true })
|
||||
.filter((dir) => dir.isDirectory())
|
||||
.reduce<UserProjectConfigExport[]>((workspaces, dir) => {
|
||||
const dirPath = `test/typescript/${dir.name}` as const;
|
||||
|
||||
const tsConfigFiles = readdirSync(dirPath).filter(
|
||||
// Do not include temporary vitest tsconfig files
|
||||
(it) => it.startsWith('tsconfig.') && it.endsWith('.json') && !it.includes('vitest-temp'),
|
||||
);
|
||||
|
||||
tsConfigFiles.forEach((tsConfigFileName) => {
|
||||
const workspaceName =
|
||||
tsConfigFileName === 'tsconfig.json'
|
||||
? `typescript-${dir.name}`
|
||||
: `${dir.name}-${tsConfigFileName.split('.')[1]}`;
|
||||
|
||||
workspaces.push({
|
||||
test: {
|
||||
dir: `./${dirPath}`,
|
||||
name: workspaceName,
|
||||
alias: {
|
||||
/**
|
||||
* From `vitest` >= 2 imports are resolved even if we are running only typecheck tests.
|
||||
* This will result in:
|
||||
* ```text
|
||||
* Error: Failed to resolve entry for package "react-i18next". The package may have incorrect main/module/exports specified in its package.json.
|
||||
* ```
|
||||
* To avoid a useless build process before running these tests an empty alias to `react-i18next` is added.
|
||||
*/
|
||||
'react-i18next': '',
|
||||
},
|
||||
typecheck: {
|
||||
enabled: true,
|
||||
include: [`**/${dirPath}/*.test.{ts,tsx}`],
|
||||
tsconfig: `./${dirPath}/${tsConfigFileName}`,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return workspaces;
|
||||
}, []),
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue