diff --git a/src/locales/en-US/apikeys.ts b/src/locales/en-US/apikeys.ts index 97e96696..d213cf4a 100644 --- a/src/locales/en-US/apikeys.ts +++ b/src/locales/en-US/apikeys.ts @@ -12,5 +12,8 @@ export default { 'apikeys.form.expiration.1month': '1 month', 'apikeys.form.expiration.6months': '6 months', 'apikeys.form.expiration.never': 'No expiration', - 'apikeys.table.bindModels': 'Allowed Models' + 'apikeys.table.bindModels': 'Model Access', + 'apikeys.models.all': 'All models', + 'apikeys.models.selected': 'Selected models', + 'apikeys.models.noModelsFound': 'No models found' }; diff --git a/src/locales/en-US/models.ts b/src/locales/en-US/models.ts index 728bed19..2b0767b1 100644 --- a/src/locales/en-US/models.ts +++ b/src/locales/en-US/models.ts @@ -170,5 +170,16 @@ export default { 'models.form.enableSpeculativeDecoding': 'Enable Speculative Decoding', 'models.form.check.clusterUnavailable': 'Current cluster is unavailable', 'models.form.check.otherClustersAvailable': - 'Available clusters: {clusters}. Please switch cluster.' + 'Available clusters: {clusters}. Please switch cluster.', + 'models.button.accessSettings': 'Access Settings', + 'models.table.accessScope': 'Access Scope', + 'models.table.accessScope.all': 'All users', + 'models.table.accessScope.selected': 'Selected users', + 'models.table.userSelection': 'User Selection', + 'models.table.filterByName': 'Filter by username', + 'models.table.admin': 'Admin', + 'models.table.noselected': 'No users selected', + 'models.table.users.all': 'All Users', + 'models.table.users.selected': 'Selected Users', + 'models.table.nouserFound': 'No users found' }; diff --git a/src/locales/ja-JP/apikeys.ts b/src/locales/ja-JP/apikeys.ts index 8627e6bb..d8da8e34 100644 --- a/src/locales/ja-JP/apikeys.ts +++ b/src/locales/ja-JP/apikeys.ts @@ -12,5 +12,15 @@ export default { 'apikeys.form.expiration.1month': '1ヶ月', 'apikeys.form.expiration.6months': '6ヶ月', 'apikeys.form.expiration.never': '無期限', - 'apikeys.table.bindModels': '許可されたモデル' + 'apikeys.table.bindModels': 'Model Access', + 'apikeys.models.all': 'All models', + 'apikeys.models.selected': 'Selected models', + 'apikeys.models.noModelsFound': 'No models found' }; + +// ========== To-Do: Translate Keys (Remove After Translation) ========== +// 1. 'apikeys.table.bindModels': 'Model Access', +// 2. 'apikeys.models.all': 'All models', +// 3. 'apikeys.models.selected': 'Selected models', +// 4. 'apikeys.models.noModelsFound': 'No models found' +// ========== End of To-Do List ========== diff --git a/src/locales/ja-JP/models.ts b/src/locales/ja-JP/models.ts index 2d6dba78..ca8c72b6 100644 --- a/src/locales/ja-JP/models.ts +++ b/src/locales/ja-JP/models.ts @@ -167,7 +167,18 @@ export default { 'models.form.enableSpeculativeDecoding': '推測デコーディングを有効にする', 'models.form.check.clusterUnavailable': 'Current cluster is unavailable', 'models.form.check.otherClustersAvailable': - 'Available clusters: {clusters}. Please switch cluster.' + 'Available clusters: {clusters}. Please switch cluster.', + 'models.button.accessSettings': 'Access Settings', + 'models.table.accessScope': 'Access Scope', + 'models.table.accessScope.all': 'All users', + 'models.table.accessScope.selected': 'Selected users', + 'models.table.userSelection': 'User Selection', + 'models.table.filterByName': 'Filter by username', + 'models.table.admin': 'Admin', + 'models.table.noselected': 'No users selected', + 'models.table.users.all': 'All Users', + 'models.table.users.selected': 'Selected Users', + 'models.table.nouserFound': 'No users found' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -175,5 +186,19 @@ export default { // 2. 'models.ollama.deprecated.notice': `The Ollama model source has been deprecated as of v0.6.1. For more information, see the related GitHub issue.` // 3. 'models.backend.mindie.310p':'Ascend 310P only supports FP16, so you need to set --dtype=float16.', // 4. 'models.form.check.clusterUnavailable': 'Current cluster is unavailable', -// 5. 'models.form.check.otherClustersAvailable': 'Available clusters: {clusters}. Please switch cluster.' +// 5. 'models.form.check.otherClustersAvailable': 'Available clusters: {clusters}. Please switch cluster.', +// 6. 'models.button.accessSettings': 'Access Settings', +// 7. 'models.table.accessScope': 'Access Scope', +// 8. 'models.table.accessScope.all': 'All users', +// 9. 'models.table.accessScope.selected': 'Selected users', +// 10. 'models.table.userSelection': 'User Selection', +// 11. 'models.table.filterByName': 'Filter by username', +// 12. 'models.table.admin': 'Admin', +// 13. 'models.table.noselected': 'No users selected' +// 14. 'models.table.uses.all': 'All users', +// 15. 'models.table.uses.selected': 'Selected users', +// 16. 'models.table.nouserFound': 'No users found', +// 17. 'models.table.users.all': 'All Users', +// 18. 'models.table.users.selected': 'Selected Users', +// 19. 'models.table.nouserFound': 'No users found' // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/apikeys.ts b/src/locales/ru-RU/apikeys.ts index b384f2b6..a76aae2d 100644 --- a/src/locales/ru-RU/apikeys.ts +++ b/src/locales/ru-RU/apikeys.ts @@ -12,5 +12,15 @@ export default { 'apikeys.form.expiration.1month': '1 месяц', 'apikeys.form.expiration.6months': '6 месяцев', 'apikeys.form.expiration.never': 'Без срока действия', - 'apikeys.table.bindModels': 'Разрешенные модели' + 'apikeys.table.bindModels': 'Доступ к моделям', + 'apikeys.models.all': 'All models', + 'apikeys.models.selected': 'Selected models', + 'apikeys.models.noModelsFound': 'No models found' }; + +// ========== To-Do: Translate Keys (Remove After Translation) ========== +// 1. 'apikeys.table.bindModels': 'Model Access', +// 2. 'apikeys.models.all': 'All models', +// 3. 'apikeys.models.selected': 'Selected models', +// 4. 'apikeys.models.noModelsFound': 'No models found' +// ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/models.ts b/src/locales/ru-RU/models.ts index 778e779b..9a07cc69 100644 --- a/src/locales/ru-RU/models.ts +++ b/src/locales/ru-RU/models.ts @@ -166,12 +166,34 @@ export default { 'models.form.gpuCount': 'GPU на реплику', 'models.form.gpuType': 'Тип GPU', 'models.form.optimizeLongPrompt': 'Оптимизировать длинные промпты', - 'models.form.enableSpeculativeDecoding': 'Включить спекулятивное декодирование', + 'models.form.enableSpeculativeDecoding': + 'Включить спекулятивное декодирование', 'models.form.check.clusterUnavailable': 'Текущий кластер недоступен', 'models.form.check.otherClustersAvailable': - 'Доступные кластеры: {clusters}. Пожалуйста, переключитесь на другой кластер.' + 'Доступные кластеры: {clusters}. Пожалуйста, переключитесь на другой кластер.', + 'models.button.accessSettings': 'Access Settings', + 'models.table.accessScope': 'Access Scope', + 'models.table.accessScope.all': 'All users', + 'models.table.accessScope.selected': 'Selected users', + 'models.table.userSelection': 'User Selection', + 'models.table.filterByName': 'Filter by username', + 'models.table.admin': 'Admin', + 'models.table.noselected': 'No users selected', + 'models.table.users.all': 'All users', + 'models.table.users.selected': 'Selected users', + 'models.table.nouserFound': 'No users found' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== - +// 1. 'models.button.accessSettings': 'Access Settings', +// 2. 'models.table.accessScope': 'Access Scope', +// 3. 'models.table.accessScope.all': 'All users', +// 4. 'models.table.accessScope.selected': 'Selected users', +// 5. 'models.table.userSelection': 'User Selection', +// 6. 'models.table.filterByName': 'Filter by username', +// 7. 'models.table.admin': 'Admin', +// 8. 'models.table.noselected': 'No users selected', +// 9. 'models.table.users.all': 'All users', +// 10. 'models.table.users.selected': 'Selected users', +// 11. 'models.table.nouserFound': 'No users found' // ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/apikeys.ts b/src/locales/zh-CN/apikeys.ts index d5fcee61..185af90c 100644 --- a/src/locales/zh-CN/apikeys.ts +++ b/src/locales/zh-CN/apikeys.ts @@ -11,5 +11,8 @@ export default { 'apikeys.form.expiration.1month': '1个月', 'apikeys.form.expiration.6months': '6个月', 'apikeys.form.expiration.never': '永不过期', - 'apikeys.table.bindModels': '绑定模型' + 'apikeys.table.bindModels': '模型访问', + 'apikeys.models.all': '所有模型', + 'apikeys.models.selected': '指定模型', + 'apikeys.models.noModelsFound': '未找到模型' }; diff --git a/src/locales/zh-CN/models.ts b/src/locales/zh-CN/models.ts index 778a5b24..73919256 100644 --- a/src/locales/zh-CN/models.ts +++ b/src/locales/zh-CN/models.ts @@ -160,5 +160,16 @@ export default { 'models.form.enableSpeculativeDecoding': '启用推测解码', 'models.form.check.clusterUnavailable': '当前集群不可用', 'models.form.check.otherClustersAvailable': - '可用的集群有: {clusters}。请切换集群。' + '可用的集群有: {clusters}。请切换集群。', + 'models.button.accessSettings': '访问设置', + 'models.table.accessScope': '访问范围', + 'models.table.accessScope.all': '所有用户', + 'models.table.accessScope.selected': '指定用户', + 'models.table.userSelection': '用户选择', + 'models.table.filterByName': '按用户名筛选', + 'models.table.admin': '管理员', + 'models.table.noselected': '未选择用户', + 'models.table.users.all': '所有用户', + 'models.table.users.selected': '已选用户', + 'models.table.nouserFound': '未找到用户' }; diff --git a/src/pages/_components/select-panel/index.tsx b/src/pages/_components/select-panel/index.tsx index bafc8a5a..2dbb21b1 100644 --- a/src/pages/_components/select-panel/index.tsx +++ b/src/pages/_components/select-panel/index.tsx @@ -1,4 +1,5 @@ import { SearchOutlined } from '@ant-design/icons'; +import { useIntl } from '@umijs/max'; import { Button, Checkbox, Empty, Input } from 'antd'; import React, { useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; @@ -34,6 +35,7 @@ interface SelectPanelProps { leftWidth?: number; options: Array<{ key: string; title: string }>; selectedKeys: string[]; + notFoundContent?: React.ReactNode; onSelectChange: (selectedKeys: string[]) => void; } @@ -43,8 +45,10 @@ const SelectPanel: React.FC = ({ options, selectedKeys, searchPlaceholder, + notFoundContent, onSelectChange }) => { + const intl = useIntl(); const [indeterminate, setIndeterminate] = React.useState(false); const [checkAll, setCheckAll] = React.useState(false); const [searchText, setSearchText] = useState(''); @@ -162,7 +166,12 @@ const SelectPanel: React.FC = ({ indeterminate={indeterminate} onChange={handleCheckAllChange} > - {selectedKeys.length} selected + + {intl.formatMessage( + { id: 'common.select.count' }, + { count: selectedKeys.length } + )} + = ({ } size="small" allowClear + status={'null' as any} placeholder={searchPlaceholder} style={{ width: 300, @@ -192,7 +202,7 @@ const SelectPanel: React.FC = ({ ) : ( )} diff --git a/src/pages/_components/transfer.tsx b/src/pages/_components/transfer.tsx index d762325f..2c531dfd 100644 --- a/src/pages/_components/transfer.tsx +++ b/src/pages/_components/transfer.tsx @@ -1,4 +1,5 @@ import { MoreOutlined } from '@ant-design/icons'; +import { useIntl } from '@umijs/max'; import { Transfer, TransferProps } from 'antd'; import styled from 'styled-components'; @@ -72,6 +73,8 @@ interface TransferInnerProps extends TransferProps { } const TransferInner: React.FC = (props) => { + const intl = useIntl(); + const renderAllLabels = (info: { selectedCount: number; totalCount: number; @@ -79,7 +82,10 @@ const TransferInner: React.FC = (props) => { if (info.selectedCount) { return ( - {info.selectedCount} selected + {intl.formatMessage( + { id: 'common.select.count' }, + { count: info.selectedCount } + )} ); } diff --git a/src/pages/api-keys/components/add-apikey-modal/allow-models.tsx b/src/pages/api-keys/components/add-apikey-modal/allow-models.tsx index 4de2b13b..78668879 100644 --- a/src/pages/api-keys/components/add-apikey-modal/allow-models.tsx +++ b/src/pages/api-keys/components/add-apikey-modal/allow-models.tsx @@ -1,7 +1,9 @@ import { PageAction } from '@/config'; import { PageActionType } from '@/config/types'; +import useAppUtils from '@/hooks/use-app-utils'; import SelectPanel from '@/pages/_components/select-panel'; import { queryModelsList } from '@/pages/llmodels/apis'; +import { useIntl } from '@umijs/max'; import { Divider, Form, Radio } from 'antd'; import { useEffect, useState } from 'react'; import styled from 'styled-components'; @@ -18,6 +20,8 @@ const AllowModelsForm: React.FC<{ currentData?: Partial | null; action: PageActionType; }> = ({ currentData, action }) => { + const intl = useIntl(); + const { getRuleMessage } = useAppUtils(); const form = Form.useFormInstance(); const allowedModelNames = Form.useWatch( 'allowed_model_names', @@ -57,7 +61,7 @@ const AllowModelsForm: React.FC<{ return (
- + -