Merge branch 'dev/i18n' into dev/main
This commit is contained in:
commit
71e90e7edd
@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<link rel="icon" type="image/png" href="/logo.svg"/>
|
<link rel="icon" type="image/png" href="/logo.svg"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<title>数字人直播</title>
|
<title></title>
|
||||||
<style>
|
<style>
|
||||||
.app-loading-text{font-family:"PingFang SC","Microsoft YaHei",sans-serif;position:fixed;left:0;right:0;text-align:center;top:50%;transform:translateY(-50%);font-size:20px}
|
.app-loading-text{font-family:"PingFang SC","Microsoft YaHei",sans-serif;position:fixed;left:0;right:0;text-align:center;top:50%;transform:translateY(-50%);font-size:20px}
|
||||||
</style>
|
</style>
|
||||||
|
@ -26,10 +26,12 @@
|
|||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"flv.js": "^1.6.2",
|
"flv.js": "^1.6.2",
|
||||||
|
"i18next": "^24.2.1",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"qs": "^6.12.1",
|
"qs": "^6.12.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-i18next": "^15.4.0",
|
||||||
"react-player": "^2.16.0",
|
"react-player": "^2.16.0",
|
||||||
"react-router-dom": "^6.28.0",
|
"react-router-dom": "^6.28.0",
|
||||||
"sass": "^1.81.0",
|
"sass": "^1.81.0",
|
||||||
|
@ -6,6 +6,7 @@ import {showErrorToast, showToast} from "@/components/message.ts";
|
|||||||
import {BizError} from "@/service/types.ts";
|
import {BizError} from "@/service/types.ts";
|
||||||
import {IconWarningCircle} from "@/components/icons";
|
import {IconWarningCircle} from "@/components/icons";
|
||||||
import {LoadingOutlined} from "@ant-design/icons";
|
import {LoadingOutlined} from "@ant-design/icons";
|
||||||
|
import {useTranslation} from "react-i18next";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
selected: any[],
|
selected: any[],
|
||||||
@ -29,6 +30,7 @@ export default function ButtonBatch(
|
|||||||
selected, emptyMessage, successMessage, children, icon,
|
selected, emptyMessage, successMessage, children, icon,
|
||||||
title, confirmMessage, onProcess, onSuccess, className
|
title, confirmMessage, onProcess, onSuccess, className
|
||||||
}: Props) {
|
}: Props) {
|
||||||
|
const {t} = useTranslation()
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const {modal} = App.useApp()
|
const {modal} = App.useApp()
|
||||||
const onBatchProcess = async () => {
|
const onBatchProcess = async () => {
|
||||||
@ -54,7 +56,7 @@ export default function ButtonBatch(
|
|||||||
if(confirmMessage){
|
if(confirmMessage){
|
||||||
modal.confirm({
|
modal.confirm({
|
||||||
wrapClassName: 'root-modal-confirm',
|
wrapClassName: 'root-modal-confirm',
|
||||||
title: title || '操作提示',
|
title: title || t('notice.title'),
|
||||||
centered: true,
|
centered: true,
|
||||||
icon: <span className="anticon anticon-exclamation-circle"><IconWarningCircle/></span>,
|
icon: <span className="anticon anticon-exclamation-circle"><IconWarningCircle/></span>,
|
||||||
content: confirmMessage,
|
content: confirmMessage,
|
||||||
|
@ -2,12 +2,12 @@ import React, {useEffect} from "react";
|
|||||||
|
|
||||||
type DocumentTitleProps = {
|
type DocumentTitleProps = {
|
||||||
children?: string;
|
children?: string;
|
||||||
text?: string;
|
title?: string;
|
||||||
}
|
}
|
||||||
export const DocumentTitle: React.FC<DocumentTitleProps> = ({children, text}) => {
|
export const DocumentTitle: React.FC<DocumentTitleProps> = ({children, title}) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (text || children) {
|
if (title || children) {
|
||||||
document.title = text || children || '';
|
document.title = title || children || '';
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
return <></>
|
return <></>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import useLocalStorage from "@/hooks/useLocalStorage";
|
import useLocalStorage from "@/hooks/useLocalStorage";
|
||||||
import {createContext} from "react";
|
import React, {createContext} from "react";
|
||||||
|
|
||||||
const config: ConfigProps = {
|
const config: ConfigProps = {
|
||||||
fontFamily: `'Public Sans', sans-serif`,
|
fontFamily: `'Public Sans', sans-serif`,
|
||||||
@ -21,7 +21,7 @@ const initialState: CustomizationProps = {
|
|||||||
|
|
||||||
const ConfigContext = createContext(initialState);
|
const ConfigContext = createContext(initialState);
|
||||||
export const ConfigProvider = ({children}: { children: React.ReactNode }) => {
|
export const ConfigProvider = ({children}: { children: React.ReactNode }) => {
|
||||||
const [config, setConfig] = useLocalStorage('app-payment-config', initialState);
|
const [config, setConfig] = useLocalStorage('app-video-admin-config', initialState);
|
||||||
// 改变语言
|
// 改变语言
|
||||||
const onChangeLocalization = (lang: I18n) => {
|
const onChangeLocalization = (lang: I18n) => {
|
||||||
setConfig({
|
setConfig({
|
||||||
|
14
src/i18n/config.ts
Normal file
14
src/i18n/config.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import i18next from 'i18next';
|
||||||
|
import {initReactI18next} from 'react-i18next';
|
||||||
|
import LangEN from './translations/en-US.json';
|
||||||
|
import LangCN from './translations/zh-CN.json';
|
||||||
|
|
||||||
|
console.log('AppConfig',AppMode)
|
||||||
|
i18next.use(initReactI18next).init({
|
||||||
|
debug: true,
|
||||||
|
fallbackLng: 'en-US',
|
||||||
|
resources: {
|
||||||
|
'en-US': {translation:LangEN},
|
||||||
|
'zh-CN': {translation:LangCN},
|
||||||
|
},
|
||||||
|
});
|
0
src/i18n/index.ts
Normal file
0
src/i18n/index.ts
Normal file
10
src/i18n/translations/en-US.json
Normal file
10
src/i18n/translations/en-US.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"AppTitle": "Digital Human Live",
|
||||||
|
"Hello": "Hello",
|
||||||
|
"login": {
|
||||||
|
"text": "Login"
|
||||||
|
},
|
||||||
|
"notice": {
|
||||||
|
"title": "操作提示"
|
||||||
|
}
|
||||||
|
}
|
10
src/i18n/translations/zh-CN.json
Normal file
10
src/i18n/translations/zh-CN.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"AppTitle": "数字人直播",
|
||||||
|
"Hello": "你好",
|
||||||
|
"login": {
|
||||||
|
"text": "登录"
|
||||||
|
},
|
||||||
|
"notice": {
|
||||||
|
"title": "Notice"
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import {createBrowserRouter, RouterProvider,} from "react-router-dom";
|
import {createBrowserRouter, RouterProvider,} from "react-router-dom";
|
||||||
import {Suspense,} from "react";
|
import {Suspense, useEffect,} from "react";
|
||||||
import {ConfigProvider, App} from "antd";
|
import {ConfigProvider, App} from "antd";
|
||||||
import zhCN from 'antd/locale/zh_CN';
|
import zhCN from 'antd/locale/zh_CN';
|
||||||
// for date-picker i18n
|
// for date-picker i18n
|
||||||
@ -8,10 +8,11 @@ import 'dayjs/locale/zh-cn';
|
|||||||
import ErrorBoundary from "./error.tsx";
|
import ErrorBoundary from "./error.tsx";
|
||||||
import Loader from "@/components/loader.tsx";
|
import Loader from "@/components/loader.tsx";
|
||||||
import routes from "@/routes/routes.tsx";
|
import routes from "@/routes/routes.tsx";
|
||||||
|
import {DocumentTitle} from "@/components/document.tsx";
|
||||||
|
import useConfig from "@/hooks/useConfig.ts";
|
||||||
|
import {useTranslation} from "react-i18next";
|
||||||
|
|
||||||
|
|
||||||
dayjs.locale('zh-cn');
|
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
...routes,
|
...routes,
|
||||||
{path: '*', element: <ErrorBoundary/>}
|
{path: '*', element: <ErrorBoundary/>}
|
||||||
@ -28,16 +29,23 @@ const router = createBrowserRouter([
|
|||||||
|
|
||||||
// future={{v7_startTransition: true,v7_relativeSplatPath: true}}
|
// future={{v7_startTransition: true,v7_relativeSplatPath: true}}
|
||||||
const AppRouter = () => {
|
const AppRouter = () => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
const {i18n} = useConfig();
|
||||||
|
useEffect(() => {
|
||||||
|
if (i18n && i18n == 'zh-CN') {
|
||||||
|
dayjs.locale('zh-cn');
|
||||||
|
}
|
||||||
|
}, [i18n])
|
||||||
|
|
||||||
return (<ConfigProvider
|
return (<ConfigProvider
|
||||||
locale={zhCN}
|
locale={i18n == 'zh-CN' ? zhCN : undefined}
|
||||||
theme={{
|
theme={{
|
||||||
token: {
|
token: {
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<DocumentTitle title={t('AppTitle')}/>
|
||||||
<App>
|
<App>
|
||||||
<Suspense fallback={<Loader/>}>
|
<Suspense fallback={<Loader/>}>
|
||||||
<RouterProvider future={{v7_startTransition: true}} router={router}/>
|
<RouterProvider future={{v7_startTransition: true}} router={router}/>
|
||||||
|
@ -12,6 +12,7 @@ import useAuth from "@/hooks/useAuth.ts";
|
|||||||
import {hidePhone} from "@/util/strings.ts";
|
import {hidePhone} from "@/util/strings.ts";
|
||||||
import {defaultCache} from "@/hooks/useCache.ts";
|
import {defaultCache} from "@/hooks/useCache.ts";
|
||||||
import {IconVideo} from "@/components/icons";
|
import {IconVideo} from "@/components/icons";
|
||||||
|
import {useTranslation} from "react-i18next";
|
||||||
|
|
||||||
|
|
||||||
type LayoutProps = {
|
type LayoutProps = {
|
||||||
@ -19,6 +20,7 @@ type LayoutProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const NavigationUserContainer = () => {
|
const NavigationUserContainer = () => {
|
||||||
|
const {t } = useTranslation()
|
||||||
const {logout, user} = useAuth()
|
const {logout, user} = useAuth()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const handleLogout = ()=>{
|
const handleLogout = ()=>{
|
||||||
@ -41,7 +43,7 @@ const NavigationUserContainer = () => {
|
|||||||
className={`flex items-center rounded-3xl ${user ? 'bg-[#e3eeff]' : 'bg-primary-blue'} p-1 pr-2 cursor-pointer rounded`}>
|
className={`flex items-center rounded-3xl ${user ? 'bg-[#e3eeff]' : 'bg-primary-blue'} p-1 pr-2 cursor-pointer rounded`}>
|
||||||
<UserAvatar className="user-avatar size-7"/>
|
<UserAvatar className="user-avatar size-7"/>
|
||||||
{user ? <span className={"username ml-2 text-sm"}>{hidePhone(user.nickname)}</span> : (
|
{user ? <span className={"username ml-2 text-sm"}>{hidePhone(user.nickname)}</span> : (
|
||||||
<span className="text-sm mx-2 text-white">登录</span>
|
<span className="text-sm mx-2 text-white">{t('login.text')}</span>
|
||||||
)}
|
)}
|
||||||
</div>)
|
</div>)
|
||||||
return (<div className={"flex items-center justify-between gap-2 ml-10"}>
|
return (<div className={"flex items-center justify-between gap-2 ml-10"}>
|
||||||
|
2
src/types/config.d.ts
vendored
2
src/types/config.d.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
type I18n = 'en-US' | 'zh-CN' | 'zh-HK';
|
type I18n = 'en-US' | 'zh-CN' | 'zh-HK' | string;
|
||||||
|
|
||||||
type ConfigProps = {
|
type ConfigProps = {
|
||||||
fontFamily: string;
|
fontFamily: string;
|
||||||
|
29
yarn.lock
29
yarn.lock
@ -201,7 +201,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.25.9"
|
"@babel/helper-plugin-utils" "^7.25.9"
|
||||||
|
|
||||||
"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.6", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.4", "@babel/runtime@^7.24.7", "@babel/runtime@^7.24.8", "@babel/runtime@^7.25.7":
|
"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.6", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.4", "@babel/runtime@^7.24.7", "@babel/runtime@^7.24.8", "@babel/runtime@^7.25.0", "@babel/runtime@^7.25.7":
|
||||||
version "7.26.0"
|
version "7.26.0"
|
||||||
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1"
|
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1"
|
||||||
integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
|
integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
|
||||||
@ -1870,6 +1870,20 @@ hasown@^2.0.0, hasown@^2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.1.2"
|
function-bind "^1.1.2"
|
||||||
|
|
||||||
|
html-parse-stringify@^3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.npmmirror.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2"
|
||||||
|
integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==
|
||||||
|
dependencies:
|
||||||
|
void-elements "3.1.0"
|
||||||
|
|
||||||
|
i18next@^24.2.1:
|
||||||
|
version "24.2.1"
|
||||||
|
resolved "https://registry.npmmirror.com/i18next/-/i18next-24.2.1.tgz#91e8f11fc9bd7042ec0bd36bed2dd0457aaa35fa"
|
||||||
|
integrity sha512-Q2wC1TjWcSikn1VAJg13UGIjc+okpFxQTxjVAymOnSA3RpttBQNMPf2ovcgoFVsV4QNxTfNZMAxorXZXsk4fBA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.23.2"
|
||||||
|
|
||||||
ignore@^5.2.0, ignore@^5.3.1:
|
ignore@^5.2.0, ignore@^5.3.1:
|
||||||
version "5.3.2"
|
version "5.3.2"
|
||||||
resolved "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
resolved "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
||||||
@ -2905,6 +2919,14 @@ react-fast-compare@^3.0.1, react-fast-compare@^3.2.2:
|
|||||||
resolved "https://registry.npmmirror.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
|
resolved "https://registry.npmmirror.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
|
||||||
integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
|
integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
|
||||||
|
|
||||||
|
react-i18next@^15.4.0:
|
||||||
|
version "15.4.0"
|
||||||
|
resolved "https://registry.npmmirror.com/react-i18next/-/react-i18next-15.4.0.tgz#87c755fb6d7a567eec134e4759b022a0baacb19e"
|
||||||
|
integrity sha512-Py6UkX3zV08RTvL6ZANRoBh9sL/ne6rQq79XlkHEdd82cZr2H9usbWpUNVadJntIZP2pu3M2rL1CN+5rQYfYFw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.25.0"
|
||||||
|
html-parse-stringify "^3.0.1"
|
||||||
|
|
||||||
react-is@^16.13.1:
|
react-is@^16.13.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
@ -3444,6 +3466,11 @@ vite@^5.2.0:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.3"
|
fsevents "~2.3.3"
|
||||||
|
|
||||||
|
void-elements@3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.npmmirror.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
|
||||||
|
integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==
|
||||||
|
|
||||||
webworkify-webpack@^2.1.5:
|
webworkify-webpack@^2.1.5:
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
resolved "https://registry.npmmirror.com/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz#bf4336624c0626cbe85cf1ffde157f7aa90b1d1c"
|
resolved "https://registry.npmmirror.com/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz#bf4336624c0626cbe85cf1ffde157f7aa90b1d1c"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user