diff --git a/ui/apps/dashboard/src/main.tsx b/ui/apps/dashboard/src/main.tsx index d614bf56..3bb1bc0d 100644 --- a/ui/apps/dashboard/src/main.tsx +++ b/ui/apps/dashboard/src/main.tsx @@ -1,57 +1,56 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App.tsx'; -import i18nInstance, {getLang} from '@/utils/i18n'; -import {initReactI18next} from 'react-i18next'; -import {loader} from '@monaco-editor/react'; +import i18nInstance, { getLang } from '@/utils/i18n'; +import { initReactI18next } from 'react-i18next'; +import { loader } from '@monaco-editor/react'; import * as monaco from 'monaco-editor'; import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'; // https://github.com/remcohaszing/monaco-yaml/issues/150 import yamlWorker from '@/utils/workaround-yaml.worker?worker'; import enTexts from '../locales/en-US.json'; import zhTexts from '../locales/zh-CN.json'; -import {initRoute} from '@/routes/route.tsx'; +import { initRoute } from '@/routes/route.tsx'; window.MonacoEnvironment = { - getWorker(_, label) { - if (label === 'yaml') { - return new yamlWorker(); - } - return new editorWorker(); - }, + getWorker(_, label) { + if (label === 'yaml') { + return new yamlWorker(); + } + return new editorWorker(); + }, }; -loader.config({monaco}); +loader.config({ monaco }); i18nInstance - .use(initReactI18next) // passes i18n down to react-i18next - .init({ - debug: true, - lng: getLang(), // if you're using a language detector, do not define the lng option - fallbackLng: ['zh-CN'], - resources: { - zh: { - translation: zhTexts, - }, - en: { - translation: enTexts, - }, - }, - interpolation: { - escapeValue: false, // react already safes from xss => https://www.i18next.com/translation-function/interpolation#unescape - }, - saveMissing: true, // send not translated keys to endpoint, - react: { - useSuspense: false, - }, - }) - .then(() => { - initRoute(); - ReactDOM.createRoot(document.getElementById('root')!).render( - - - , - ); - }) - .catch(() => { - - }) + .use(initReactI18next) // passes i18n down to react-i18next + .init({ + debug: true, + lng: getLang(), // if you're using a language detector, do not define the lng option + // fallbackLng: ['zh-CN'], + fallbackLng: ['en-US'], + resources: { + zh: { + translation: zhTexts, + }, + en: { + translation: enTexts, + }, + }, + interpolation: { + escapeValue: false, // react already safes from xss => https://www.i18next.com/translation-function/interpolation#unescape + }, + saveMissing: true, // send not translated keys to endpoint, + react: { + useSuspense: false, + }, + }) + .then(() => { + initRoute(); + ReactDOM.createRoot(document.getElementById('root')!).render( + + + , + ); + }) + .catch(() => {}); diff --git a/ui/apps/dashboard/src/pages/cluster-manage/index.tsx b/ui/apps/dashboard/src/pages/cluster-manage/index.tsx index 8e8be2b0..bfca18c4 100644 --- a/ui/apps/dashboard/src/pages/cluster-manage/index.tsx +++ b/ui/apps/dashboard/src/pages/cluster-manage/index.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import Panel from '@/components/panel'; import { useQuery } from '@tanstack/react-query'; import { GetClusters } from '@/services'; @@ -54,7 +54,9 @@ const ClusterManagePage = () => { }); const columns: TableColumnProps[] = [ { - title: i18nInstance.t('c3f28b34bbdec501802fa403584267e6', '集群名称'), + title: titleCase( + i18nInstance.t('c3f28b34bbdec501802fa403584267e6', '集群名称'), + ), key: 'clusterName', width: 150, render: (_, r) => { @@ -63,9 +65,8 @@ const ClusterManagePage = () => { }, }, { - title: i18nInstance.t( - 'bd17297989ec345cbc03ae0b8a13dc0a', - 'kubernetes版本', + title: titleCase( + i18nInstance.t('bd17297989ec345cbc03ae0b8a13dc0a', 'kubernetes版本'), ), dataIndex: 'kubernetesVersion', key: 'kubernetesVersion', @@ -73,7 +74,9 @@ const ClusterManagePage = () => { align: 'center', }, { - title: i18nInstance.t('ee00813361387a116d274c608ba8bb13', '集群状态'), + title: titleCase( + i18nInstance.t('ee00813361387a116d274c608ba8bb13', '集群状态'), + ), dataIndex: 'ready', key: 'ready', align: 'center', @@ -113,7 +116,9 @@ const ClusterManagePage = () => { }, }, { - title: i18nInstance.t('f0789e79d48f135e5d870753f7a85d05', '模式'), + title: titleCase( + i18nInstance.t('f0789e79d48f135e5d870753f7a85d05', '模式'), + ), dataIndex: 'syncMode', width: 150, align: 'center', @@ -126,7 +131,9 @@ const ClusterManagePage = () => { }, }, { - title: i18nInstance.t('b86224e030e5948f96b70a4c3600b33f', '节点状态'), + title: titleCase( + i18nInstance.t('b86224e030e5948f96b70a4c3600b33f', '节点状态'), + ), dataIndex: 'nodeStatus', align: 'center', width: 150, @@ -143,7 +150,9 @@ const ClusterManagePage = () => { }, }, { - title: i18nInstance.t('763a78a5fc84dbca6f0137a591587f5f', 'cpu用量'), + title: titleCase( + i18nInstance.t('763a78a5fc84dbca6f0137a591587f5f', 'cpu用量'), + ), dataIndex: 'cpuFraction', width: '15%', render: (_, r) => { @@ -159,7 +168,9 @@ const ClusterManagePage = () => { }, }, { - title: i18nInstance.t('8b2e672e8b847415a47cc2dd25a87a07', 'memory用量'), + title: titleCase( + i18nInstance.t('8b2e672e8b847415a47cc2dd25a87a07', 'memory用量'), + ), dataIndex: 'memoryFraction', width: '15%', render: (_, r) => { @@ -175,7 +186,9 @@ const ClusterManagePage = () => { }, }, { - title: i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + title: titleCase( + i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + ), key: 'op', width: 200, render: (_, r) => { diff --git a/ui/apps/dashboard/src/pages/multicloud-policy-manage/override-policy/index.tsx b/ui/apps/dashboard/src/pages/multicloud-policy-manage/override-policy/index.tsx index 284644e9..289cc460 100644 --- a/ui/apps/dashboard/src/pages/multicloud-policy-manage/override-policy/index.tsx +++ b/ui/apps/dashboard/src/pages/multicloud-policy-manage/override-policy/index.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import { useMemo, useState } from 'react'; import Panel from '@/components/panel'; import { @@ -90,7 +90,9 @@ const OverridePolicyManage = () => { }); const columns = [ filter.policyScope === 'namespace-scope' && { - title: i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + title: titleCase( + i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + ), key: 'namespaceName', width: 200, render: (_v: string, r: OverridePolicy | ClusterOverridePolicy) => { @@ -98,7 +100,9 @@ const OverridePolicyManage = () => { }, }, { - title: i18nInstance.t('53cf41060c577315071a7c14bb612852', '策略名称'), + title: titleCase( + i18nInstance.t('53cf41060c577315071a7c14bb612852', '策略名称'), + ), key: 'policyName', width: 200, render: (_v: string, r: OverridePolicy | ClusterOverridePolicy) => { @@ -106,9 +110,8 @@ const OverridePolicyManage = () => { }, }, { - title: i18nInstance.t( - '8a59b316f11d99f01ebe9b1b466ba8de', - '差异化策略类型', + title: titleCase( + i18nInstance.t('8a59b316f11d99f01ebe9b1b466ba8de', '差异化策略类型'), ), key: 'ruleTypes', dataIndex: 'ruleTypes', @@ -125,7 +128,9 @@ const OverridePolicyManage = () => { }, }, { - title: i18nInstance.t('ab7e397dd8c88360e441f1c1525a5758', '关联集群'), + title: titleCase( + i18nInstance.t('ab7e397dd8c88360e441f1c1525a5758', '关联集群'), + ), key: 'cluster', render: (_v: string, r: OverridePolicy | ClusterOverridePolicy) => { const clusters = extractClusterNames(r); @@ -140,7 +145,9 @@ const OverridePolicyManage = () => { }, }, { - title: i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + title: titleCase( + i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + ), key: 'op', width: 200, render: (_v: string, r: OverridePolicy | ClusterOverridePolicy) => { @@ -263,16 +270,17 @@ const OverridePolicyManage = () => { }} options={[ { - label: i18nInstance.t( - 'bf15e71b2553d369585ace795d15ac3b', - '命名空间级别', + label: titleCase( + i18nInstance.t( + 'bf15e71b2553d369585ace795d15ac3b', + '命名空间级别', + ), ), value: 'namespace-scope', }, { - label: i18nInstance.t( - '860f29d8fc7a68113902db52885111d4', - '集群级别', + label: titleCase( + i18nInstance.t('860f29d8fc7a68113902db52885111d4', '集群级别'), ), value: 'cluster-scope', }, diff --git a/ui/apps/dashboard/src/pages/multicloud-policy-manage/propagation-policy/index.tsx b/ui/apps/dashboard/src/pages/multicloud-policy-manage/propagation-policy/index.tsx index a743c63a..417e21ba 100644 --- a/ui/apps/dashboard/src/pages/multicloud-policy-manage/propagation-policy/index.tsx +++ b/ui/apps/dashboard/src/pages/multicloud-policy-manage/propagation-policy/index.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import { useState } from 'react'; import Panel from '@/components/panel'; import { @@ -79,7 +79,9 @@ const PropagationPolicyManage = () => { }); const columns = [ filter.policyScope === PolicyScope.Namespace && { - title: i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + title: titleCase( + i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + ), key: 'namespaceName', width: 200, render: (_v: string, r: PropagationPolicy) => { @@ -87,7 +89,9 @@ const PropagationPolicyManage = () => { }, }, { - title: i18nInstance.t('53cf41060c577315071a7c14bb612852', '策略名称'), + title: titleCase( + i18nInstance.t('53cf41060c577315071a7c14bb612852', '策略名称'), + ), key: 'policyName', width: 200, render: (_v: string, r: PropagationPolicy) => { @@ -95,13 +99,17 @@ const PropagationPolicyManage = () => { }, }, { - title: i18nInstance.t('915f48c8fcbe25e3dc5875c471b0ce3e', '调度器名称'), + title: titleCase( + i18nInstance.t('915f48c8fcbe25e3dc5875c471b0ce3e', '调度器名称'), + ), key: 'schedulerName', dataIndex: 'schedulerName', width: 200, }, { - title: i18nInstance.t('ab7e397dd8c88360e441f1c1525a5758', '关联集群'), + title: titleCase( + i18nInstance.t('ab7e397dd8c88360e441f1c1525a5758', '关联集群'), + ), key: 'cluster', render: (_v: string, r: PropagationPolicy) => { if (!r?.clusterAffinity?.clusterNames) { @@ -117,7 +125,9 @@ const PropagationPolicyManage = () => { }, }, { - title: i18nInstance.t('8c0921045b741bc4e19d61426b99c938', '关联资源'), + title: titleCase( + i18nInstance.t('8c0921045b741bc4e19d61426b99c938', '关联资源'), + ), key: 'deployments', render: (_v: string, r: PropagationPolicy) => { return r?.deployments?.map((d) => ( @@ -126,7 +136,9 @@ const PropagationPolicyManage = () => { }, }, { - title: i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + title: titleCase( + i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + ), key: 'op', width: 200, render: (_v: string, r: PropagationPolicy) => { @@ -257,16 +269,17 @@ const PropagationPolicyManage = () => { }} options={[ { - label: i18nInstance.t( - 'bf15e71b2553d369585ace795d15ac3b', - '命名空间级别', + label: titleCase( + i18nInstance.t( + 'bf15e71b2553d369585ace795d15ac3b', + '命名空间级别', + ), ), value: PolicyScope.Namespace, }, { - label: i18nInstance.t( - '860f29d8fc7a68113902db52885111d4', - '集群级别', + label: titleCase( + i18nInstance.t('860f29d8fc7a68113902db52885111d4', '集群级别'), ), value: PolicyScope.Cluster, }, diff --git a/ui/apps/dashboard/src/pages/multicloud-resource-manage/config/components/configmap-table.tsx b/ui/apps/dashboard/src/pages/multicloud-resource-manage/config/components/configmap-table.tsx index 1112c153..7bc934c4 100644 --- a/ui/apps/dashboard/src/pages/multicloud-resource-manage/config/components/configmap-table.tsx +++ b/ui/apps/dashboard/src/pages/multicloud-resource-manage/config/components/configmap-table.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import { Button, Popconfirm, Space, Table, TableColumnProps, Tag } from 'antd'; import TagList from '@/components/tag-list'; import { FC } from 'react'; @@ -25,7 +25,9 @@ const ConfigMapTable: FC = (props) => { } = props; const columns: TableColumnProps[] = [ { - title: i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + title: titleCase( + i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + ), key: 'namespaceName', width: 200, render: (_, r) => { @@ -33,7 +35,9 @@ const ConfigMapTable: FC = (props) => { }, }, { - title: i18nInstance.t('4fcad1c9ba0732214679e13bd69d998b', '配置名称'), + title: titleCase( + i18nInstance.t('4fcad1c9ba0732214679e13bd69d998b', '配置名称'), + ), key: 'configmapName', width: 300, render: (_, r) => { @@ -41,7 +45,9 @@ const ConfigMapTable: FC = (props) => { }, }, { - title: i18nInstance.t('1f7be0a924280cd098db93c9d81ecccd', '标签信息'), + title: titleCase( + i18nInstance.t('1f7be0a924280cd098db93c9d81ecccd', '标签信息'), + ), key: 'labelName', align: 'left', width: '30%', @@ -59,7 +65,9 @@ const ConfigMapTable: FC = (props) => { }, }, { - title: i18nInstance.t('8a99082b2c32c843d2241e0ba60a3619', '分发策略'), + title: titleCase( + i18nInstance.t('8a99082b2c32c843d2241e0ba60a3619', '分发策略'), + ), key: 'propagationPolicies', render: (_, r) => { const pp = extractPropagationPolicy(r); @@ -67,15 +75,19 @@ const ConfigMapTable: FC = (props) => { }, }, { - title: i18nInstance.t('eaf8a02d1b16fcf94302927094af921f', '覆盖策略'), + title: titleCase( + i18nInstance.t('eaf8a02d1b16fcf94302927094af921f', '覆盖策略'), + ), key: 'overridePolicies', - width: 150, + width: i18nInstance.language === 'en-US' ? '200px' : '150px', render: () => { return '-'; }, }, { - title: i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + title: titleCase( + i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + ), key: 'op', width: 200, render: (_, r) => { diff --git a/ui/apps/dashboard/src/pages/multicloud-resource-manage/config/components/secret-table.tsx b/ui/apps/dashboard/src/pages/multicloud-resource-manage/config/components/secret-table.tsx index 98e1719b..a7b8423d 100644 --- a/ui/apps/dashboard/src/pages/multicloud-resource-manage/config/components/secret-table.tsx +++ b/ui/apps/dashboard/src/pages/multicloud-resource-manage/config/components/secret-table.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import { Button, Popconfirm, Space, Table, TableColumnProps, Tag } from 'antd'; import { extractPropagationPolicy } from '@/services/base'; import TagList from '@/components/tag-list'; @@ -35,7 +35,9 @@ const SecretTable: FC = (props) => { }); const columns: TableColumnProps[] = [ { - title: i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + title: titleCase( + i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + ), key: 'namespaceName', width: 200, render: (_, r) => { @@ -43,7 +45,9 @@ const SecretTable: FC = (props) => { }, }, { - title: i18nInstance.t('d1d64de5ff73bc8b408035fcdb2cc77c', '秘钥名称'), + title: titleCase( + i18nInstance.t('d1d64de5ff73bc8b408035fcdb2cc77c', '秘钥名称'), + ), key: 'secretName', width: 300, render: (_, r) => { @@ -51,7 +55,9 @@ const SecretTable: FC = (props) => { }, }, { - title: i18nInstance.t('1f7be0a924280cd098db93c9d81ecccd', '标签信息'), + title: titleCase( + i18nInstance.t('1f7be0a924280cd098db93c9d81ecccd', '标签信息'), + ), key: 'labelName', align: 'left', width: '30%', @@ -69,7 +75,9 @@ const SecretTable: FC = (props) => { }, }, { - title: i18nInstance.t('8a99082b2c32c843d2241e0ba60a3619', '分发策略'), + title: titleCase( + i18nInstance.t('8a99082b2c32c843d2241e0ba60a3619', '分发策略'), + ), key: 'propagationPolicies', render: (_, r) => { const pp = extractPropagationPolicy(r); @@ -77,15 +85,19 @@ const SecretTable: FC = (props) => { }, }, { - title: i18nInstance.t('eaf8a02d1b16fcf94302927094af921f', '覆盖策略'), + title: titleCase( + i18nInstance.t('eaf8a02d1b16fcf94302927094af921f', '覆盖策略'), + ), key: 'overridePolicies', - width: 150, + width: i18nInstance.language === 'en-US' ? '200px' : '150px', render: () => { return '-'; }, }, { - title: i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + title: titleCase( + i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + ), key: 'op', width: 200, render: (_, r) => { diff --git a/ui/apps/dashboard/src/pages/multicloud-resource-manage/namespace/index.tsx b/ui/apps/dashboard/src/pages/multicloud-resource-manage/namespace/index.tsx index 5614b0d7..992f23d6 100644 --- a/ui/apps/dashboard/src/pages/multicloud-resource-manage/namespace/index.tsx +++ b/ui/apps/dashboard/src/pages/multicloud-resource-manage/namespace/index.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import Panel from '@/components/panel'; import { useQuery } from '@tanstack/react-query'; import { App, Button, Input, Space, Table, TableColumnProps, Tag } from 'antd'; @@ -29,7 +29,9 @@ const NamespacePage = () => { const size = useWindowSize(); const columns: TableColumnProps[] = [ { - title: i18nInstance.t('06ff2e9eba7ae422587c6536e337395f', '命名空间名称'), + title: titleCase( + i18nInstance.t('06ff2e9eba7ae422587c6536e337395f', '命名空间名称'), + ), key: 'namespaceName', width: 200, render: (_, r) => { @@ -37,7 +39,9 @@ const NamespacePage = () => { }, }, { - title: i18nInstance.t('14d342362f66aa86e2aa1c1e11aa1204', '标签'), + title: titleCase( + i18nInstance.t('14d342362f66aa86e2aa1c1e11aa1204', '标签'), + ), key: 'label', align: 'left', render: (_, r) => ( @@ -48,9 +52,8 @@ const NamespacePage = () => { ), }, { - title: i18nInstance.t( - '1d5fc011c19d35d08186afc4bad14be9', - '是否跳过自动调度', + title: titleCase( + i18nInstance.t('1d5fc011c19d35d08186afc4bad14be9', '是否跳过自动调度'), ), key: 'skipAutoPropagation', render: (_, r) => { @@ -62,12 +65,16 @@ const NamespacePage = () => { }, }, { - title: i18nInstance.t('e4b51d5cd0e4f199e41c25be1c7591d3', '运行状态'), + title: titleCase( + i18nInstance.t('e4b51d5cd0e4f199e41c25be1c7591d3', '运行状态'), + ), key: 'phase', dataIndex: 'phase', }, { - title: i18nInstance.t('eca37cb0726c51702f70c486c1c38cf3', '创建时间'), + title: titleCase( + i18nInstance.t('eca37cb0726c51702f70c486c1c38cf3', '创建时间'), + ), key: 'creationTimestamp', render: (_, r) => { return dayjs(r.objectMeta.creationTimestamp).format( @@ -76,7 +83,9 @@ const NamespacePage = () => { }, }, { - title: i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + title: titleCase( + i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + ), key: 'op', width: 200, render: (_, r) => { diff --git a/ui/apps/dashboard/src/pages/multicloud-resource-manage/service/components/ingress-table.tsx b/ui/apps/dashboard/src/pages/multicloud-resource-manage/service/components/ingress-table.tsx index 933ffac2..e4379cc6 100644 --- a/ui/apps/dashboard/src/pages/multicloud-resource-manage/service/components/ingress-table.tsx +++ b/ui/apps/dashboard/src/pages/multicloud-resource-manage/service/components/ingress-table.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import { Button, Popconfirm, Space, Table, TableColumnProps, Tag } from 'antd'; import { extractPropagationPolicy, @@ -26,7 +26,9 @@ const IngressTable: FC = (props) => { } = props; const columns: TableColumnProps[] = [ { - title: i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + title: titleCase( + i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + ), key: 'namespaceName', width: 200, render: (_, r) => { @@ -34,7 +36,9 @@ const IngressTable: FC = (props) => { }, }, { - title: i18nInstance.t('d7ec2d3fea4756bc1642e0f10c180cf5', '名称'), + title: titleCase( + i18nInstance.t('d7ec2d3fea4756bc1642e0f10c180cf5', '名称'), + ), key: 'ingressName', width: 300, render: (_, r) => { @@ -42,7 +46,9 @@ const IngressTable: FC = (props) => { }, }, { - title: i18nInstance.t('1f7be0a924280cd098db93c9d81ecccd', '标签信息'), + title: titleCase( + i18nInstance.t('1f7be0a924280cd098db93c9d81ecccd', '标签信息'), + ), key: 'labelName', align: 'left', width: '30%', @@ -60,7 +66,9 @@ const IngressTable: FC = (props) => { }, }, { - title: i18nInstance.t('8a99082b2c32c843d2241e0ba60a3619', '分发策略'), + title: titleCase( + i18nInstance.t('8a99082b2c32c843d2241e0ba60a3619', '分发策略'), + ), key: 'propagationPolicies', render: (_, r) => { const pp = extractPropagationPolicy(r); @@ -68,15 +76,19 @@ const IngressTable: FC = (props) => { }, }, { - title: i18nInstance.t('eaf8a02d1b16fcf94302927094af921f', '覆盖策略'), + title: titleCase( + i18nInstance.t('eaf8a02d1b16fcf94302927094af921f', '覆盖策略'), + ), key: 'overridePolicies', - width: 150, + width: i18nInstance.language === 'en-US' ? '200px' : '150px', render: () => { return '-'; }, }, { - title: i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + title: titleCase( + i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + ), key: 'op', width: 200, render: (_, r) => { diff --git a/ui/apps/dashboard/src/pages/multicloud-resource-manage/service/components/service-table.tsx b/ui/apps/dashboard/src/pages/multicloud-resource-manage/service/components/service-table.tsx index a87e3b46..60d33d6d 100644 --- a/ui/apps/dashboard/src/pages/multicloud-resource-manage/service/components/service-table.tsx +++ b/ui/apps/dashboard/src/pages/multicloud-resource-manage/service/components/service-table.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import { Button, Popconfirm, Space, Table, TableColumnProps, Tag } from 'antd'; import { extractPropagationPolicy, @@ -9,6 +9,7 @@ import TagList from '@/components/tag-list'; import { FC } from 'react'; import { useQuery } from '@tanstack/react-query'; import { GetResource } from '@/services/unstructured.ts'; +import { useTranslation } from 'react-i18next'; interface ServiceTableProps { labelTagNum?: number; selectedWorkSpace: string; @@ -18,6 +19,7 @@ interface ServiceTableProps { onDeleteServiceContent: (r: Service) => void; } const ServiceTable: FC = (props) => { + const { i18n } = useTranslation(); const { labelTagNum, selectedWorkSpace, @@ -28,7 +30,9 @@ const ServiceTable: FC = (props) => { } = props; const columns: TableColumnProps[] = [ { - title: i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + title: titleCase( + i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + ), key: 'namespaceName', width: 200, render: (_, r) => { @@ -36,7 +40,9 @@ const ServiceTable: FC = (props) => { }, }, { - title: i18nInstance.t('8f3747c057d893862fbe4b7980e9b451', '服务名称'), + title: titleCase( + i18nInstance.t('8f3747c057d893862fbe4b7980e9b451', '服务名称'), + ), key: 'serviceName', width: 300, render: (_, r) => { @@ -44,7 +50,9 @@ const ServiceTable: FC = (props) => { }, }, { - title: i18nInstance.t('1f7be0a924280cd098db93c9d81ecccd', '标签信息'), + title: titleCase( + i18nInstance.t('1f7be0a924280cd098db93c9d81ecccd', '标签信息'), + ), key: 'labelName', align: 'left', width: '30%', @@ -62,7 +70,9 @@ const ServiceTable: FC = (props) => { }, }, { - title: i18nInstance.t('8a99082b2c32c843d2241e0ba60a3619', '分发策略'), + title: titleCase( + i18nInstance.t('8a99082b2c32c843d2241e0ba60a3619', '分发策略'), + ), key: 'propagationPolicies', render: (_, r) => { const pp = extractPropagationPolicy(r); @@ -70,15 +80,19 @@ const ServiceTable: FC = (props) => { }, }, { - title: i18nInstance.t('eaf8a02d1b16fcf94302927094af921f', '覆盖策略'), + title: titleCase( + i18nInstance.t('eaf8a02d1b16fcf94302927094af921f', '覆盖策略'), + ), key: 'overridePolicies', - width: 150, + width: i18n.language === 'en-US' ? 200 : 150, render: () => { return '-'; }, }, { - title: i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + title: titleCase( + i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + ), key: 'op', width: 200, render: (_, r) => { diff --git a/ui/apps/dashboard/src/pages/multicloud-resource-manage/workload/index.tsx b/ui/apps/dashboard/src/pages/multicloud-resource-manage/workload/index.tsx index 44451915..494c544a 100644 --- a/ui/apps/dashboard/src/pages/multicloud-resource-manage/workload/index.tsx +++ b/ui/apps/dashboard/src/pages/multicloud-resource-manage/workload/index.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import Panel from '@/components/panel'; import { App, @@ -77,7 +77,9 @@ const WorkloadPage = () => { const size = useWindowSize(); const columns: TableColumnProps[] = [ { - title: i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + title: titleCase( + i18nInstance.t('a4b28a416f0b6f3c215c51e79e517298', '命名空间'), + ), key: 'namespaceName', width: 200, render: (_, r) => { @@ -85,7 +87,9 @@ const WorkloadPage = () => { }, }, { - title: i18nInstance.t('89d19c60880d35c2bd88af0d9cc0497b', '负载名称'), + title: titleCase( + i18nInstance.t('89d19c60880d35c2bd88af0d9cc0497b', '负载名称'), + ), key: 'workloadName', width: 200, render: (_, r) => { @@ -93,7 +97,9 @@ const WorkloadPage = () => { }, }, { - title: i18nInstance.t('1f7be0a924280cd098db93c9d81ecccd', '标签信息'), + title: titleCase( + i18nInstance.t('1f7be0a924280cd098db93c9d81ecccd', '标签信息'), + ), key: 'labelName', align: 'left', width: '30%', @@ -105,7 +111,9 @@ const WorkloadPage = () => { ), }, { - title: i18nInstance.t('8a99082b2c32c843d2241e0ba60a3619', '分发策略'), + title: titleCase( + i18nInstance.t('8a99082b2c32c843d2241e0ba60a3619', '分发策略'), + ), key: 'propagationPolicies', render: (_, r) => { if (!r?.objectMeta?.annotations?.[propagationpolicyKey]) { @@ -115,15 +123,19 @@ const WorkloadPage = () => { }, }, { - title: i18nInstance.t('eaf8a02d1b16fcf94302927094af921f', '覆盖策略'), + title: titleCase( + i18nInstance.t('eaf8a02d1b16fcf94302927094af921f', '覆盖策略'), + ), key: 'overridePolicies', - width: 150, + width: i18nInstance.language === 'en-US' ? 200 : 150, render: () => { return '-'; }, }, { - title: i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + title: titleCase( + i18nInstance.t('2b6bc0f293f5ca01b006206c2535ccbc', '操作'), + ), key: 'op', width: 200, render: (_, r) => { diff --git a/ui/apps/dashboard/src/pages/multicloud-resource-manage/workload/workload-detail-drawer.tsx b/ui/apps/dashboard/src/pages/multicloud-resource-manage/workload/workload-detail-drawer.tsx index f40048c7..5b65762e 100644 --- a/ui/apps/dashboard/src/pages/multicloud-resource-manage/workload/workload-detail-drawer.tsx +++ b/ui/apps/dashboard/src/pages/multicloud-resource-manage/workload/workload-detail-drawer.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import { FC, useMemo } from 'react'; import { Drawer, @@ -59,27 +59,37 @@ const WorkloadDetailDrawer: FC = (props) => { }); const columns: TableColumnProps[] = [ { - title: i18nInstance.t('383a6d166f8f60e16e726ccc9c483631', '类别'), + title: titleCase( + i18nInstance.t('383a6d166f8f60e16e726ccc9c483631', '类别'), + ), key: 'type', dataIndex: 'type', }, { - title: i18nInstance.t('26ca20b161c33362d88eb0ba0bc90751', '来源'), + title: titleCase( + i18nInstance.t('26ca20b161c33362d88eb0ba0bc90751', '来源'), + ), key: 'sourceComponent', dataIndex: 'sourceComponent', }, { - title: i18nInstance.t('03663386e7d82f847634a6ee9111a32b', '最后检测时间'), + title: titleCase( + i18nInstance.t('03663386e7d82f847634a6ee9111a32b', '最后检测时间'), + ), key: 'lastSeen', dataIndex: 'lastSeen', }, { - title: i18nInstance.t('41dfb0bf6167ca035b93caf3e06d6c95', '原因'), + title: titleCase( + i18nInstance.t('41dfb0bf6167ca035b93caf3e06d6c95', '原因'), + ), key: 'reason', dataIndex: 'reason', }, { - title: i18nInstance.t('d8c7e04c8e2be23dd3b81a31db6e04f1', '信息'), + title: titleCase( + i18nInstance.t('d8c7e04c8e2be23dd3b81a31db6e04f1', '信息'), + ), key: 'message', dataIndex: 'message', }, @@ -87,7 +97,9 @@ const WorkloadDetailDrawer: FC = (props) => { return ( = (props) => { onClose={onClose} >
= (props) => { } /> = (props) => { /> = (props) => {
diff --git a/ui/apps/dashboard/src/pages/overview/index.tsx b/ui/apps/dashboard/src/pages/overview/index.tsx index 34a10f36..42f4568a 100644 --- a/ui/apps/dashboard/src/pages/overview/index.tsx +++ b/ui/apps/dashboard/src/pages/overview/index.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import Panel from '@/components/panel'; import { Badge, Descriptions, DescriptionsProps, Statistic, Spin } from 'antd'; import { useQuery } from '@tanstack/react-query'; @@ -16,12 +16,16 @@ const Overview = () => { const basicItems: DescriptionsProps['items'] = [ { key: 'karmada-version', - label: i18nInstance.t('66e8579fa53a0cdf402e882a3574a380', 'Karmada版本'), + label: titleCase( + i18nInstance.t('66e8579fa53a0cdf402e882a3574a380', 'Karmada版本'), + ), children: data?.karmadaInfo.version.gitVersion || '-', }, { key: 'karmada-status', - label: i18nInstance.t('3fea7ca76cdece641436d7ab0d02ab1b', '状态'), + label: titleCase( + i18nInstance.t('3fea7ca76cdece641436d7ab0d02ab1b', '状态'), + ), children: data?.karmadaInfo.status === 'running' ? ( { }, { key: 'karmada-create-time', - label: i18nInstance.t('eca37cb0726c51702f70c486c1c38cf3', '创建时间'), + label: titleCase( + i18nInstance.t('eca37cb0726c51702f70c486c1c38cf3', '创建时间'), + ), children: (data?.karmadaInfo.createTime && dayjs(data?.karmadaInfo.createTime).format('YYYY-MM-DD HH:mm:ss')) || @@ -48,7 +54,12 @@ const Overview = () => { }, { key: 'cluster-info', - label: i18nInstance.t('a0d6cb39b547d45a530a3308dce79c86', '工作集群信息'), + label: titleCase( + i18nInstance.t('a0d6cb39b547d45a530a3308dce79c86', '工作集群信息'), + ), + labelStyle: { + width: i18nInstance.language === 'en-US' ? '300px' : '150px', + }, children: ( <>
@@ -123,68 +134,76 @@ const Overview = () => { const resourceItems: DescriptionsProps['items'] = [ { key: 'policy-info', - label: i18nInstance.t('85c6051762df2fe8f93ebc1083b7f6a4', '策略信息'), + label: titleCase( + i18nInstance.t('85c6051762df2fe8f93ebc1083b7f6a4', '策略信息'), + ), children: (
), - span: 3, }, { key: 'multicloud-resources-info', - label: i18nInstance.t('612af712ef5ed7868a6b2f1d3d68530c', '多云资源信息'), + label: titleCase( + i18nInstance.t('612af712ef5ed7868a6b2f1d3d68530c', '多云资源信息'), + ), children: (
), - span: 3, }, ]; @@ -194,17 +213,23 @@ const Overview = () => { diff --git a/ui/apps/dashboard/src/routes/route.tsx b/ui/apps/dashboard/src/routes/route.tsx index 1982504f..423b0ece 100644 --- a/ui/apps/dashboard/src/routes/route.tsx +++ b/ui/apps/dashboard/src/routes/route.tsx @@ -1,4 +1,4 @@ -import i18nInstance from '@/utils/i18n'; +import i18nInstance, { titleCase } from '@/utils/i18n'; import React, { ReactNode } from 'react'; import { NonIndexRouteObject, redirect } from 'react-router-dom'; import type { MenuProps } from 'antd'; @@ -69,7 +69,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'OVERVIEW', - sidebarName: i18nInstance.t('86385379cf9cfbc2c554944f1c054a45'), + sidebarName: titleCase( + i18nInstance.t('86385379cf9cfbc2c554944f1c054a45'), + ), icon: , }, }, @@ -77,7 +79,9 @@ export function getRoutes() { path: '/multicloud-resource-manage', handle: { sidebarKey: 'MULTICLOUD-RESOURCE-MANAGE', - sidebarName: i18nInstance.t('21a4e07b08a4efbbfe2b9d88c208836a'), + sidebarName: titleCase( + i18nInstance.t('21a4e07b08a4efbbfe2b9d88c208836a'), + ), isPage: false, icon: , }, @@ -87,9 +91,11 @@ export function getRoutes() { element: , handle: { sidebarKey: 'NAMESPACE', - sidebarName: i18nInstance.t( - 'a4b28a416f0b6f3c215c51e79e517298', - '命名空间', + sidebarName: titleCase( + i18nInstance.t( + 'a4b28a416f0b6f3c215c51e79e517298', + '命名空间', + ), ), }, }, @@ -98,7 +104,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'WORKLOAD', - sidebarName: i18nInstance.t('c3bc562e9ffcae6029db730fe218515c'), + sidebarName: titleCase( + i18nInstance.t('c3bc562e9ffcae6029db730fe218515c'), + ), }, }, { @@ -106,7 +114,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'SERVICE', - sidebarName: i18nInstance.t('4653569c7943335f62caa11e38d48aa0'), + sidebarName: titleCase( + i18nInstance.t('4653569c7943335f62caa11e38d48aa0'), + ), }, }, { @@ -114,7 +124,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'CONFIG', - sidebarName: i18nInstance.t('837d8a6473195b8b5e85d58a72cb9c7e'), + sidebarName: titleCase( + i18nInstance.t('837d8a6473195b8b5e85d58a72cb9c7e'), + ), }, }, ], @@ -123,7 +135,9 @@ export function getRoutes() { path: '/multicloud-policy-manage', handle: { sidebarKey: 'MULTICLOUD-POLICY-MANAGE', - sidebarName: i18nInstance.t('8654db688fcb1f7f11f6d7ea6b208a55'), + sidebarName: titleCase( + i18nInstance.t('8654db688fcb1f7f11f6d7ea6b208a55'), + ), icon: , isPage: false, }, @@ -133,7 +147,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'PROPAGATION-POLICY', - sidebarName: i18nInstance.t('a95abe7b8eeb55427547e764bf39f1c4'), + sidebarName: titleCase( + i18nInstance.t('a95abe7b8eeb55427547e764bf39f1c4'), + ), }, }, { @@ -141,7 +157,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'OVERRIDE-POLICY', - sidebarName: i18nInstance.t('0a7e9443c41575378d2db1e288d3f1cb'), + sidebarName: titleCase( + i18nInstance.t('0a7e9443c41575378d2db1e288d3f1cb'), + ), }, }, ], @@ -151,7 +169,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'CLUSTER-MANAGE', - sidebarName: i18nInstance.t('74ea72bbd64d8251bbc2642cc38e7bb1'), + sidebarName: titleCase( + i18nInstance.t('74ea72bbd64d8251bbc2642cc38e7bb1'), + ), icon: , isPage: false, }, @@ -160,7 +180,9 @@ export function getRoutes() { path: '/basic-config', handle: { sidebarKey: 'BASIC-CONFIG', - sidebarName: i18nInstance.t('cba0d61936703636d3ab45914c9e754a'), + sidebarName: titleCase( + i18nInstance.t('cba0d61936703636d3ab45914c9e754a'), + ), icon: , isPage: false, }, @@ -170,7 +192,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'OEM', - sidebarName: i18nInstance.t('bdf0eb5121c6dd3b2c57ab9d01b02a7e'), + sidebarName: titleCase( + i18nInstance.t('bdf0eb5121c6dd3b2c57ab9d01b02a7e'), + ), }, }, { @@ -178,7 +202,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'UPGRADE', - sidebarName: i18nInstance.t('0506797675615f94ddf57bebca9da81f'), + sidebarName: titleCase( + i18nInstance.t('0506797675615f94ddf57bebca9da81f'), + ), }, }, { @@ -186,7 +212,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'KARMADA-CONFIG', - sidebarName: i18nInstance.t('3955f4df8c2b4cb52d3c91296308edef'), + sidebarName: titleCase( + i18nInstance.t('3955f4df8c2b4cb52d3c91296308edef'), + ), }, }, { @@ -194,7 +222,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'HELM', - sidebarName: i18nInstance.t('f8bb304d7eae5ddba6ac13bf6931187b'), + sidebarName: titleCase( + i18nInstance.t('f8bb304d7eae5ddba6ac13bf6931187b'), + ), }, }, { @@ -202,7 +232,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'REGISTRY', - sidebarName: i18nInstance.t('c8330a63d6dfbb7dabb24cbf26430cb4'), + sidebarName: titleCase( + i18nInstance.t('c8330a63d6dfbb7dabb24cbf26430cb4'), + ), }, }, ], @@ -211,9 +243,8 @@ export function getRoutes() { path: '/advanced-config', handle: { sidebarKey: 'ADVANCED-CONFIG', - sidebarName: i18nInstance.t( - '1f318234cab713b51b5172d91770bc11', - '高级配置', + sidebarName: titleCase( + i18nInstance.t('1f318234cab713b51b5172d91770bc11', '高级配置'), ), icon: , isPage: false, @@ -224,7 +255,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'FAILOVER', - sidebarName: i18nInstance.t('41c84a00fe4f8f03d3f06a5887de31c8'), + sidebarName: titleCase( + i18nInstance.t('41c84a00fe4f8f03d3f06a5887de31c8'), + ), }, }, { @@ -232,7 +265,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'RESCHEDULE', - sidebarName: i18nInstance.t('28a905999d14769b2aae998b74c1a864'), + sidebarName: titleCase( + i18nInstance.t('28a905999d14769b2aae998b74c1a864'), + ), }, }, { @@ -240,7 +275,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'PERMISSION', - sidebarName: i18nInstance.t('23bbdd59d0b1d94621fc98e7f533ad9f'), + sidebarName: titleCase( + i18nInstance.t('23bbdd59d0b1d94621fc98e7f533ad9f'), + ), }, }, ], @@ -249,7 +286,9 @@ export function getRoutes() { path: '/addon', handle: { sidebarKey: 'ADDON', - sidebarName: i18nInstance.t('14c4e4ecdac2ff3337385747dda6e621'), + sidebarName: titleCase( + i18nInstance.t('14c4e4ecdac2ff3337385747dda6e621'), + ), icon: , isPage: false, }, @@ -259,7 +298,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'BUILDIN', - sidebarName: i18nInstance.t('976eb1e050088fbdd7d2cab3f644e7e5'), + sidebarName: titleCase( + i18nInstance.t('976eb1e050088fbdd7d2cab3f644e7e5'), + ), }, }, { @@ -267,7 +308,9 @@ export function getRoutes() { element: , handle: { sidebarKey: 'THIRDPARTY', - sidebarName: i18nInstance.t('fb7f97d757a27c46d1e4f03287d9dd1f'), + sidebarName: titleCase( + i18nInstance.t('fb7f97d757a27c46d1e4f03287d9dd1f'), + ), }, }, ], diff --git a/ui/apps/dashboard/src/utils/i18n.tsx b/ui/apps/dashboard/src/utils/i18n.tsx index 0b12fec8..58bb1505 100644 --- a/ui/apps/dashboard/src/utils/i18n.tsx +++ b/ui/apps/dashboard/src/utils/i18n.tsx @@ -58,4 +58,22 @@ export function getSidebarWidth(lang?: string) { return supportedLangConfig[lang]?.sidebarWidth || ''; } +export function capitalize(value: string) { + if (!value) return ''; + return value.charAt(0).toUpperCase() + value.slice(1); +} + +export function titleCase(value: string) { + if (!value) return ''; + return value + .split(' ') + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); +} + +export function lowerCase(value: string) { + if (!value) return ''; + return value.toLowerCase(); +} + export default i18nInstance;