diff --git a/jest.config.ts b/jest.config.ts index 13f9a91e7ee6..31ccf0f896fb 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -25,6 +25,7 @@ const config: InitialOptionsTsJest = { moduleNameMapper: { '@masknet/shared-base': '/packages/shared-base/src/index.ts', '@masknet/typed-message': '/packages/typed-message/base/index.ts', + '@masknet/public-api': '/packages/public-api/src/index.ts', 'jest-websocket-mock': '/packages/web3-shared/base/node_modules/jest-websocket-mock', 'reconnecting-websocket': '/packages/web3-shared/base/node_modules/reconnecting-websocket', 'date-fns/(.*)': '/packages/web3-shared/base/node_modules/date-fns/$1', diff --git a/package.json b/package.json index 33a45bcd9e14..a2f602de0700 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,6 @@ "@types/react": "^17.0.43", "@types/react-dom": "17.0.14", "@types/web": "^0.0.60", - "i18next": "^21.6.14", "lodash": "^4.17.21", "lodash-es": "^4.17.21", "lodash-unified": "1.0.2", diff --git a/packages/dashboard/.storybook/preview.js b/packages/dashboard/.storybook/preview.js index bcb4c09e8fba..33d586d14208 100644 --- a/packages/dashboard/.storybook/preview.js +++ b/packages/dashboard/.storybook/preview.js @@ -1,22 +1,15 @@ // @ts-check import React from 'react' import { ThemeProvider, StyledEngineProvider } from '@mui/material' -import { MaskLightTheme, applyMaskColorVars, CustomSnackbarProvider, MaskDarkTheme } from '@masknet/theme' +import { applyMaskColorVars, CustomSnackbarProvider, MaskDarkTheme } from '@masknet/theme' import { addSharedI18N, I18NextProviderHMR } from '@masknet/shared' -import { fallbackLng } from '../../shared-base/src/i18n/fallbackRule' // import { withMatrix } from 'storybook-addon-matrix' import { addDashboardI18N } from '../src/locales/languages' -import { initReactI18next } from 'react-i18next' -import i18n from 'i18next' -i18n.init({ - keySeparator: false, - interpolation: { escapeValue: false }, - fallbackLng, - nonExplicitSupportedLngs: true, -}) -i18n.use(initReactI18next) -addDashboardI18N(i18n) -addSharedI18N(i18n) +import { i18NextInstance } from '@masknet/shared-base' + +addDashboardI18N(i18NextInstance) +addSharedI18N(i18NextInstance) + export const parameters = { actions: { argTypesRegex: '^on[A-Z].*' }, } @@ -26,7 +19,7 @@ export const decorators = [ - + diff --git a/packages/dashboard/package.json b/packages/dashboard/package.json index 54e3dabb34cd..752af5457f27 100644 --- a/packages/dashboard/package.json +++ b/packages/dashboard/package.json @@ -36,7 +36,6 @@ "color": "^4.2.1", "date-fns": "2.28.0", "html-to-image": "^1.9.0", - "i18next-browser-languagedetector": "^6.1.4", "json-stable-stringify": "^1.0.1", "react-avatar-editor": "^12.0.0", "react-hook-form": "^7.28.1", diff --git a/packages/dashboard/src/initialization/Dashboard.tsx b/packages/dashboard/src/initialization/Dashboard.tsx index b8d4d7932ac1..9a1a09394423 100644 --- a/packages/dashboard/src/initialization/Dashboard.tsx +++ b/packages/dashboard/src/initialization/Dashboard.tsx @@ -18,7 +18,7 @@ import { } from '@masknet/plugin-infra' import { Web3Provider } from '@masknet/web3-shared-evm' -import i18n from 'i18next' +import { i18NextInstance } from '@masknet/shared-base' import '../utils/kv-storage' @@ -55,7 +55,7 @@ export default function DashboardRoot() { return ( - + diff --git a/packages/dashboard/src/initialization/PluginHost.ts b/packages/dashboard/src/initialization/PluginHost.ts index ab3a0eff3ce9..90046b03c47b 100644 --- a/packages/dashboard/src/initialization/PluginHost.ts +++ b/packages/dashboard/src/initialization/PluginHost.ts @@ -3,8 +3,7 @@ import './plugins' import { Emitter } from '@servie/events' import { startPluginDashboard, Plugin } from '@masknet/plugin-infra' import { Services, Messages } from '../API' -import { createI18NBundle } from '@masknet/shared-base' -import i18n from 'i18next' +import { createI18NBundle, i18NextInstance } from '@masknet/shared-base' import { InMemoryStorages, PersistentStorages } from '../utils/kv-storage' const PluginHost: Plugin.__Host.Host = { @@ -15,7 +14,7 @@ const PluginHost: Plugin.__Host.Host = { }, }, addI18NResource(plugin, resource) { - createI18NBundle(plugin, resource)(i18n) + createI18NBundle(plugin, resource)(i18NextInstance) }, createContext: (pluginID, signal) => { return { diff --git a/packages/dashboard/src/initialization/i18n.ts b/packages/dashboard/src/initialization/i18n.ts index 3fde4e947dbc..503c40f00cc3 100644 --- a/packages/dashboard/src/initialization/i18n.ts +++ b/packages/dashboard/src/initialization/i18n.ts @@ -1,21 +1,8 @@ -import i18n from 'i18next' -import Detector from 'i18next-browser-languagedetector' +import { i18NextInstance } from '@masknet/shared-base' import { addSharedI18N } from '@masknet/shared' -import { fallbackLng } from '@masknet/shared-base' import { addDashboardI18N } from '../locales/languages' import { initReactI18next } from 'react-i18next' -i18n.use(Detector).init({ - keySeparator: false, - interpolation: { - escapeValue: false, - }, - fallbackLng, - nonExplicitSupportedLngs: true, - detection: { - order: ['navigator'], - }, -}) -i18n.use(initReactI18next) -addSharedI18N(i18n) -addDashboardI18N(i18n) +initReactI18next.init(i18NextInstance) +addSharedI18N(i18NextInstance) +addDashboardI18N(i18NextInstance) diff --git a/packages/mask/package.json b/packages/mask/package.json index 46985cd97798..676b418c42f8 100644 --- a/packages/mask/package.json +++ b/packages/mask/package.json @@ -83,7 +83,6 @@ "graphql": "^15.5.1", "graphql-request": "^3.4.0", "https-browserify": "^1.0.0", - "i18next-browser-languagedetector": "^6.1.4", "idb": "^7.0.1", "iframe-resizer-react": "^1.1.0", "immer": "^9.0.12", diff --git a/packages/mask/shared-ui/locales/en-US.json b/packages/mask/shared-ui/locales/en-US.json index b8b822066700..729ca4e3cc86 100644 --- a/packages/mask/shared-ui/locales/en-US.json +++ b/packages/mask/shared-ui/locales/en-US.json @@ -152,15 +152,6 @@ "service_invalid_backup_file": "This does not seem like a backup of Mask.", "service_unknown_payload": "Unknown post version. You may need to update Mask.", "service_username_invalid": "Invalid Username", - "settings_enable_debug": "Debug Mode", - "settings_enable_debug_desc": "See additional information for debugging.", - "settings_appearance": "Appearance", - "settings_appearance_secondary": "Select the theme you would like to use.", - "settings_language": "Language", - "settings_language_secondary": "Select the language you would like to use.", - "settings_choose_eth_network": "Choose Ethereum Network", - "settings_launch_page": "Launch Page", - "settings_launch_page_secondary": "Select the default page to open when launch the app", "speed_up": "Speed up", "save": "Save", "skip": "Skip", @@ -318,10 +309,6 @@ "plugin_wallet_not_available_on": "Not available on {{network}} Network.", "plugin_wallet_connect_wallet": "Connect Wallet", "plugin_wallet_connect_wallet_tip": "Please connect to a wallet.", - "plugin_wallet_settings_fungible_asset_data_source_primary": "Portfolio Data Source", - "plugin_wallet_settings_fungible_asset_data_source_secondary": "Select the source of portfolio data.", - "plugin_wallet_settings_non_fungible_data_source_primary": "Collectible Data Source", - "plugin_wallet_settings_non_fungible_data_source_secondary": "Select the source of collectible data.", "plugin_wallet_name_placeholder": "Enter 1-12 characters", "plugin_wallet_fail_to_sign": "Failed to sign password.", "plugin_wallet_cancel_sign": "Signature canceled.", @@ -452,8 +439,6 @@ "plugin_trader_error_insufficient_balance": "Insufficient {{symbol}} balance", "plugin_trader_error_insufficient_lp": "Insufficient liquidity for this trade", "plugin_trade_error_input_amount_less_minimum_amount": "Input amount is below the minimum amount", - "plugin_trader_settings_data_source_primary": "Trending Data Source", - "plugin_trader_settings_data_source_secondary": "Select the source of cryptocurrencies' trending data.", "plugin_trader_slippage_tolerance": "Slippage Tolerance:", "plugin_trader_swap_from": "From", "plugin_trader_swap_to": "To(estimated)", diff --git a/packages/mask/shared-ui/locales/ja-JP.json b/packages/mask/shared-ui/locales/ja-JP.json index ddbe55582ad1..7c6078307c2b 100644 --- a/packages/mask/shared-ui/locales/ja-JP.json +++ b/packages/mask/shared-ui/locales/ja-JP.json @@ -68,15 +68,6 @@ "service_invalid_backup_file": "これは Mask のバックアップではないかもしれません。", "service_unknown_payload": "投稿のバージョンが不明です。Mask のアップデートが必要かもしれません。", "service_username_invalid": "無効なユーザー名", - "settings_enable_debug": "デバッグモード", - "settings_enable_debug_desc": "デバッグのための追加情報を参照してください。", - "settings_appearance": "テーマ", - "settings_appearance_secondary": "テーマを選んでください。", - "settings_language": "言語を設定", - "settings_language_secondary": "ご利用になりたい言語をお選びください。", - "settings_choose_eth_network": "Ethereum ネットワークを選択してください", - "settings_launch_page": "初期画面", - "settings_launch_page_secondary": "アプリを開いたときに最初に開かれる画面を選んでください。", "skip": "スキップ", "share": "共有", "share_to": "共有先", @@ -178,8 +169,6 @@ "plugin_trader_error_insufficient_balance": "{{symbol}} の残高が足りません", "plugin_trader_error_insufficient_lp": "流動性が足りません", "plugin_trade_error_input_amount_less_minimum_amount": "入力量は最小量を下回っています", - "plugin_trader_settings_data_source_primary": "取引データのソース", - "plugin_trader_settings_data_source_secondary": "暗号通貨トレンドデータのソースを選択する。", "plugin_trader_slippage_tolerance": "スリッページの許容範囲:", "plugin_poll_display_name": "プラグイン: 投票", "plugin_poll_question_hint": "質問を入力してください...", diff --git a/packages/mask/shared-ui/locales/ko-KR.json b/packages/mask/shared-ui/locales/ko-KR.json index 7f6d0b03a5c8..083fe75cf200 100644 --- a/packages/mask/shared-ui/locales/ko-KR.json +++ b/packages/mask/shared-ui/locales/ko-KR.json @@ -127,15 +127,6 @@ "service_invalid_backup_file": "Mask의 백업이 아닌 것 같습니다.", "service_unknown_payload": "알 수 없는 게시물 버전입니다. Mask를 업데이트하세요.", "service_username_invalid": "무효한 아이디입니다", - "settings_enable_debug": "디버그 모드", - "settings_enable_debug_desc": "디버깅에 대한 추가 정보 보기", - "settings_appearance": "화면", - "settings_appearance_secondary": "이용하고 싶은 테마를 선택하세요.", - "settings_language": "언어", - "settings_language_secondary": "이용하고 싶은 언어를 선택하세요.", - "settings_choose_eth_network": "이더리움 네트워크를 선택하기", - "settings_launch_page": "시작 페이지", - "settings_launch_page_secondary": "앱을 열을 때 디폴트 페이지를 선택하세요.", "speed_up": "가속하기", "save": "저장", "skip": "넘어가기", @@ -344,8 +335,6 @@ "plugin_trader_error_insufficient_balance": "{{symbol}}잔액 부족", "plugin_trader_error_insufficient_lp": "유동성 부족", "plugin_trade_error_input_amount_less_minimum_amount": "입력 금액은 최소 금액 이하입니다.", - "plugin_trader_settings_data_source_primary": "트렌딩 데이터 소스", - "plugin_trader_settings_data_source_secondary": "암호화폐의 트렌딩 데이터를 선택하세요.", "plugin_trader_slippage_tolerance": "슬리피지 톨러런스:", "plugin_trader_swap_from": "From", "plugin_trader_swap_to": "To(estimated)", diff --git a/packages/mask/shared-ui/locales/qya-AA.json b/packages/mask/shared-ui/locales/qya-AA.json index 12421f3f022c..c3ae1b888ebb 100644 --- a/packages/mask/shared-ui/locales/qya-AA.json +++ b/packages/mask/shared-ui/locales/qya-AA.json @@ -152,15 +152,6 @@ "service_invalid_backup_file": "crwdns4345:0crwdne4345:0", "service_unknown_payload": "crwdns4357:0crwdne4357:0", "service_username_invalid": "crwdns4359:0crwdne4359:0", - "settings_enable_debug": "crwdns4427:0crwdne4427:0", - "settings_enable_debug_desc": "crwdns4429:0crwdne4429:0", - "settings_appearance": "crwdns4431:0crwdne4431:0", - "settings_appearance_secondary": "crwdns4433:0crwdne4433:0", - "settings_language": "crwdns4441:0crwdne4441:0", - "settings_language_secondary": "crwdns4443:0crwdne4443:0", - "settings_choose_eth_network": "crwdns4445:0crwdne4445:0", - "settings_launch_page": "crwdns4457:0crwdne4457:0", - "settings_launch_page_secondary": "crwdns4459:0crwdne4459:0", "speed_up": "crwdns9393:0crwdne9393:0", "save": "crwdns10439:0crwdne10439:0", "skip": "crwdns4463:0crwdne4463:0", @@ -318,10 +309,6 @@ "plugin_wallet_not_available_on": "crwdns7913:0{{network}}crwdne7913:0", "plugin_wallet_connect_wallet": "crwdns4693:0crwdne4693:0", "plugin_wallet_connect_wallet_tip": "crwdns4695:0crwdne4695:0", - "plugin_wallet_settings_fungible_asset_data_source_primary": "crwdns10043:0crwdne10043:0", - "plugin_wallet_settings_fungible_asset_data_source_secondary": "crwdns10045:0crwdne10045:0", - "plugin_wallet_settings_non_fungible_data_source_primary": "crwdns10047:0crwdne10047:0", - "plugin_wallet_settings_non_fungible_data_source_secondary": "crwdns10049:0crwdne10049:0", "plugin_wallet_name_placeholder": "crwdns4705:0crwdne4705:0", "plugin_wallet_fail_to_sign": "crwdns4707:0crwdne4707:0", "plugin_wallet_cancel_sign": "crwdns4709:0crwdne4709:0", @@ -452,8 +439,6 @@ "plugin_trader_error_insufficient_balance": "crwdns4917:0{{symbol}}crwdne4917:0", "plugin_trader_error_insufficient_lp": "crwdns4919:0crwdne4919:0", "plugin_trade_error_input_amount_less_minimum_amount": "crwdns4923:0crwdne4923:0", - "plugin_trader_settings_data_source_primary": "crwdns4927:0crwdne4927:0", - "plugin_trader_settings_data_source_secondary": "crwdns4929:0crwdne4929:0", "plugin_trader_slippage_tolerance": "crwdns7917:0crwdne7917:0", "plugin_trader_swap_from": "crwdns10441:0crwdne10441:0", "plugin_trader_swap_to": "crwdns10443:0crwdne10443:0", diff --git a/packages/mask/shared-ui/locales/zh-CN.json b/packages/mask/shared-ui/locales/zh-CN.json index 7cf2eaec9d61..a2e6e7faba63 100644 --- a/packages/mask/shared-ui/locales/zh-CN.json +++ b/packages/mask/shared-ui/locales/zh-CN.json @@ -143,15 +143,6 @@ "service_invalid_backup_file": "这似乎不是Mask的备份。", "service_unknown_payload": "未知的贴文版本。您可能需要更新Mask。", "service_username_invalid": "无效的用户名", - "settings_enable_debug": "调试模式", - "settings_enable_debug_desc": "查看更多信息进行调试。", - "settings_appearance": "外观", - "settings_appearance_secondary": "选择您要使用的外观主题.", - "settings_language": "语言", - "settings_language_secondary": "选择您要使用的语言.", - "settings_choose_eth_network": "选择以太坊网络", - "settings_launch_page": "启动页面", - "settings_launch_page_secondary": "选择启动应用程序时要打开的默认页面", "speed_up": "加速", "save": "保存", "skip": "跳过", @@ -308,10 +299,6 @@ "plugin_wallet_not_available_on": "在 {{network}} 网络上不可用。", "plugin_wallet_connect_wallet": "连接钱包", "plugin_wallet_connect_wallet_tip": "请连接钱包", - "plugin_wallet_settings_fungible_asset_data_source_primary": "投资组合数据源", - "plugin_wallet_settings_fungible_asset_data_source_secondary": "选择投资组合数据来源。", - "plugin_wallet_settings_non_fungible_data_source_primary": "收藏品数据源", - "plugin_wallet_settings_non_fungible_data_source_secondary": "选择收藏品的数据源。", "plugin_wallet_name_placeholder": "输入1-12 个字符", "plugin_wallet_fail_to_sign": "无法签名密码。", "plugin_wallet_cancel_sign": "签名已取消。", @@ -439,8 +426,6 @@ "plugin_trader_error_insufficient_balance": "{{symbol}} 余额不足", "plugin_trader_error_insufficient_lp": "该交易的流动性不足", "plugin_trade_error_input_amount_less_minimum_amount": "提交兑换的数额低于最低数额", - "plugin_trader_settings_data_source_primary": "趋势数据源", - "plugin_trader_settings_data_source_secondary": "选择加密货币趋势数据的来源。", "plugin_trader_slippage_tolerance": "滑点容许值", "plugin_trader_swap_from": "从", "plugin_trader_swap_to": "至(预计)", diff --git a/packages/mask/shared-ui/locales/zh-TW.json b/packages/mask/shared-ui/locales/zh-TW.json index 0d750aed3bd7..531eafacb83d 100644 --- a/packages/mask/shared-ui/locales/zh-TW.json +++ b/packages/mask/shared-ui/locales/zh-TW.json @@ -100,15 +100,6 @@ "service_invalid_backup_file": "這不是一個 Mask 的備份檔。", "service_unknown_payload": "未知的貼文版本。您或許需要升級 Mask。", "service_username_invalid": "錯誤的使用者名稱", - "settings_enable_debug": "除錯模式", - "settings_enable_debug_desc": "請參考有關除錯的附加資訊", - "settings_appearance": "外觀", - "settings_appearance_secondary": "選擇你想使用的外觀。", - "settings_language": "語言", - "settings_language_secondary": "選擇你想使用的語言。", - "settings_choose_eth_network": "選擇乙太坊網路", - "settings_launch_page": "啟動頁面", - "settings_launch_page_secondary": "選擇啟動程式時要打開的預設頁面", "speed_up": "加速", "save": "存檔", "skip": "跳過", @@ -230,7 +221,6 @@ "plugin_wallet_not_available_on": "{{network}} 不可用", "plugin_wallet_connect_wallet": "連接錢包", "plugin_wallet_connect_wallet_tip": "請連接你的錢包", - "plugin_wallet_settings_non_fungible_data_source_primary": "收藏品資料來源", "plugin_red_packet_display_name": "插件:紅包", "plugin_red_packet_claimed": "已認領", "plugin_red_packet_erc20_tab_title": "代幣", @@ -308,8 +298,6 @@ "plugin_trader_error_insufficient_balance": "{{symbol}} 餘額不足", "plugin_trader_error_insufficient_lp": "本次交易流動性不足", "plugin_trade_error_input_amount_less_minimum_amount": "輸入金額低於最小值", - "plugin_trader_settings_data_source_primary": "趨勢資料來源", - "plugin_trader_settings_data_source_secondary": "選擇加密貨幣趨勢資料的來源。", "plugin_trader_slippage_tolerance": "滑動容許值:", "plugin_trader_swap_from": "來自", "plugin_trader_gas_fee": "礦工費", diff --git a/packages/mask/shared-ui/locales_legacy/index.ts b/packages/mask/shared-ui/locales_legacy/index.ts index b457d247f7db..9c881feb36f3 100644 --- a/packages/mask/shared-ui/locales_legacy/index.ts +++ b/packages/mask/shared-ui/locales_legacy/index.ts @@ -1,40 +1,15 @@ -import i18nNextInstance from 'i18next' -import type { TOptions } from 'i18next' +import { i18NextInstance, TranslateOptions } from '@masknet/shared-base' import type en from '../locales/en-US.json' -import Detector from 'i18next-browser-languagedetector' - -import { addMaskI18N } from '../locales/languages' -import { addSharedI18N } from '@masknet/shared' -import { fallbackLng } from '@masknet/shared-base' -// @ts-ignore in case circle dependency make typescript complains -import { addDashboardI18N } from '@masknet/dashboard' - -i18nNextInstance.use(Detector).init({ - keySeparator: false, - interpolation: { escapeValue: false }, - fallbackLng, - defaultNS: 'mask', - nonExplicitSupportedLngs: true, - detection: { - order: ['navigator'], - }, -}) - -addMaskI18N(i18nNextInstance) -addSharedI18N(i18nNextInstance) -addDashboardI18N(i18nNextInstance) - -export default i18nNextInstance // Deprecates. Prefer useMaskI18n() export const i18n = { t: ((key, options) => { - return i18nNextInstance.t(key, options) + return i18NextInstance.t(key, options) }) as I18NFunction, } export type I18NFunction = ( key: TKeys | TKeys[], // defaultValue?: string, - options?: TOptions | string, + options?: TranslateOptions | string, ) => typeof en[TKeys] diff --git a/packages/mask/shared-ui/locales_legacy/init.ts b/packages/mask/shared-ui/locales_legacy/init.ts new file mode 100644 index 000000000000..479c608d97c2 --- /dev/null +++ b/packages/mask/shared-ui/locales_legacy/init.ts @@ -0,0 +1,13 @@ +import { i18NextInstance } from '@masknet/shared-base' + +// @ts-ignore to prevent TypeScript complains +import { addDashboardI18N } from '@masknet/dashboard' +import { addMaskI18N } from '../locales/languages' +import { addSharedI18N } from '@masknet/shared' + +import { initReactI18next } from 'react-i18next' + +initReactI18next.init(i18NextInstance) +addMaskI18N(i18NextInstance) +addSharedI18N(i18NextInstance) +addDashboardI18N(i18NextInstance) diff --git a/packages/mask/src/UIRoot.tsx b/packages/mask/src/UIRoot.tsx index f117c0b281f8..58221ebea995 100644 --- a/packages/mask/src/UIRoot.tsx +++ b/packages/mask/src/UIRoot.tsx @@ -4,7 +4,7 @@ import { CssBaseline, StyledEngineProvider, Theme } from '@mui/material' import { NetworkPluginID, PluginsWeb3ContextProvider, useAllPluginsWeb3State } from '@masknet/plugin-infra' import { I18NextProviderHMR } from '@masknet/shared' import { ErrorBoundary, ErrorBoundaryBuildInfoContext, useValueRef } from '@masknet/shared-base-ui' -import i18nNextInstance from '../shared-ui/locales_legacy' +import { i18NextInstance } from '@masknet/shared-base' import { Web3Context } from './web3/context' import { buildInfoMarkdown } from './utils/BuildInfoMarkdown' import { activatedSocialNetworkUI } from './social-network' @@ -50,7 +50,7 @@ export function MaskUIRoot({ children, kind, useTheme }: MaskUIRootProps) { ), - (jsx) => , + (jsx) => , kind === 'page' ? (jsx) => : identity, (jsx) => ( ( signal: AbortSignal | undefined, @@ -26,7 +24,7 @@ export function createPluginHost( signal, minimalMode, addI18NResource(plugin, resource) { - createI18NBundle(plugin, resource)(i18nNextInstance) + createI18NBundle(plugin, resource)(i18NextInstance) }, createContext, } diff --git a/packages/mask/src/plugins/ITO/assets/formatDate.ts b/packages/mask/src/plugins/ITO/assets/formatDate.ts index 8cad1ee04f0e..92b715fd378a 100644 --- a/packages/mask/src/plugins/ITO/assets/formatDate.ts +++ b/packages/mask/src/plugins/ITO/assets/formatDate.ts @@ -1,7 +1,7 @@ -import i18nNextInstance from '../../../../shared-ui/locales_legacy' +import { i18NextInstance } from '@masknet/shared-base' export const dateTimeFormat = (date: Date, includeTime = true) => - new Intl.DateTimeFormat(i18nNextInstance.language, { + new Intl.DateTimeFormat(i18NextInstance.language, { year: 'numeric', month: 'numeric', day: 'numeric', diff --git a/packages/mask/src/plugins/Pets/settings.ts b/packages/mask/src/plugins/Pets/settings.ts index 5f8214a4fabe..89cfc8dc529d 100644 --- a/packages/mask/src/plugins/Pets/settings.ts +++ b/packages/mask/src/plugins/Pets/settings.ts @@ -1,6 +1,4 @@ import { createGlobalSettings } from '../../settings/createSettings' import { PetsPluginID } from './constants' -export const petShowSettings = createGlobalSettings(`${PetsPluginID}+selectedClosePet`, true, { - primary: () => 'DO NOT DISPLAY IT IN UI', -}) +export const petShowSettings = createGlobalSettings(`${PetsPluginID}+selectedClosePet`, true) diff --git a/packages/mask/src/plugins/Trader/settings.ts b/packages/mask/src/plugins/Trader/settings.ts index f27830ef56fe..82b450abf78f 100644 --- a/packages/mask/src/plugins/Trader/settings.ts +++ b/packages/mask/src/plugins/Trader/settings.ts @@ -1,6 +1,5 @@ import { unreachable } from '@dimensiondev/kit' import { createGlobalSettings, createInternalSettings } from '../../settings/createSettings' -import { i18n } from '../../../shared-ui/locales_legacy' import { PLUGIN_ID, SLIPPAGE_DEFAULT } from './constants' import type { ZrxTradePool } from './types' import { DataProvider } from '@masknet/public-api' @@ -8,20 +7,12 @@ import { DataProvider } from '@masknet/public-api' /** * The slippage tolerance of trader */ -export const currentSlippageSettings = createGlobalSettings( - `${PLUGIN_ID}+slippageTolerance`, - SLIPPAGE_DEFAULT, - { - primary: () => '', - }, -) +export const currentSlippageSettings = createGlobalSettings(`${PLUGIN_ID}+slippageTolerance`, SLIPPAGE_DEFAULT) /** * Single Hop */ -export const currentSingleHopOnlySettings = createGlobalSettings(`${PLUGIN_ID}+singleHopOnly`, false, { - primary: () => '', -}) +export const currentSingleHopOnlySettings = createGlobalSettings(`${PLUGIN_ID}+singleHopOnly`, false) /** * The default data provider @@ -29,10 +20,6 @@ export const currentSingleHopOnlySettings = createGlobalSettings(`${PLU export const currentDataProviderSettings = createGlobalSettings( `${PLUGIN_ID}+dataProvider`, DataProvider.COIN_GECKO, - { - primary: () => i18n.t('plugin_trader_settings_data_source_primary'), - secondary: () => i18n.t('plugin_trader_settings_data_source_secondary'), - }, ) // #region trade provider general settings diff --git a/packages/mask/src/plugins/Wallet/settings.ts b/packages/mask/src/plugins/Wallet/settings.ts index 45c7a5bfebab..a0b94cd6c47f 100644 --- a/packages/mask/src/plugins/Wallet/settings.ts +++ b/packages/mask/src/plugins/Wallet/settings.ts @@ -1,6 +1,5 @@ import { isEqual } from 'lodash-unified' import { createGlobalSettings } from '../../settings/createSettings' -import { i18n } from '../../../shared-ui/locales_legacy' import { ChainId, NonFungibleAssetProvider, @@ -16,93 +15,51 @@ import { PLUGIN_ID } from './constants' export const currentMaskWalletAccountSettings = createGlobalSettings( `${PLUGIN_ID}+selectedMaskWalletAddress`, '', - { - primary: () => 'DO NOT DISPLAY IT IN UI', - }, ) export const currentMaskWalletChainIdSettings = createGlobalSettings( `${PLUGIN_ID}+maskWalletChainId`, ChainId.Mainnet, - { - primary: () => i18n.t('settings_choose_eth_network'), - secondary: () => 'This only affects the built-in wallet.', - }, ) export const currentMaskWalletNetworkSettings = createGlobalSettings( `${PLUGIN_ID}+selectedMaskWalletNetwork`, NetworkType.Ethereum, - { - primary: () => 'DO NOT DISPLAY IT IN UI', - }, ) export const currentMaskWalletLockStatusSettings = createGlobalSettings( `${PLUGIN_ID}+maskWalletLockStatus`, LockStatus.INIT, - { - primary: () => 'DO NOT DISPLAY IT IN UI', - }, ) -export const currentAccountSettings = createGlobalSettings(`${PLUGIN_ID}+selectedWalletAddress`, '', { - primary: () => 'DO NOT DISPLAY IT IN UI', -}) +export const currentAccountSettings = createGlobalSettings(`${PLUGIN_ID}+selectedWalletAddress`, '') -export const currentChainIdSettings = createGlobalSettings(`${PLUGIN_ID}+chainId`, ChainId.Mainnet, { - primary: () => i18n.t('settings_choose_eth_network'), - secondary: () => 'This only affects the built-in wallet.', -}) +export const currentChainIdSettings = createGlobalSettings(`${PLUGIN_ID}+chainId`, ChainId.Mainnet) export const currentNetworkSettings = createGlobalSettings( `${PLUGIN_ID}+selectedWalletNetwork`, NetworkType.Ethereum, - { - primary: () => 'DO NOT DISPLAY IT IN UI', - }, ) export const currentProviderSettings = createGlobalSettings( `${PLUGIN_ID}+selectedWalletProvider`, ProviderType.MaskWallet, - { - primary: () => 'DO NOT DISPLAY IT IN UI', - }, ) export const currentFungibleAssetDataProviderSettings = createGlobalSettings( `${PLUGIN_ID}+fungibleAssetProvider`, FungibleAssetProvider.DEBANK, - { - primary: () => i18n.t('plugin_wallet_settings_fungible_asset_data_source_primary'), - secondary: () => i18n.t('plugin_wallet_settings_fungible_asset_data_source_secondary'), - }, ) export const currentNonFungibleAssetDataProviderSettings = createGlobalSettings( `${PLUGIN_ID}+nonFungibleAssetProvider`, NonFungibleAssetProvider.OPENSEA, - { - primary: () => i18n.t('plugin_wallet_settings_non_fungible_data_source_primary'), - secondary: () => i18n.t('plugin_wallet_settings_non_fungible_data_source_secondary'), - }, ) export const currentGasOptionsSettings = createGlobalSettings( `${PLUGIN_ID}+gasOptions`, null, - { - primary: () => 'DO NOT DISPLAY IT IN UI', - }, - (a: GasOptions | null, b: GasOptions | null) => isEqual(a, b), + isEqual, ) -export const currentTokenPricesSettings = createGlobalSettings( - `${PLUGIN_ID}+tokenPrices`, - {}, - { - primary: () => 'DO NOT DISPLAY IT IN UI', - }, - (a, b) => isEqual(a, b), -) +export const currentTokenPricesSettings = createGlobalSettings(`${PLUGIN_ID}+tokenPrices`, {}, isEqual) diff --git a/packages/mask/src/settings/createSettings.ts b/packages/mask/src/settings/createSettings.ts index 7892708da862..e55825ec7090 100644 --- a/packages/mask/src/settings/createSettings.ts +++ b/packages/mask/src/settings/createSettings.ts @@ -3,10 +3,6 @@ import Services from '../extension/service' import { MaskMessages } from '../utils/messages' import { defer } from '@dimensiondev/kit' -export interface SettingsTexts { - primary: () => string - secondary?: () => string -} export type InternalSettings = ValueRef & { readonly key: string readonly ready: boolean @@ -94,7 +90,6 @@ export function createInternalSettings( export function createGlobalSettings( key: string, value: T, - UITexts: SettingsTexts, comparer: ValueComparer = defaultValueComparer, ) { const settings = createInternalSettings(`settings+${key}`, value, comparer) diff --git a/packages/mask/src/settings/settings.ts b/packages/mask/src/settings/settings.ts index 8f21f995b71d..587dc78a9bff 100644 --- a/packages/mask/src/settings/settings.ts +++ b/packages/mask/src/settings/settings.ts @@ -1,70 +1,21 @@ import { createGlobalSettings, createNetworkSettings, NetworkSettings } from './createSettings' -import { i18n } from '../../shared-ui/locales_legacy' import { LaunchPage } from './types' import { Appearance } from '@masknet/theme' import { LanguageOptions } from '@masknet/public-api' -import { Identifier, ProfileIdentifier } from '@masknet/shared-base' +import { updateLanguage } from '@masknet/shared-base' import { PLUGIN_ID } from '../plugins/EVM/constants' import { isEqual } from 'lodash-unified' -/** - * Does the debug mode on - */ -export const debugModeSetting = createGlobalSettings('debugMode', false, { - primary: () => i18n.t('settings_enable_debug'), - secondary: () => i18n.t('settings_enable_debug_desc'), -}) - -// #region appearance -export const appearanceSettings = createGlobalSettings('appearance', Appearance.default, { - primary: () => i18n.t('settings_appearance'), - secondary: () => i18n.t('settings_appearance_secondary'), -}) -// #endregion - -// #region language -export const languageSettings = createGlobalSettings('language', LanguageOptions.__auto__, { - primary: () => i18n.t('settings_language'), - secondary: () => i18n.t('settings_language_secondary'), -}) -// #endregion +export const debugModeSetting = createGlobalSettings('debugMode', false) +export const appearanceSettings = createGlobalSettings('appearance', Appearance.default) +export const languageSettings = createGlobalSettings('language', LanguageOptions.__auto__) +languageSettings.addListener(updateLanguage) +export const pluginIDSettings = createGlobalSettings('pluginID', PLUGIN_ID) -// #region web3 plugin ID -export const pluginIDSettings = createGlobalSettings('pluginID', PLUGIN_ID, { - primary: () => 'DO NOT DISPLAY IT IN UI', -}) -// #endregion - -// #region network setting - -/** - * Expected Usage: export const currentImagePayloadStatus = createNetworkSettings('currentImagePayloadStatus') - * - * Work around the issue: - * https://github.com/microsoft/TypeScript/issues/42873 - * https://github.com/microsoft/TypeScript/issues/30858 - * - * References: - * PluginGitcoinMessages: packages/mask/src/plugins/Gitcoin/messages.ts - * PluginTraderMessages: packages/mask/src/plugins/Trader/messages.ts - * PluginTransakMessages: packages/mask/src/plugins/Transak/messages.ts - */ -export const currentImagePayloadStatus: NetworkSettings = createNetworkSettings('currentImagePayloadStatus', '') -export const currentSelectedIdentity: NetworkSettings = createNetworkSettings('currentSelectedIdentity', '') -export function getCurrentSelectedIdentity(network: string) { - return Identifier.fromString(currentSelectedIdentity[network].value, ProfileIdentifier).unwrapOr( - ProfileIdentifier.unknown, - ) -} export const currentSetupGuideStatus: NetworkSettings = createNetworkSettings('currentSetupGuideStatus', '') export const userGuideStatus: NetworkSettings = createNetworkSettings('userGuideStatus', '') export const sayHelloShowed: NetworkSettings = createNetworkSettings('sayHelloShowed', false) -export const dismissPinExtensionTip = createGlobalSettings('dismissPinExtensionTip', false, { - primary: () => '', -}) -export const userPinExtension = createGlobalSettings('userPinExtension', false, { - primary: () => '', -}) +export const userPinExtension = createGlobalSettings('userPinExtension', false) export const dismissVerifyNextID: NetworkSettings<{ [key in string]: boolean }> = createNetworkSettings( 'dismissVerifyNextID', {}, @@ -85,21 +36,8 @@ export const currentPluginMinimalModeNOTEnabled: NetworkSettings = crea 'pluginsEnabled', true, ) -// #endregion - -export const launchPageSettings = createGlobalSettings('launchPage', LaunchPage.dashboard, { - primary: () => i18n.t('settings_launch_page'), - secondary: () => i18n.t('settings_launch_page_secondary'), -}) - -export const newDashboardConnection = createGlobalSettings('beta-dashboard', false, { - primary: () => 'Experimental: Allow isolated dashboard to connect', - secondary: () => "WARNING: DON'T OPEN THIS UNLESS YOU KNOW WHAT YOU ARE DOING.", -}) - -export const currentPersonaIdentifier = createGlobalSettings('currentPersonaIdentifier', '', { - primary: () => 'DO NOT DISPLAY IT IN UI', -}) +export const launchPageSettings = createGlobalSettings('launchPage', LaunchPage.dashboard) +export const currentPersonaIdentifier = createGlobalSettings('currentPersonaIdentifier', '') try { // Migrate language settings diff --git a/packages/mask/src/setup.ui.ts b/packages/mask/src/setup.ui.ts index 2b38418f12b8..27c93e7e4758 100644 --- a/packages/mask/src/setup.ui.ts +++ b/packages/mask/src/setup.ui.ts @@ -1,4 +1,5 @@ // Start SNS adaptor +import '../shared-ui/locales_legacy/init' import './setup.ui.0' import './social-network-adaptor' import { activateSocialNetworkUI } from './social-network/define' diff --git a/packages/mask/src/social-network/ui.ts b/packages/mask/src/social-network/ui.ts index a83e52c5f38d..001c5103391f 100644 --- a/packages/mask/src/social-network/ui.ts +++ b/packages/mask/src/social-network/ui.ts @@ -2,7 +2,6 @@ import '../utils/debug/general' import '../utils/debug/ui' import Services from '../extension/service' import { Flags, InMemoryStorages, PersistentStorages } from '../../shared' -import i18nNextInstance from '../../shared-ui/locales_legacy' import type { SocialNetworkUI } from './types' import { managedStateCreator } from './utils' import { currentSetupGuideStatus } from '../settings/settings' @@ -13,6 +12,7 @@ import { createSubscriptionFromAsync, PersonaIdentifier, EnhanceableSite, + i18NextInstance, } from '@masknet/shared-base' import { Environment, assertNotEnvironment } from '@dimensiondev/holoflows-kit' import { startPluginSNSAdaptor } from '@masknet/plugin-infra' @@ -128,7 +128,7 @@ export async function activateSocialNetworkUIInner(ui_deferred: SocialNetworkUI. const pair = i18n[namespace][i18nKey] for (const language in pair) { const value = pair[language] - i18nNextInstance.addResource(language, namespace, i18nKey, value) + i18NextInstance.addResource(language, namespace, i18nKey, value) } } } diff --git a/packages/mask/src/utils/i18n-next-ui.ts b/packages/mask/src/utils/i18n-next-ui.ts index 092d9984a306..1e893020cca6 100644 --- a/packages/mask/src/utils/i18n-next-ui.ts +++ b/packages/mask/src/utils/i18n-next-ui.ts @@ -1,17 +1,12 @@ -import type { i18n, TOptions } from 'i18next' -import { initReactI18next, useTranslation as useTranslation_, UseTranslationOptions } from 'react-i18next' +import { useTranslation, UseTranslationOptions } from 'react-i18next' import type en from '../../shared-ui/locales/en-US.json' -import i18nNextInstance from '../../shared-ui/locales_legacy' -import { languageSettings } from '../settings/settings' -import { LanguageOptions, SupportedLanguages } from '@masknet/public-api' -import { languages } from '../../shared-ui' - -i18nNextInstance.use(initReactI18next) +import type { i18NextInstance, TranslateOptions } from '@masknet/shared-base' +import { SupportedLanguages } from '@masknet/public-api' export type I18NFunction = ( key: TKeys | TKeys[], // defaultValue?: string, - options?: TOptions | string, + options?: TranslateOptions | string, ) => typeof en[TKeys] /** @@ -20,27 +15,15 @@ export type I18NFunction = ( */ export function useI18N(opt?: UseTranslationOptions): { t: I18NFunction - i18n: i18n + i18n: typeof i18NextInstance ready: boolean } { - return useTranslation_('mask', opt) + return useTranslation('mask', opt) } export function useLanguage(): SupportedLanguages { - const { i18n } = useTranslation_() + const { i18n } = useTranslation() const lang = i18n.language if (lang in SupportedLanguages) return lang as any return SupportedLanguages.enUS } - -languageSettings.addListener((next): void => { - if (next === LanguageOptions.__auto__) { - const result: string[] = i18nNextInstance.services.languageDetector.detect() - for (const lng of result) { - if (lng in languages) return void i18nNextInstance.changeLanguage(lng) - } - i18nNextInstance.changeLanguage(LanguageOptions.enUS) - } else { - i18nNextInstance.changeLanguage(next) - } -}) diff --git a/packages/shared-base/package.json b/packages/shared-base/package.json index 9b6f20cedb00..d3fee20bccef 100644 --- a/packages/shared-base/package.json +++ b/packages/shared-base/package.json @@ -18,6 +18,8 @@ "anchorme": "^2.1.2", "async-call-rpc": "^6.0.2", "bignumber.js": "^9.0.2", + "i18next": "^21.6.14", + "i18next-browser-languagedetector": "^6.1.4", "idb": "^7.0.1", "immer": "^9.0.12", "pvtsutils": "^1.2.2", diff --git a/packages/shared-base/src/i18n/fallbackRule.ts b/packages/shared-base/src/i18n/fallbackRule.ts deleted file mode 100644 index 54b1f8121f85..000000000000 --- a/packages/shared-base/src/i18n/fallbackRule.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const fallbackLng = { - 'zh-CN': ['zh-TW', 'en'], - 'zh-TW': ['zh-CN', 'en'], - default: ['en'], -} diff --git a/packages/shared-base/src/i18n/index.ts b/packages/shared-base/src/i18n/index.ts index 56d0888dfd27..6b7f6be3a525 100644 --- a/packages/shared-base/src/i18n/index.ts +++ b/packages/shared-base/src/i18n/index.ts @@ -1,2 +1,2 @@ -export * from './fallbackRule' export * from './register-ns' +export { i18NextInstance, type TranslateOptions, updateLanguage } from './instance' diff --git a/packages/shared-base/src/i18n/instance.ts b/packages/shared-base/src/i18n/instance.ts new file mode 100644 index 000000000000..6f584c77a1c0 --- /dev/null +++ b/packages/shared-base/src/i18n/instance.ts @@ -0,0 +1,31 @@ +import { LanguageOptions } from '@masknet/public-api' +import i18n from 'i18next' +import Detector from 'i18next-browser-languagedetector' + +export const i18NextInstance = i18n + +i18n.use(Detector).init({ + keySeparator: false, + interpolation: { escapeValue: false }, + fallbackLng: { + 'zh-CN': ['zh-TW', 'en'], + 'zh-TW': ['zh-CN', 'en'], + default: ['en'], + }, + defaultNS: 'mask', + nonExplicitSupportedLngs: true, + detection: { + order: ['navigator'], + }, +}) + +export function updateLanguage(next: LanguageOptions) { + if (next === LanguageOptions.__auto__) { + const result: string[] = i18n.services.languageDetector.detect() + i18n.changeLanguage(result[0] || LanguageOptions.enUS) + } else { + i18n.changeLanguage(next) + } +} + +export type { TOptions as TranslateOptions } from 'i18next' diff --git a/packages/shared-base/src/i18n/register-ns.ts b/packages/shared-base/src/i18n/register-ns.ts index 481e59576ef8..ae7239c88012 100644 --- a/packages/shared-base/src/i18n/register-ns.ts +++ b/packages/shared-base/src/i18n/register-ns.ts @@ -1,6 +1,6 @@ import type { i18n } from 'i18next' -export function addI18NBundle(instance: i18n, namespace: string, langs: Record) { +function addI18NBundle(instance: i18n, namespace: string, langs: Record) { if (!instance.addResourceBundle) throw new TypeError('Please call instance.init() first') try { diff --git a/packages/shared/src/UI/components/I18NextProviderHMR.tsx b/packages/shared/src/UI/components/I18NextProviderHMR.tsx index 3539057ad94f..ed52432832b5 100644 --- a/packages/shared/src/UI/components/I18NextProviderHMR.tsx +++ b/packages/shared/src/UI/components/I18NextProviderHMR.tsx @@ -1,6 +1,8 @@ import React, { useEffect, useState } from 'react' -import { I18nextProvider, type I18nextProviderProps } from 'react-i18next' +import { I18nextProvider, initReactI18next, type I18nextProviderProps } from 'react-i18next' +import { i18NextInstance } from '@masknet/shared-base' +initReactI18next.init(i18NextInstance) export const I18NextProviderHMR = process.env.NODE_ENV === 'development' ? function I18NextProviderHMR({ i18n, defaultNS, children }: React.PropsWithChildren) { diff --git a/packages/theme/.storybook/preview.js b/packages/theme/.storybook/preview.js index daf2e3b6abee..f5de10eae390 100644 --- a/packages/theme/.storybook/preview.js +++ b/packages/theme/.storybook/preview.js @@ -4,16 +4,10 @@ import { MaskDarkTheme, MaskLightTheme, applyMaskColorVars } from '../src/index' // Not compatible? // import { withMatrix } from 'storybook-addon-matrix' import { I18nextProvider, initReactI18next } from 'react-i18next' -import i18n from 'i18next' +import { i18NextInstance } from '@masknet/shared-base' + +initReactI18next.init(i18NextInstance) -i18n.init({ - keySeparator: false, - interpolation: { escapeValue: false }, - // TODO: use fallbackLng from shared-base package - fallbackLng: 'en-US', - nonExplicitSupportedLngs: true, -}) -i18n.use(initReactI18next) export const parameters = { actions: { argTypesRegex: '^on[A-Z].*' }, } @@ -32,7 +26,7 @@ export const decorators = [ - + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c344b0f33007..7426325d938d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,7 +44,6 @@ importers: eslint-plugin-unused-imports: ^2.0.0 gulp: ^4.0.2 husky: ^7.0.4 - i18next: ^21.6.14 jest: ^28.0.0-alpha.3 lint-staged: ^12.3.7 lodash: ^4.17.21 @@ -75,13 +74,12 @@ importers: '@types/react': 17.0.43 '@types/react-dom': 17.0.14 '@types/web': 0.0.60 - i18next: 21.6.14 lodash: 4.17.21 lodash-es: 4.17.21 lodash-unified: 1.0.2_da03a4540fbd16bbaafbb96724306afd react: 18.0.0 react-dom: 18.0.0_react@18.0.0 - react-i18next: 11.16.2_67d9cd14f543534febc666d787b5936c + react-i18next: 11.16.2_react-dom@18.0.0+react@18.0.0 ts-results: 3.3.0 web3-core: 1.5.2 web3-core-method: 1.5.2 @@ -164,7 +162,6 @@ importers: color: ^4.2.1 date-fns: 2.28.0 html-to-image: ^1.9.0 - i18next-browser-languagedetector: ^6.1.4 json-stable-stringify: ^1.0.1 path-browserify: ^1.0.1 react-avatar-editor: ^12.0.0 @@ -210,7 +207,6 @@ importers: color: 4.2.1 date-fns: 2.28.0 html-to-image: 1.9.0 - i18next-browser-languagedetector: 6.1.4 json-stable-stringify: 1.0.1 react-avatar-editor: 12.0.0_572108936dbf4157100a77328045f809 react-hook-form: 7.28.1_react@18.0.0 @@ -378,7 +374,6 @@ importers: graphql-request: ^3.4.0 html-webpack-plugin: ^5.5.0 https-browserify: ^1.0.0 - i18next-browser-languagedetector: ^6.1.4 idb: ^7.0.1 iframe-resizer-react: ^1.1.0 immer: ^9.0.12 @@ -509,7 +504,6 @@ importers: graphql: 15.5.3 graphql-request: 3.5.0_graphql@15.5.3 https-browserify: 1.0.0 - i18next-browser-languagedetector: 6.1.4 idb: 7.0.1 iframe-resizer-react: 1.1.0_react-dom@18.0.0+react@18.0.0 immer: 9.0.12 @@ -616,7 +610,7 @@ importers: unstated-next: 1.1.0 use-subscription: 1.6.0_react@18.0.0 devDependencies: - react-i18next: 11.16.2_67d9cd14f543534febc666d787b5936c + react-i18next: 11.16.2_react-dom@18.0.0+react@18.0.0 packages/plugins/CyberConnect: specifiers: @@ -1020,6 +1014,8 @@ importers: anchorme: ^2.1.2 async-call-rpc: ^6.0.2 bignumber.js: ^9.0.2 + i18next: ^21.6.14 + i18next-browser-languagedetector: ^6.1.4 idb: ^7.0.1 immer: ^9.0.12 pvtsutils: ^1.2.2 @@ -1043,6 +1039,8 @@ importers: anchorme: 2.1.2 async-call-rpc: 6.0.2 bignumber.js: 9.0.2 + i18next: 21.6.14 + i18next-browser-languagedetector: 6.1.4 idb: 7.0.1 immer: 9.0.12 pvtsutils: 1.2.2 @@ -17975,7 +17973,7 @@ packages: /i18next/21.6.14: resolution: {integrity: sha512-XL6WyD+xlwQwbieXRlXhKWoLb/rkch50/rA+vl6untHnJ+aYnkQ0YDZciTWE78PPhOpbi2gR0LTJCJpiAhA+uQ==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dev: false /iconv-lite/0.4.24: @@ -22873,7 +22871,7 @@ packages: react: 18.0.0 dev: false - /react-i18next/11.16.2_67d9cd14f543534febc666d787b5936c: + /react-i18next/11.16.2_react-dom@18.0.0+react@18.0.0: resolution: {integrity: sha512-1iuZduvARUelL5ux663FvIoDZExwFO+9QtRAAt4uvs1/aun4cUZt8XBrVg7iiDgNls9cOSORAhE7Ri5KA9RMvg==} peerDependencies: i18next: '>= 19.0.0' @@ -22889,7 +22887,6 @@ packages: '@babel/runtime': 7.17.8 html-escaper: 2.0.2 html-parse-stringify: 3.0.1 - i18next: 21.6.14 react: 18.0.0 react-dom: 18.0.0_react@18.0.0