diff --git a/README.cn.md b/README.cn.md index 3e5ca3bcf..e677450f7 100644 --- a/README.cn.md +++ b/README.cn.md @@ -47,7 +47,7 @@ Coze Loop 通过提供全生命周期的管理能力,帮助开发者更高效 * [Prompt 开发与调试](https://loop.coze.cn/open/docs/cozeloop/create-prompt):Coze Loop 提供了完整的提示词开发流程。 * [评测](https://loop.coze.cn/open/docs/cozeloop/evaluation-quick-start):Coze Loop 的评测功能提供标准评测数据管理、自动化评估引擎和综合的实验结果统计。 * [Trace 上报与查询](https://loop.coze.cn/open/docs/cozeloop/trace_integrate):Coze Loop 支持对平台上创建的 Prompt 调试的 Trace 自动上报,实时追踪每一条 Trace 数据。 -* [开源版使用Coze Loop SDK](https://github.com/coze-dev/cozeloop/wiki/8.-%E5%BC%80%E6%BA%90%E7%89%88%E4%BD%BF%E7%94%A8-CozeLoop-SDK):Coze Loop 三个语言的 [SDK](https://loop.coze.cn/open/docs/CozeLoop/sdk) 均适用于商业版和开源版。对于开源版,开发者只需要初始化时修改部分参数配置。 +* [开源版使用Coze Loop SDK](https://github.com/coze-dev/cozeloop/wiki/8.-%E5%BC%80%E6%BA%90%E7%89%88%E4%BD%BF%E7%94%A8-CozeLoop-SDK):Coze Loop 三个语言的 [SDK](https://loop.coze.cn/open/docs/cozeloop/sdk) 均适用于商业版和开源版。对于开源版,开发者只需要初始化时修改部分参数配置。 ## 开发指南 diff --git a/README.md b/README.md index 9c0f2afd7..894fed3d9 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ English | [中文](README.cn.md) [Coze Loop](https://www.coze.cn/loop) is a developer-oriented, platform-level solution focused on the development and operation of AI agents. It addresses various challenges faced during the AI agent development process, providing full lifecycle management capabilities from development, debugging, evaluation, to monitoring. -Based on the commercial version, Coze Loop introduces a community edition that offers developers free access to core foundational feature modules. By sharing its core technology framework in an open-source model, developers can customize and extend according to business needs, facilitating community co-construction, sharing, and exchange, helping developers participate in AI agent exploration and practice with zero barriers. +Based on the commercial version, Coze Loop introduces an open-source edition that offers developers free access to core foundational feature modules. By sharing its core technology framework in an open-source model, developers can customize and extend according to business needs, facilitating community co-construction, sharing, and exchange, helping developers participate in AI agent exploration and practice with zero barriers. ## What can Coze Loop do? Coze Loop helps developers efficiently develop and operate AI agents by providing full-lifecycle management capabilities. Whether it's prompt engineering, AI agent evaluation, or monitoring and optimization after deployment, Coze Loop offers powerful tools and intelligent support, significantly simplifying the AI agent development process and improving the performance and stability of AI agents. @@ -42,19 +42,19 @@ Coze Loop helps developers efficiently develop and operate AI agents by providin ## Quickstart Refer to the [Quickstart](https://github.com/coze-dev/CozeLoop/wiki/2.-Quickstart) to learn how to install and deploy the latest version of Coze Loop. -## Using CozeLoop Community Edition +## Using Coze Loop Open-source Edition * [Prompt development and debugging](https://loop.coze.cn/open/docs/cozeloop/create-prompt): Coze Loop provides a complete prompt development workflow. * [Evaluation](https://loop.coze.cn/open/docs/cozeloop/evaluation-quick-start): Coze Loop's evaluation functionality offers standardized evaluation data management, automated assessment engines, and comprehensive experimental result statistics. * [Trace reporting and querying](https://loop.coze.cn/open/docs/cozeloop/trace_integrate): Coze Loop supports automatic Trace reporting for prompt debugging conducted on the platform, enabling real-time tracking of each Trace data. -* [Community Edition usage of the Coze Loop SDK](https://github.com/coze-dev/cozeLoop/wiki/8.-Open-source-edition-uses-CozeLoop-SDK): The Coze Loop SDK in three languages is suitable for both commercial and community editions. For the Community Edition, developers only need to modify some parameter configurations during initialization. +* [Open-source Edition usage of the Coze Loop SDK](https://github.com/coze-dev/cozeLoop/wiki/8.-Open-source-edition-uses-CozeLoop-SDK): The Coze Loop SDK in three languages is suitable for both commercial and open-source editions. For the Open-source Edition, developers only need to modify some parameter configurations during initialization. ## Developer guide -* [System architecture](https://github.com/coze-dev/CozeLoop/wiki/3.-Architecture): Learn about the technical architecture and core components of Coze Loop Community Edition. -* [Startup mode](https://github.com/coze-dev/CozeLoop/wiki/4.-Service-startup-modes): When installing and deploying Coze Loop Community Edition, the default development mode allows backend file modifications without requiring service redeployment. -* [Model configuration](https://github.com/coze-dev/CozeLoop/wiki/5.-Model-configuration): Coze Loop Community Edition supports various LLM models through the Eino framework. Refer to this document to view the supported model list and learn how to configure models. -* [Code development and testing](https://github.com/coze-dev/CozeLoop/wiki/6.-Code-development-and-testing): Learn how to perform secondary development and testing based on Coze Loop Community Edition. +* [System architecture](https://github.com/coze-dev/CozeLoop/wiki/3.-Architecture): Learn about the technical architecture and core components of Coze Loop Open-source Edition. +* [Startup mode](https://github.com/coze-dev/CozeLoop/wiki/4.-Service-startup-modes): When installing and deploying Coze Loop Open-source Edition, the default development mode allows backend file modifications without requiring service redeployment. +* [Model configuration](https://github.com/coze-dev/CozeLoop/wiki/5.-Model-configuration): Coze Loop Open-source Edition supports various LLM models through the Eino framework. Refer to this document to view the supported model list and learn how to configure models. +* [Code development and testing](https://github.com/coze-dev/CozeLoop/wiki/6.-Code-development-and-testing): Learn how to perform secondary development and testing based on Coze Loop Open-source Edition. * [Fault troubleshooting](https://github.com/coze-dev/CozeLoop/wiki/7.-Troubleshooting): Learn how to check container status and system logs. ## License diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index 010f6d8ad..0a47365f0 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -1400,6 +1400,9 @@ importers: '@cozeloop/i18n-adapter': specifier: workspace:* version: link:../i18n + '@cozeloop/stores': + specifier: workspace:* + version: link:../stores ahooks: specifier: 3.7.8 version: 3.7.8(patch_hash=sa4ddrxdk2yhjzudeck6u5ww3i)(react@18.2.0) @@ -1492,6 +1495,9 @@ importers: '@cozeloop/components': specifier: workspace:* version: link:../components + '@cozeloop/i18n-adapter': + specifier: workspace:* + version: link:../i18n classnames: specifier: ^2.3.2 version: 2.5.1 @@ -2172,6 +2178,9 @@ importers: '@formatjs/icu-messageformat-parser': specifier: ^2.11.2 version: 2.11.2 + '@types/react': + specifier: 18.2.37 + version: 18.2.37 '@vitest/coverage-v8': specifier: ~3.0.5 version: 3.0.9(vitest@3.0.9) @@ -2892,6 +2901,9 @@ importers: '@cozeloop/components': specifier: workspace:* version: link:../components + '@cozeloop/i18n-adapter': + specifier: workspace:* + version: link:../i18n '@cozeloop/observation-component-adapter': specifier: workspace:* version: link:../observation/trace-detail @@ -3095,6 +3107,9 @@ importers: ../../../frontend/packages/cozeloop/stores: dependencies: + '@cozeloop/i18n-adapter': + specifier: workspace:* + version: link:../i18n '@cozeloop/toolkit': specifier: workspace:* version: link:../toolkit diff --git a/conf/default/app/runtime/model_config.yaml b/conf/default/app/runtime/model_config.yaml index ff23625ab..2aab6ca79 100644 --- a/conf/default/app/runtime/model_config.yaml +++ b/conf/default/app/runtime/model_config.yaml @@ -9,53 +9,23 @@ models: param_config: param_schemas: - name: "temperature" - label: "Generation Randomness" + label: "temperature" desc: "Increasing temperature makes model output more diverse and creative, while decreasing it makes output more focused on instructions but less diverse. It's recommended not to adjust this simultaneously with 'Top p'." type: "float" min: "0" max: "1.0" default_val: "0.7" - name: "max_tokens" - label: "Maximum Response Length" + label: "max_tokens" desc: "Controls the maximum number of tokens in model output. Typically, 100 tokens equals about 150 Chinese characters." type: "int" min: "1" max: "4096" default_val: "2048" - name: "top_p" - label: "Nucleus Sampling Probability" + label: "top_p" desc: "Selects the minimum token set with cumulative probability reaching top_p during generation, excluding tokens outside the set, balancing diversity and reasonableness." type: "float" min: "0.001" max: "1.0" default_val: "0.7" - - id: 2 - name: "openapi" - frame: "eino" - protocol: "openai" - protocol_config: - api_key: "***" - model: "***" - param_config: - param_schemas: - - name: "temperature" - label: "Generation Randomness" - desc: "Increasing temperature makes model output more diverse and creative, while decreasing it makes output more focused on instructions but less diverse. It's recommended not to adjust this simultaneously with 'Top p'." - type: "float" - min: "0" - max: "1.0" - default_val: "0.7" - - name: "max_tokens" - label: "Maximum Response Length" - desc: "Controls the maximum number of tokens in model output. Typically, 100 tokens equals about 150 Chinese characters." - type: "int" - min: "1" - max: "4096" - default_val: "2048" - - name: "top_p" - label: "Nucleus Sampling Probability" - desc: "Selects the minimum token set with cumulative probability reaching top_p during generation, excluding tokens outside the set, balancing diversity and reasonableness." - type: "float" - min: "0.001" - max: "1.0" - default_val: "0.7" \ No newline at end of file diff --git a/frontend/apps/cozeloop/rsbuild.config.ts b/frontend/apps/cozeloop/rsbuild.config.ts index f9f95c5c0..4984fa00d 100644 --- a/frontend/apps/cozeloop/rsbuild.config.ts +++ b/frontend/apps/cozeloop/rsbuild.config.ts @@ -17,7 +17,7 @@ export default createRsbuildConfig({ }, }, html: { - title: '扣子罗盘', + title: 'Coze Loop', template: './src/assets/template.html', favicon: './src/assets/images/coze.svg', crossorigin: 'anonymous', diff --git a/frontend/apps/cozeloop/src/app.tsx b/frontend/apps/cozeloop/src/app.tsx index 143d3e8d0..817c5ea91 100644 --- a/frontend/apps/cozeloop/src/app.tsx +++ b/frontend/apps/cozeloop/src/app.tsx @@ -3,23 +3,24 @@ import { RouterProvider, createBrowserRouter } from 'react-router-dom'; import { Suspense } from 'react'; -import { I18n } from '@cozeloop/i18n-adapter'; import { PageLoading } from '@cozeloop/components'; -import { zh_CN } from '@coze-arch/coze-design/locales'; -import { CDLocaleProvider } from '@coze-arch/coze-design'; import { routeConfig } from './routes'; +import { useSetupI18n } from './hooks'; +import { LocaleProvider } from './components'; import './index.css'; const router = createBrowserRouter(routeConfig); export function App() { + useSetupI18n(); + return ( }> - + - + ); } diff --git a/frontend/apps/cozeloop/src/assets/images/discord.svg b/frontend/apps/cozeloop/src/assets/images/discord.svg new file mode 100644 index 000000000..7b6e0b38e --- /dev/null +++ b/frontend/apps/cozeloop/src/assets/images/discord.svg @@ -0,0 +1 @@ + diff --git a/frontend/apps/cozeloop/src/assets/images/lark.svg b/frontend/apps/cozeloop/src/assets/images/lark.svg new file mode 100644 index 000000000..9fb6a6941 --- /dev/null +++ b/frontend/apps/cozeloop/src/assets/images/lark.svg @@ -0,0 +1,9 @@ + + + + + diff --git a/frontend/apps/cozeloop/src/components/basic-layout/index.tsx b/frontend/apps/cozeloop/src/components/basic-layout/index.tsx index 4a3625b5d..80d456018 100644 --- a/frontend/apps/cozeloop/src/components/basic-layout/index.tsx +++ b/frontend/apps/cozeloop/src/components/basic-layout/index.tsx @@ -4,6 +4,7 @@ import { Outlet, useLocation, useNavigate } from 'react-router-dom'; import { ErrorBoundary } from 'react-error-boundary'; import { Suspense } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { PageError, PageLoading, PageNotFound } from '@cozeloop/components'; import { useSpaceStore } from '@cozeloop/account'; import { Button } from '@coze-arch/coze-design'; @@ -22,7 +23,7 @@ export function BasicLayout() { switch (status) { case SetupSpaceStatus.NOT_FOUND: return ( - + ); case SetupSpaceStatus.FETCH_ERROR: return ( - + ); diff --git a/frontend/apps/cozeloop/src/components/breadcrumb/index.tsx b/frontend/apps/cozeloop/src/components/breadcrumb/index.tsx index db117ce0f..8d8dee00f 100644 --- a/frontend/apps/cozeloop/src/components/breadcrumb/index.tsx +++ b/frontend/apps/cozeloop/src/components/breadcrumb/index.tsx @@ -5,6 +5,7 @@ import { useEffect, useState } from 'react'; import { useShallow } from 'zustand/react/shallow'; import { useUIStore, type BreadcrumbItemConfig } from '@cozeloop/stores'; import { useApp, useNavigateModule } from '@cozeloop/biz-hooks-adapter'; +import { SwitchLang } from '@cozeloop/auth-pages'; import { Breadcrumb } from '@coze-arch/coze-design'; import { useMenuConfig } from '../navbar/menu-config'; @@ -51,7 +52,7 @@ export function MainBreadcrumb() { }, [breadcrumbConfig]); return ( -
+
/
} > @@ -72,6 +73,7 @@ export function MainBreadcrumb() { ))} +
); } diff --git a/frontend/apps/cozeloop/src/components/index.ts b/frontend/apps/cozeloop/src/components/index.ts index 97ca4acde..df4e12411 100644 --- a/frontend/apps/cozeloop/src/components/index.ts +++ b/frontend/apps/cozeloop/src/components/index.ts @@ -1,3 +1,4 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 export { BasicLayout } from './basic-layout'; +export { LocaleProvider } from './locale-provider'; diff --git a/frontend/apps/cozeloop/src/components/locale-provider.tsx b/frontend/apps/cozeloop/src/components/locale-provider.tsx new file mode 100644 index 000000000..6b4a29ba0 --- /dev/null +++ b/frontend/apps/cozeloop/src/components/locale-provider.tsx @@ -0,0 +1,42 @@ +// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates +// SPDX-License-Identifier: Apache-2.0 +import { type PropsWithChildren } from 'react'; + +import { useI18nStore } from '@cozeloop/stores'; +import { I18n } from '@cozeloop/i18n-adapter'; +import { en_US, zh_CN } from '@coze-arch/coze-design/locales'; +import { + CDLocaleProvider, + ConfigProvider, + enUS, + zhCN, +} from '@coze-arch/coze-design'; + +function langToLocale(lang: string) { + if (!lang) { + return { locale: zhCN, cdLocale: zh_CN }; + } + switch (lang) { + case 'zh': + case 'zh-CN': + return { locale: zhCN, cdLocale: zh_CN }; + default: + return { locale: enUS, cdLocale: en_US }; + } +} + +export function LocaleProvider({ children }: PropsWithChildren) { + const lang = useI18nStore(s => s.lng); + const { locale, cdLocale } = langToLocale(lang); + + return ( + + I18n.unsafeT(key) }} + > + {children} + + + ); +} diff --git a/frontend/apps/cozeloop/src/components/navbar/footer-menus.tsx b/frontend/apps/cozeloop/src/components/navbar/footer-menus.tsx index d6b065817..dd2ce0f8a 100644 --- a/frontend/apps/cozeloop/src/components/navbar/footer-menus.tsx +++ b/frontend/apps/cozeloop/src/components/navbar/footer-menus.tsx @@ -3,6 +3,7 @@ import { type ReactNode, useState } from 'react'; import cls from 'classnames'; +import { I18n } from '@cozeloop/i18n-adapter'; import { IconCozDocument, IconCozArrowDown, @@ -15,8 +16,10 @@ import { COZELOOP_DOC_URL, COZELOOP_LARK_GROUP_URL, COZELOOP_GITHUB_URL, + COZELOOP_DISCORD_URL, } from '@/constants'; import { ReactComponent as IconGithub } from '@/assets/images/github.svg'; +import { ReactComponent as IconDiscord } from '@/assets/images/discord.svg'; import { ItemWithLink } from './item-with-link'; @@ -37,13 +40,13 @@ export function FooterMenus({ isCollapsed, isHovered }: Props) { const [isShow, setIsShow] = useState(true); const menuItems: MenuItem[] = [ { - text: '文档', + text: I18n.t('document'), key: 'actions/doc', icon: , onClick: () => window.open(COZELOOP_DOC_URL), }, { - text: '飞书群', + text: I18n.t('lark_group'), key: 'actions/lark', icon: , onClick: () => window.open(COZELOOP_LARK_GROUP_URL), @@ -54,6 +57,12 @@ export function FooterMenus({ isCollapsed, isHovered }: Props) { icon: , onClick: () => window.open(COZELOOP_GITHUB_URL), }, + { + text: 'Discord', + key: 'actions/discord', + icon: , + onClick: () => window.open(COZELOOP_DISCORD_URL), + }, ]; return ( diff --git a/frontend/apps/cozeloop/src/components/navbar/menu-config.tsx b/frontend/apps/cozeloop/src/components/navbar/menu-config.tsx index 7e7d87e04..d129d55ec 100644 --- a/frontend/apps/cozeloop/src/components/navbar/menu-config.tsx +++ b/frontend/apps/cozeloop/src/components/navbar/menu-config.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { type ReactNode } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { type Space } from '@cozeloop/api-schema/foundation'; import { IconCozChat, @@ -38,12 +39,12 @@ export function useMenuConfig() { const menuConfig: MenuConfig[] = [ { itemKey: 'pe', - text: 'Prompt 工程', + text: I18n.t('prompt_engineering'), visible: ({ space }) => Boolean(space?.id), items: [ { itemKey: 'pe/prompts', - text: 'Prompt 开发', + text: I18n.t('prompt_development'), icon: , selectedIcon: , }, @@ -57,24 +58,24 @@ export function useMenuConfig() { }, { itemKey: 'evaluation', - text: '评测', + text: I18n.t('evaluation'), visible: ({ space }) => Boolean(space?.id), items: [ { itemKey: 'evaluation/datasets', - text: '评测集', + text: I18n.t('evaluation_set'), icon: , selectedIcon: , }, { itemKey: 'evaluation/evaluators', - text: '评估器', + text: I18n.t('evaluator'), icon: , selectedIcon: , }, { itemKey: 'evaluation/experiments', - text: '实验', + text: I18n.t('experiment'), icon: , selectedIcon: , }, @@ -82,7 +83,7 @@ export function useMenuConfig() { }, { itemKey: 'observation', - text: '观测', + text: I18n.t('observation'), visible: ({ space }) => Boolean(space?.id), items: [ { diff --git a/frontend/apps/cozeloop/src/components/user-info-section/index.tsx b/frontend/apps/cozeloop/src/components/user-info-section/index.tsx index 9c4caeb21..c2d0d3539 100644 --- a/frontend/apps/cozeloop/src/components/user-info-section/index.tsx +++ b/frontend/apps/cozeloop/src/components/user-info-section/index.tsx @@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom'; import { useState } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { AccountSetting } from '@cozeloop/auth-pages'; import { useLogout, useUserStore, useSpaceStore } from '@cozeloop/account'; import { Popover, Modal } from '@coze-arch/coze-design'; @@ -27,9 +28,9 @@ export function UserInfoSection({ isCollapsed }: Props) { switch (action) { case 'logout': Modal.confirm({ - title: '确认要退出登录吗?', - okText: '退出登录', - cancelText: '取消', + title: I18n.t('confirm_logout'), + okText: I18n.t('logout'), + cancelText: I18n.t('cancel'), type: 'modal', autoLoading: true, okButtonProps: { diff --git a/frontend/apps/cozeloop/src/components/user-info-section/settings-menu.tsx b/frontend/apps/cozeloop/src/components/user-info-section/settings-menu.tsx index beef6c2b1..937a12f65 100644 --- a/frontend/apps/cozeloop/src/components/user-info-section/settings-menu.tsx +++ b/frontend/apps/cozeloop/src/components/user-info-section/settings-menu.tsx @@ -1,6 +1,7 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 import classNames from 'classnames'; +import { I18n } from '@cozeloop/i18n-adapter'; import { useBaseURL } from '@cozeloop/biz-hooks-adapter'; import { PERSONAL_ENTERPRISE_ID } from '@cozeloop/account'; import { IconCozExit, IconCozSetting } from '@coze-arch/coze-design/icons'; @@ -18,7 +19,7 @@ export function SettingsMenu({ onAction }: Props) { const menus = [ { icon: , - text: '账户设置', + text: I18n.t('account_settings'), onClick: () => { onAction?.('setting'); }, @@ -26,7 +27,7 @@ export function SettingsMenu({ onAction }: Props) { }, { icon: , - text: '退出登录', + text: I18n.t('logout'), onClick: () => { onAction?.('logout'); }, diff --git a/frontend/apps/cozeloop/src/constants/home.ts b/frontend/apps/cozeloop/src/constants/home.ts index c7b1a99d9..fa5431b4e 100644 --- a/frontend/apps/cozeloop/src/constants/home.ts +++ b/frontend/apps/cozeloop/src/constants/home.ts @@ -13,6 +13,9 @@ export const COZELOOP_DOC_URL = /** github url */ export const COZELOOP_GITHUB_URL = 'https://github.com/coze-dev/cozeloop'; +/** discord url */ +export const COZELOOP_DISCORD_URL = 'https://discord.gg/x8kbtMwrJ2'; + /** lark group url */ export const COZELOOP_LARK_GROUP_URL = 'https://applink.larkoffice.com/client/chat/chatter/add_by_link?link_token=decke114-4486-45de-a7a1-3bc2efd47795'; diff --git a/frontend/apps/cozeloop/src/constants/index.ts b/frontend/apps/cozeloop/src/constants/index.ts index 3bd5f726c..7f6ec1033 100644 --- a/frontend/apps/cozeloop/src/constants/index.ts +++ b/frontend/apps/cozeloop/src/constants/index.ts @@ -7,6 +7,7 @@ export { CONSOLE_PATH, COZELOOP_DOC_URL, COZELOOP_GITHUB_URL, + COZELOOP_DISCORD_URL, COZELOOP_LARK_GROUP_URL, } from './home'; diff --git a/frontend/apps/cozeloop/src/hooks/index.ts b/frontend/apps/cozeloop/src/hooks/index.ts index ef82c1d42..b75c927a2 100644 --- a/frontend/apps/cozeloop/src/hooks/index.ts +++ b/frontend/apps/cozeloop/src/hooks/index.ts @@ -2,3 +2,4 @@ // SPDX-License-Identifier: Apache-2.0 export { useSetupSpace, SetupSpaceStatus } from './use-setup-space'; export { useApiErrorToast } from './use-api-error-toast'; +export { useSetupI18n } from './use-setup-i18n'; diff --git a/frontend/apps/cozeloop/src/hooks/use-setup-i18n.ts b/frontend/apps/cozeloop/src/hooks/use-setup-i18n.ts new file mode 100644 index 000000000..bbf53f5bb --- /dev/null +++ b/frontend/apps/cozeloop/src/hooks/use-setup-i18n.ts @@ -0,0 +1,14 @@ +// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates +// SPDX-License-Identifier: Apache-2.0 +import { useEffect } from 'react'; + +import { useI18nStore } from '@cozeloop/stores'; +import { I18n } from '@cozeloop/i18n-adapter'; + +export function useSetupI18n() { + const setLng = useI18nStore(s => s.setLng); + + useEffect(() => { + setLng(I18n.lang); + }, []); +} diff --git a/frontend/apps/cozeloop/src/routes/space-route.tsx b/frontend/apps/cozeloop/src/routes/space-route.tsx index 4e1afd6d0..ec143a66f 100644 --- a/frontend/apps/cozeloop/src/routes/space-route.tsx +++ b/frontend/apps/cozeloop/src/routes/space-route.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { Navigate } from 'react-router-dom'; +import { I18n } from '@cozeloop/i18n-adapter'; import { PageNoContent } from '@cozeloop/components'; import { useSpaceStore } from '@cozeloop/account'; @@ -13,7 +14,12 @@ export function SpaceRoute({ index }: Props) { const space = useSpaceStore(s => s.space); if (!space?.id) { - return ; + return ( + + ); } const path = index ? `space/${space.id}` : space.id; diff --git a/frontend/cspell.json b/frontend/cspell.json index 34405ba4d..baa0f3fbd 100644 --- a/frontend/cspell.json +++ b/frontend/cspell.json @@ -12,6 +12,7 @@ "cozeloop", "dotenv", "eslintcache", + "Expt", "immer", "pnpmfile", "Popconfirm", @@ -19,9 +20,13 @@ "rspack", "rushstack", "rushx", + "sidesheet", "stylelint", "tailwindcss", "tanstack", + "testrun", + "vchart", + "visactor", "webp", "zustand" ], diff --git a/frontend/packages/cozeloop/auth-pages/package.json b/frontend/packages/cozeloop/auth-pages/package.json index 0ee767483..8c1caabbe 100644 --- a/frontend/packages/cozeloop/auth-pages/package.json +++ b/frontend/packages/cozeloop/auth-pages/package.json @@ -17,6 +17,7 @@ "@cozeloop/account": "workspace:*", "@cozeloop/api-schema": "workspace:*", "@cozeloop/i18n-adapter": "workspace:*", + "@cozeloop/stores": "workspace:*", "ahooks": "^3.7.8", "classnames": "^2.3.2" }, @@ -39,4 +40,3 @@ "react-router-dom": "^6.22.0" } } - diff --git a/frontend/packages/cozeloop/auth-pages/src/components/account-setting/index.tsx b/frontend/packages/cozeloop/auth-pages/src/components/account-setting/index.tsx index deb91f7e6..46e17f498 100644 --- a/frontend/packages/cozeloop/auth-pages/src/components/account-setting/index.tsx +++ b/frontend/packages/cozeloop/auth-pages/src/components/account-setting/index.tsx @@ -3,6 +3,7 @@ import { useState } from 'react'; import cls from 'classnames'; +import { I18n } from '@cozeloop/i18n-adapter'; import { Space, Typography } from '@coze-arch/coze-design'; import { UserInfoPanel } from '../user-info-panel'; @@ -23,8 +24,8 @@ interface Props { export function AccountSetting({ className, activeTab }: Props) { const [tabId, setTabId] = useState(activeTab || 'user-info'); const tabs: Tab[] = [ - { name: '账户设置', key: 'user-info' }, - { name: 'API 授权', key: 'pat' }, + { name: I18n.t('account_settings'), key: 'user-info' }, + { name: I18n.t('api_authorization'), key: 'pat' }, ]; const tabName = tabs.find(it => it.key === tabId)?.name; @@ -47,7 +48,7 @@ export function AccountSetting({ className, activeTab }: Props) { spacing={16} className={s['tab-bar']} > -
{'账户'}
+
{I18n.t('account')}
{tabs.map(({ name, key }) => (
state.lng); + + useEffect(() => { + const title = I18n.t('platform_name'); + if (document.title !== title) { + document.title = title; + } + }, [lng]); + return (
{brand ? ( diff --git a/frontend/packages/cozeloop/auth-pages/src/components/index.ts b/frontend/packages/cozeloop/auth-pages/src/components/index.ts index fd59eb652..4555d7c00 100644 --- a/frontend/packages/cozeloop/auth-pages/src/components/index.ts +++ b/frontend/packages/cozeloop/auth-pages/src/components/index.ts @@ -4,3 +4,4 @@ export { AuthFrame } from './auth-frame'; export { Logo } from './logo'; export { LoginPanel } from './login-panel'; export { AccountSetting } from './account-setting'; +export { SwitchLang } from './switch-lng'; diff --git a/frontend/packages/cozeloop/auth-pages/src/components/login-panel/index.tsx b/frontend/packages/cozeloop/auth-pages/src/components/login-panel/index.tsx index df23c0801..ff80b964b 100644 --- a/frontend/packages/cozeloop/auth-pages/src/components/login-panel/index.tsx +++ b/frontend/packages/cozeloop/auth-pages/src/components/login-panel/index.tsx @@ -2,10 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 import { useState } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { Input, Button, Typography } from '@coze-arch/coze-design'; -import { ReactComponent as IconGithub } from '@/assets/github.svg'; import loopBanner from '@/assets/loop-banner.png'; +import { ReactComponent as IconGithub } from '@/assets/github.svg'; + +import { SwitchLang } from '../switch-lng'; import s from './index.module.less'; @@ -33,25 +36,26 @@ export function LoginPanel({ loading, onLogin, onRegister }: Props) { return (
+
- {'欢迎使用扣子罗盘-开源版'} + {I18n.t('welcome_to_cozeloop')}
-
+
{/*
@@ -78,17 +82,20 @@ export function LoginPanel({ loading, onLogin, onRegister }: Props) { onChange={e => setConsent(Boolean(e.target.checked))} disabled={loading} > - {'请先同意'} - { - e.stopPropagation(); - }} - > - 用户协议 - + {I18n.t('please_agree_first', { + agreement: ( + { + e.stopPropagation(); + }} + > + {I18n.t('user_agreement')} + + ), + })}
*/}
@@ -97,7 +104,7 @@ export function LoginPanel({ loading, onLogin, onRegister }: Props) { ©2025 Coze Loop - 基于开源代码部署 + {I18n.t('deploy_info')} · [] { return [ { - title: I18n.t('coze_api_list1'), + title: I18n.t('name'), dataIndex: 'name', width: 120, render: (name: string) => {name}, }, { - title: I18n.t('coze_api_list3'), + title: I18n.t('create_time'), dataIndex: 'created_at', render: (createTime: number) => getDetailTime(createTime), }, { - title: I18n.t('coze_api_list4'), + title: I18n.t('last_used'), dataIndex: 'last_used_at', render: (lastUseTime: number) => getDetailTime(lastUseTime), }, { - title: I18n.t('expire_time_1'), // 状态 + title: I18n.t('expiration_time'), // 状态 dataIndex: 'expire_at', render: (expireTime: number) => getExpirationTime(expireTime), }, { - title: I18n.t('api_status_1'), + title: I18n.t('status'), dataIndex: 'id', width: 80, render: (_: string, record: PersonalAccessToken) => { const isActive = getStatus(record?.expire_at); return ( - {I18n.t(isActive ? 'api_status_active_1' : 'api_status_expired_1')} + {isActive ? I18n.t('active') : I18n.t('expired')} ); }, }, { - title: I18n.t('coze_api_list5'), + title: I18n.t('operation'), width: 120, render: (_, record) => ( diff --git a/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/index.tsx b/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/index.tsx index 452ea3993..18bf01cd3 100644 --- a/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/index.tsx +++ b/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/index.tsx @@ -58,7 +58,7 @@ export function PatPanel({ className }: Props) { reloadPatList(); setModalData({ visible: false }); Modal.info({ - title: I18n.t('new_pat_1'), + title: I18n.t('new_pat'), footer: false, width: 560, closable: true, @@ -101,17 +101,17 @@ export function PatPanel({ className }: Props) { type="primary" onClick={() => setModalData({ visible: true })} > - {I18n.t('add_new_token_button_1')} + {I18n.t('add_token')}

- {I18n.t('pat_reminder_1')} + {I18n.t('pat_introduction')} - {I18n.t('coze_api_instru')} + {I18n.t('api_instruction')}

-

{I18n.t('pat_reminder_2')}

+

{I18n.t('pat_reminder')}

-

- { - '此令牌仅显示一次。请将此密钥保存在安全且可获取的地方。不要与他人共享,也不要在浏览器或其他客户端代码中暴露它。' - } -

+

{I18n.t('token_show_only_once')}

-
{'名称'}
+
{I18n.t('name')}
{pat?.name}
-
{'过期时间'}
+
{I18n.t('expiration_time')}
{getExpirationTime(pat?.expire_at)}
-
{'令牌'}
+
{I18n.t('token')}
(); const dataOptionsList = getExpirationOptions(); const isCreate = !value; - const modalTitle = - title || isCreate ? I18n.t('add_new_pat_1') : I18n.t('edit_pat_1'); + const modalTitle = title || isCreate ? I18n.t('add_pat') : I18n.t('edit_pat'); const onOk = async () => { const values = await formApi.current?.getValues(); @@ -75,22 +80,19 @@ export function PatModal({
setDuration(v as PatInfo['duration'])} - placeholder={I18n.t('select_expired_time_1')} + placeholder={I18n.t('please_select', { + field: I18n.t('expiration_time'), + })} /> {duration === 'custom' ? ( onDelete?.(pat.id)} diff --git a/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/pat-table.tsx b/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/pat-table.tsx index 31d6a272d..8a3827ff4 100644 --- a/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/pat-table.tsx +++ b/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/pat-table.tsx @@ -34,10 +34,7 @@ export function PatTable({ loading, dataSource, onEdit, onDelete }: Props) { scroll: {}, }} empty={ - + } />
diff --git a/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/utils.ts b/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/utils.ts index aa554cf14..0a1a895f0 100644 --- a/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/utils.ts +++ b/frontend/packages/cozeloop/auth-pages/src/components/pat-panel/utils.ts @@ -39,14 +39,14 @@ export function formatDate( export function getExpirationOptions() { const dataOptionsList = [ - { label: '1天', value: DurationDay.Day1 }, - { label: '30天', value: DurationDay.Day30 }, - { label: '60天', value: DurationDay.Day60 }, - { label: '90天', value: DurationDay.Day90 }, - { label: '180天', value: DurationDay.Day180 }, - { label: '365天', value: DurationDay.Day365 }, - { label: '永久', value: DurationDay.Permanent }, - { label: I18n.t('customize_key_1'), value: 'custom' }, + { label: I18n.t('x_days', { num: 1 }), value: DurationDay.Day1 }, + { label: I18n.t('x_days', { num: 30 }), value: DurationDay.Day30 }, + { label: I18n.t('x_days', { num: 60 }), value: DurationDay.Day60 }, + { label: I18n.t('x_days', { num: 90 }), value: DurationDay.Day90 }, + { label: I18n.t('x_days', { num: 180 }), value: DurationDay.Day180 }, + { label: I18n.t('x_days', { num: 365 }), value: DurationDay.Day365 }, + { label: I18n.t('permanent'), value: DurationDay.Permanent }, + { label: I18n.t('customize'), value: 'custom' }, ]; const newOptions = dataOptionsList.map(item => { const { value } = item; @@ -59,7 +59,7 @@ export function getExpirationOptions() { label: value === DurationDay.Permanent ? 'Permanent' - : I18n.t('expired_time_days_1', { num: Number(value), date }), + : I18n.t('expired_time_days', { num: Number(value), date }), value, }; }); @@ -104,7 +104,7 @@ export function getExpirationTime(v?: number | string) { } if (d === -1) { - return I18n.t('api_status_permanent_1'); + return I18n.t('permanent'); } return formatDate(new Date(d * 1000)); diff --git a/frontend/packages/cozeloop/auth-pages/src/components/switch-lng/index.module.less b/frontend/packages/cozeloop/auth-pages/src/components/switch-lng/index.module.less new file mode 100644 index 000000000..60cbc6ff0 --- /dev/null +++ b/frontend/packages/cozeloop/auth-pages/src/components/switch-lng/index.module.less @@ -0,0 +1,27 @@ +// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates +// SPDX-License-Identifier: Apache-2.0 +.container { + cursor: pointer; + + display: flex; + align-items: center; + + padding: 2px 4px; + + border-radius: 4px; + + &:hover, &:active { + background-color: rgba(var(--coze-bg-5), var(--coze-bg-5-alpha)); + } + + > svg { + font-size: 0; + } +} + +.text { + user-select: none; + margin-left: 4px; + font-size: 13px; + color: var(--coz-fg-primary); +} diff --git a/frontend/packages/cozeloop/auth-pages/src/components/switch-lng/index.tsx b/frontend/packages/cozeloop/auth-pages/src/components/switch-lng/index.tsx new file mode 100644 index 000000000..6843a09f4 --- /dev/null +++ b/frontend/packages/cozeloop/auth-pages/src/components/switch-lng/index.tsx @@ -0,0 +1,47 @@ +// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates +// SPDX-License-Identifier: Apache-2.0 +import cls from 'classnames'; +import { useI18nStore } from '@cozeloop/stores'; +import { I18n } from '@cozeloop/i18n-adapter'; +import { Tooltip } from '@coze-arch/coze-design'; + +import s from './index.module.less'; + +interface Props { + className?: string; +} + +export function SwitchLang({ className }: Props) { + const toggleLangState = useI18nStore(state => state.toggleLng); + const lang = useI18nStore(state => state.lng); + const isEn = lang === 'en-US'; + const toggleLang = () => { + toggleLangState(); + location.reload(); + }; + + return ( + +
+ + {/* A */} + + {/* 文 */} + + +
{isEn ? 'English' : '中文'}
+
+
+ ); +} diff --git a/frontend/packages/cozeloop/auth-pages/src/components/user-info-panel/edit-wrap.tsx b/frontend/packages/cozeloop/auth-pages/src/components/user-info-panel/edit-wrap.tsx index e54ad93e6..b1233ec78 100644 --- a/frontend/packages/cozeloop/auth-pages/src/components/user-info-panel/edit-wrap.tsx +++ b/frontend/packages/cozeloop/auth-pages/src/components/user-info-panel/edit-wrap.tsx @@ -7,6 +7,7 @@ import { IconCozEdit } from '@coze-arch/coze-design/icons'; import { IconButton, Button } from '@coze-arch/coze-design'; import s from './edit-wrap.module.less'; +import { I18n } from '@cozeloop/i18n-adapter'; interface Props { className?: string; @@ -26,8 +27,8 @@ export function EditWrap({ editableComponent, canSave, loading, - cancelText = 'Cancel', - saveText = 'Save', + cancelText = I18n.t('cancel'), + saveText = I18n.t('save'), onSave, onCancel, }: Props) { diff --git a/frontend/packages/cozeloop/auth-pages/src/components/user-info-panel/index.tsx b/frontend/packages/cozeloop/auth-pages/src/components/user-info-panel/index.tsx index 28e3db2b1..7b474e6f5 100644 --- a/frontend/packages/cozeloop/auth-pages/src/components/user-info-panel/index.tsx +++ b/frontend/packages/cozeloop/auth-pages/src/components/user-info-panel/index.tsx @@ -62,7 +62,7 @@ export function UserInfoPanel({ className }: Props) { {userInfo?.nick_name} - + setName(userInfo?.name)} /> - + setNickName(userInfo?.nick_name)} /> - - {userInfo?.email} - + {userInfo?.email}
UID: {userInfo?.user_id}
); diff --git a/frontend/packages/cozeloop/auth-pages/src/index.ts b/frontend/packages/cozeloop/auth-pages/src/index.ts index d3895c642..ed700ad00 100644 --- a/frontend/packages/cozeloop/auth-pages/src/index.ts +++ b/frontend/packages/cozeloop/auth-pages/src/index.ts @@ -1,4 +1,4 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 export { App as default } from './app'; -export { AccountSetting } from './components'; +export { AccountSetting, SwitchLang } from './components'; diff --git a/frontend/packages/cozeloop/auth-pages/src/pages/login-page/index.tsx b/frontend/packages/cozeloop/auth-pages/src/pages/login-page/index.tsx index 104e2dfea..9313b8691 100644 --- a/frontend/packages/cozeloop/auth-pages/src/pages/login-page/index.tsx +++ b/frontend/packages/cozeloop/auth-pages/src/pages/login-page/index.tsx @@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom'; import { useState, useEffect } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { $notification } from '@cozeloop/api-schema'; import { useLogin, useLoginStatus, useRegister } from '@cozeloop/account'; import { Toast } from '@coze-arch/coze-design'; @@ -40,7 +41,7 @@ export function LoginPage() { className: 'api-error-toast', content: ( - {'注册/登录失败,请检查邮箱或密码'} + {I18n.t('register_or_login_failed')} ), }); diff --git a/frontend/packages/cozeloop/auth-pages/tsconfig.misc.json b/frontend/packages/cozeloop/auth-pages/tsconfig.misc.json index 76fce28fb..69cde449f 100644 --- a/frontend/packages/cozeloop/auth-pages/tsconfig.misc.json +++ b/frontend/packages/cozeloop/auth-pages/tsconfig.misc.json @@ -13,7 +13,7 @@ "target": "ES2020", "moduleResolution": "bundler" }, - "include": ["__tests__", "vitest.config.ts", "stories"], + "include": ["__tests__", "vitest.config.ts"], "exclude": ["./dist"], "references": [ { diff --git a/frontend/packages/cozeloop/biz-components/package.json b/frontend/packages/cozeloop/biz-components/package.json index bddfee49c..75b576e97 100644 --- a/frontend/packages/cozeloop/biz-components/package.json +++ b/frontend/packages/cozeloop/biz-components/package.json @@ -14,6 +14,7 @@ "@cozeloop/api-schema": "workspace:*", "@cozeloop/biz-hooks-adapter": "workspace:*", "@cozeloop/components": "workspace:*", + "@cozeloop/i18n-adapter": "workspace:*", "classnames": "^2.3.2", "nanoid": "^4.0.2" }, @@ -37,4 +38,3 @@ "react-dom": ">=18.2.0" } } - diff --git a/frontend/packages/cozeloop/biz-components/src/user-select/index.tsx b/frontend/packages/cozeloop/biz-components/src/user-select/index.tsx index 432721931..c3de2e475 100644 --- a/frontend/packages/cozeloop/biz-components/src/user-select/index.tsx +++ b/frontend/packages/cozeloop/biz-components/src/user-select/index.tsx @@ -1,6 +1,7 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 import cs from 'classnames'; +import { I18n } from '@cozeloop/i18n-adapter'; import { UserProfile } from '@cozeloop/components'; import { useUserInfo } from '@cozeloop/biz-hooks-adapter'; import { Select, type SelectProps, Tag } from '@coze-arch/coze-design'; @@ -26,12 +27,12 @@ export const UserSelect = ({ ), value: userInfo?.user_id_str || '', data: { - user_name: userInfo?.name, + user_name: userInfo?.screen_name || userInfo.name, avatar_url: userInfo?.avatar_url, }, }, @@ -61,7 +62,7 @@ export const UserSelect = ({ +
@@ -237,7 +245,7 @@ export const DatasetImportItemsModal = ({ onCancel(); }} > - 取消 + {I18n.t('Cancel')}
diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-import-items-modal/overwrite-field.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-import-items-modal/overwrite-field.tsx index 3129abe8e..e5bc3f722 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-import-items-modal/overwrite-field.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-import-items-modal/overwrite-field.tsx @@ -1,5 +1,6 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { Modal, Radio, RadioGroup } from '@coze-arch/coze-design'; interface OverWriteFieldProps { @@ -13,10 +14,10 @@ export const OverWriteField = ({ value, onChange }: OverWriteFieldProps) => ( const newValue = e.target.value === 'true'; if (newValue) { Modal.confirm({ - title: '确认选择全量覆盖', - content: '继续导入数据将覆盖现有数据', - okText: '确认', - cancelText: '取消', + title: I18n.t('confirm_select_full_coverage'), + content: I18n.t('continue_will_override_existing_data'), + okText: I18n.t('confirm'), + cancelText: I18n.t('Cancel'), onOk: () => { onChange?.(true); }, @@ -32,7 +33,7 @@ export const OverWriteField = ({ value, onChange }: OverWriteFieldProps) => ( } }} > - 追加数据 - 全量覆盖 + {I18n.t('append_data')} + {I18n.t('overwrite_data')} ); diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-import-items-modal/use-import-progress.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-import-items-modal/use-import-progress.tsx index 4a5117ee4..9a2e042d1 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-import-items-modal/use-import-progress.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-import-items-modal/use-import-progress.tsx @@ -3,6 +3,7 @@ import { useMemo, useState } from 'react'; import { useRequest } from 'ahooks'; +import { I18n } from '@cozeloop/i18n-adapter'; import { useSpace, useDataImportApi } from '@cozeloop/biz-hooks-adapter'; import { JobStatus } from '@cozeloop/api-schema/data'; import { Button, Loading, Modal } from '@coze-arch/coze-design'; @@ -57,7 +58,11 @@ export const useDatasetImportProgress = (onImportSuccess: () => void) => { width={420} title={
- {isFinish ? '执行结果' : '执行中'} + + {isFinish + ? I18n.t('execution_result') + : I18n.t('execution_in_progress')} +
} footer={ @@ -68,7 +73,7 @@ export const useDatasetImportProgress = (onImportSuccess: () => void) => { onImportSuccess(); }} > - 已知晓 + {I18n.t('known')} ) } diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item-expand/use-dataset-item-expand.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item-expand/use-dataset-item-expand.tsx index 53d1897d7..ae0b6cd6d 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item-expand/use-dataset-item-expand.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item-expand/use-dataset-item-expand.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { useState } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { IconCozLoose, IconCozTight } from '@coze-arch/coze-design/icons'; import { Radio, Tooltip } from '@coze-arch/coze-design'; @@ -14,12 +15,12 @@ export const useDatasetItemExpand = () => { value={expand ? 'expand' : 'shrink'} onChange={e => setExpand(e.target.value === 'expand' ? true : false)} > - + - + diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item-panel/index.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item-panel/index.tsx index f68312e62..bf49649a9 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item-panel/index.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item-panel/index.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { useRef, useState } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { GuardPoint, Guard } from '@cozeloop/guard'; import { ResizeSidesheet } from '@cozeloop/components'; import { useSpace } from '@cozeloop/biz-hooks-adapter'; @@ -10,7 +11,10 @@ import { type EvaluationSetItem, } from '@cozeloop/api-schema/evaluation'; import { StoneEvaluationApi } from '@cozeloop/api-schema'; -import { IconCozArrowLeft, IconCozArrowRight } from '@coze-arch/coze-design/icons'; +import { + IconCozArrowLeft, + IconCozArrowRight, +} from '@coze-arch/coze-design/icons'; import { Button, Form, type FormApi, Toast } from '@coze-arch/coze-design'; import IDWithCopy from '../id-with-copy'; @@ -61,7 +65,7 @@ export const DatasetItemPanel = ({ turns: newTurnsData, workspace_id: spaceID, }); - Toast.success('保存成功'); + Toast.success(I18n.t('save_success')); onSave(); } catch (error) { console.error(error); @@ -99,23 +103,23 @@ export const DatasetItemPanel = ({ }} disabled={loading} > - 保存 + {I18n.t('save')} ) : ( )}
} title={
- {isEdit ? '编辑数据项:' : '查看数据项:'} + {isEdit ? I18n.t('edit_data_item') : I18n.t('view_data_item')}
{switchConfig ? ( @@ -129,7 +133,7 @@ export const DatasetItemPanel = ({ switchConfig?.onSwith('pre'); }} > - 上一条 + {I18n.t('prev_item')}
) : null} diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/empty.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/empty.tsx index cfc30819d..1567fd4c4 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/empty.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/empty.tsx @@ -1,10 +1,11 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { IconCozEmpty } from '@coze-arch/coze-design/icons'; export const EmptyDatasetItem = () => (
- 暂无数据 + {I18n.t('no_data')}
); diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/bool/edit.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/bool/edit.tsx index c21625755..4fe997908 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/bool/edit.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/bool/edit.tsx @@ -1,5 +1,6 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { Radio } from '@coze-arch/coze-design'; import { saftJsonParse } from '../../util'; @@ -21,10 +22,10 @@ export const BoolDatasetItemEdit = ({ return (
handleChange(true)}> - 是 + {I18n.t('yes')} handleChange(false)}> - 否 + {I18n.t('no')}
); diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/float/edit.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/float/edit.tsx index 711660eb5..ad0f164cc 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/float/edit.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/float/edit.tsx @@ -1,14 +1,13 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { Input } from '@coze-arch/coze-design'; import { type DatasetItemProps } from '../../type'; -export const FloatDatasetItemEdit = ({ - fieldContent, - onChange, -}: DatasetItemProps) => ( + +export const FloatDatasetItemEdit = ({ fieldContent, onChange }: DatasetItemProps) => ( { diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/integer/edit.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/integer/edit.tsx index 1d60b4c52..8c6f061c5 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/integer/edit.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/integer/edit.tsx @@ -1,5 +1,6 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { Input } from '@coze-arch/coze-design'; import { type DatasetItemProps } from '../../type'; @@ -10,7 +11,7 @@ export const IntegerDatasetItemEdit = ({ }: DatasetItemProps) => ( <> { diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/string/code/index.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/string/code/index.tsx index 6f19bb87e..4b36e590b 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/string/code/index.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/text/string/code/index.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { useState } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { CodeEditor, handleCopy } from '@cozeloop/components'; import { IconCozCopy } from '@coze-arch/coze-design/icons'; import { Button, SemiSelect } from '@coze-arch/coze-design'; @@ -42,7 +43,7 @@ export const CodeDatasetItem = ({ color="primary" size="small" > - 复制 + {I18n.t('copy')}
diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/util.ts b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/util.ts index 6f4173d01..3fd2089fa 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/util.ts +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-item/util.ts @@ -3,6 +3,7 @@ /* eslint-disable @coze-arch/use-error-in-catch */ import JSONBig from 'json-bigint'; import Decimal from 'decimal.js'; +import { I18n } from '@cozeloop/i18n-adapter'; import { type FieldSchema } from '@cozeloop/api-schema/evaluation'; import { ContentType, COLUMN_TYPE_MAP, DataType } from './type'; @@ -113,6 +114,7 @@ export const validateAndFormat = ({ } }; +// eslint-disable-next-line complexity -- skip export const validarDatasetItem = ( value: string, callback: (error?: string) => void, @@ -123,7 +125,7 @@ export const validarDatasetItem = ( return true; } if (!/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/.test(value)) { - callback('请输入数字'); + callback(I18n.t('please_input', { field: I18n.t('number') })); return false; } // 校验value 是否为数字; @@ -136,29 +138,33 @@ export const validarDatasetItem = ( const minValue = minimum ? new Decimal(minimum) : undefined; const maxValue = maximum ? new Decimal(maximum) : undefined; if (minValue && decimalValue.lt(minValue)) { - callback(`请输入大于等于${minimum}的数字`); + callback(I18n.t('input_num_gte', { num: I18n.t('number') })); return false; } if (maxValue && decimalValue.gt(maxValue)) { - callback(`请输入小于等于${maximum}的数字`); + callback(I18n.t('input_num_lte', { num: I18n.t('number') })); return false; } if (type === DataType.Integer && decimalValue.isInteger() === false) { - callback('请输入整数'); + callback(I18n.t('please_input', { field: I18n.t('integer') })); return false; } if (type === DataType.Float && multipleOf) { const multipleOfDecimal = new Decimal(multipleOf); const division = decimalValue.dividedBy(multipleOfDecimal); if (!division.isInteger()) { - callback(`仅支持精确到小数点后${multipleOfDecimal.decimalPlaces()}位`); + callback( + I18n.t('support_precision', { + precision: multipleOfDecimal.decimalPlaces(), + }), + ); return false; } } return true; } catch (error) { - callback('请输入数字'); + callback(I18n.t('please_input', { field: I18n.t('number') })); return false; } }; diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/column-config.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/column-config.tsx index d4f90cefb..a51614c39 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/column-config.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/column-config.tsx @@ -1,6 +1,7 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 import { formatTimestampToString } from '@cozeloop/toolkit'; +import { I18n } from '@cozeloop/i18n-adapter'; import { type ColumnItem, UserProfile } from '@cozeloop/components'; import { type UserInfo, @@ -28,8 +29,8 @@ export const DatasetColumnConfig: Record< ColumnProps > = { name: { - title: '名称', - displayName: '名称', + title: I18n.t('name'), + displayName: I18n.t('name'), key: 'name', disabled: true, dataIndex: 'name', @@ -43,30 +44,30 @@ export const DatasetColumnConfig: Record< size="small" className="!min-w-[70px] !h-[20px] !px-[4px] !font-normal" > - 修改未提交 + {I18n.t('changes_not_submitted')} ) : null}
), }, description: { - title: '描述', - displayName: '描述', + title: I18n.t('description'), + displayName: I18n.t('description'), key: 'description', dataIndex: 'description', width: 170, render: text => {text}, }, columns: { - title: '列名', - displayName: '列名', + title: I18n.t('column_name'), + displayName: I18n.t('column_name'), key: 'columns', width: 300, render: record => , }, item_count: { - title:
数据项
, - displayName: '数据项', + title:
{I18n.t('data_item')}
, + displayName: I18n.t('data_item'), key: 'item_count', dataIndex: 'item_count', width: 100, @@ -77,16 +78,16 @@ export const DatasetColumnConfig: Record< ), }, latest_version: { - title: '最新版本', + title: I18n.t('latest_version'), key: 'latest_version', - displayName: '最新版本', + displayName: I18n.t('latest_version'), dataIndex: 'latest_version', width: 100, render: text => (text ? {text} : '-'), }, updated_by: { - title: '更新人', - displayName: '更新人', + title: I18n.t('updated_person'), + displayName: I18n.t('updated_person'), key: 'updated_by', dataIndex: 'base_info.updated_by', width: 180, @@ -98,9 +99,9 @@ export const DatasetColumnConfig: Record< ), }, update_at: { - title: '更新时间', + title: I18n.t('update_time'), key: 'updated_at', - displayName: '更新时间', + displayName: I18n.t('update_time'), width: 180, dataIndex: 'base_info.updated_at', sorter: true, @@ -115,8 +116,8 @@ export const DatasetColumnConfig: Record< ), }, created_by: { - title: '创建人', - displayName: '创建人', + title: I18n.t('creator'), + displayName: I18n.t('creator'), key: 'created_by', dataIndex: 'base_info.created_by', @@ -129,8 +130,8 @@ export const DatasetColumnConfig: Record< ), }, created_at: { - title: '创建时间', - displayName: '创建时间', + title: I18n.t('create_time'), + displayName: I18n.t('create_time'), key: 'created_at', width: 180, render: (record?: EvaluationSet) => diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/column-name-list-tag.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/column-name-list-tag.tsx index c0aa756cc..f63b437a3 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/column-name-list-tag.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/column-name-list-tag.tsx @@ -1,11 +1,17 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 import cs from 'classnames'; +import { I18n } from '@cozeloop/i18n-adapter'; import { type FieldSchema, type EvaluationSet, } from '@cozeloop/api-schema/evaluation'; -import { Dropdown, OverflowList, Tag, Typography } from '@coze-arch/coze-design'; +import { + Dropdown, + OverflowList, + Tag, + Typography, +} from '@coze-arch/coze-design'; import { getColumnType } from '../dataset-item/util'; import { dataTypeMap } from '../dataset-item/type'; @@ -23,7 +29,7 @@ export const ColumnNameListTag = ({ set }: { set: EvaluationSet }) => { borderBottom: '1px solid var(--semi-color-border)', }} > - + {I18n.t('column')} {items.length} @@ -51,7 +57,7 @@ export const ColumnNameListTag = ({ set }: { set: EvaluationSet }) => {
- 数据类型 + {I18n.t('data_type')} {dataTypeMap[getColumnType(item)]} @@ -59,7 +65,7 @@ export const ColumnNameListTag = ({ set }: { set: EvaluationSet }) => {
- 描述 + {I18n.t('description')} { size: 'large', className: 'w-[420px]', type: 'dialog', - title: '删除评测集', + title: I18n.t('delete_evaluation_set'), content: ( - 确定删除评测集 - - {row.name} - - 吗?此修改将不可逆。 + {I18n.t('confirm_to_delete_evaluation_set', { + name: ( + + {row.name} + + ), + })} ), autoLoading: true, @@ -66,8 +69,8 @@ export const DatasetList = () => { service.refresh(); }, showCancelButton: true, - cancelText: '取消', - okText: '删除', + cancelText: I18n.t('Cancel'), + okText: I18n.t('delete'), }); }; @@ -79,7 +82,7 @@ export const DatasetList = () => { const allColumns: ColumnProps[] = [ ...columns, { - title: '操作', + title: I18n.t('operation'), key: 'actions', width: 100, fixed: 'right', @@ -87,11 +90,11 @@ export const DatasetList = () => { handleDatasetBaseInfoEdit(record), }, { - label: '删除', + label: I18n.t('delete'), type: 'danger', onClick: () => handleDelete(record), disabled: guards.data.readonly, @@ -105,12 +108,12 @@ export const DatasetList = () => { return (
- +
@@ -169,15 +172,17 @@ export const DatasetList = () => { } - title="未能找到相关结果" - description={'请尝试其他关键词或修改筛选项'} + title={I18n.t('failed_to_find_related_results')} + description={I18n.t( + 'try_other_keywords_or_modify_filter_options', + )} /> ) : ( } - title="暂无评测集" - description={'点击右上角新建评测集按钮进行创建'} + title={I18n.t('no_evaluation_dataset')} + description={I18n.t('click_to_create_evaluation_set')} /> ) } diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/list-filter/index.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/list-filter/index.tsx index f67505bea..21c4870e3 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/list-filter/index.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/list-filter/index.tsx @@ -1,6 +1,7 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 import { useDebounceFn } from 'ahooks'; +import { I18n } from '@cozeloop/i18n-adapter'; import { GuardPoint, useGuard } from '@cozeloop/guard'; import { UserSelect } from '@cozeloop/biz-components-adapter'; import { type ListEvaluationSetsRequest } from '@cozeloop/api-schema/evaluation'; @@ -41,7 +42,7 @@ export const ListFilter = ({ filter, setFilter }: ListFilterProps) => { field="name" fieldClassName="!mr-0 !pr-0" className="!w-full" - placeholder="搜索名称" + placeholder={I18n.t('search_name')} prefix={} convert={value => value?.slice(0, 100)} showClear diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/sort-icon.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/sort-icon.tsx index e74928d25..bc230d092 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/sort-icon.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-list/sort-icon.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { type SVGAttributes } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { IconButtonContainer } from '@cozeloop/components'; import { Tooltip } from '@coze-arch/coze-design'; @@ -51,11 +52,11 @@ export default function LoopTableSortIcon({ }: { sortOrder?: 'ascend' | 'descend' | boolean; }) { - let tooltip = '点击升序'; + let tooltip = I18n.t('click_ascending'); if (sortOrder === 'ascend') { - tooltip = '点击降序'; + tooltip = I18n.t('click_descending'); } else if (sortOrder === 'descend') { - tooltip = '点击恢复默认排序'; + tooltip = I18n.t('restore_default_sort'); } return ( diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-version-tag/index.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-version-tag/index.tsx index 3e7f751a1..5de5a8999 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/dataset-version-tag/index.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/dataset-version-tag/index.tsx @@ -1,5 +1,6 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { type Version } from '@cozeloop/components'; import { type EvaluationSet } from '@cozeloop/api-schema/evaluation'; import { Tag } from '@coze-arch/coze-design'; @@ -24,11 +25,11 @@ export const DatasetVersionTag = ({ } return datasetDetail?.change_uncommitted ? ( - 修改未提交 + {I18n.t('changes_not_submitted')} ) : ( - 草稿版本 + {I18n.t('draft_version')} ); }; diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/evaluator-select-card/evaluator-field-card.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/evaluator-select-card/evaluator-field-card.tsx index 1960a89b7..de6da83ac 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/evaluator-select-card/evaluator-field-card.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/evaluator-select-card/evaluator-field-card.tsx @@ -1,9 +1,11 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +/* eslint-disable @coze-arch/max-line-per-function */ import { forwardRef, useImperativeHandle, useState } from 'react'; import classNames from 'classnames'; import { useRequest } from 'ahooks'; +import { I18n } from '@cozeloop/i18n-adapter'; import { useSpace } from '@cozeloop/biz-hooks-adapter'; import { type Evaluator, @@ -82,7 +84,7 @@ function FieldMappingCard({ onClick={e => e.stopPropagation()} className="flex flex-row items-center gap-1 invisible group-hover:visible" > - +
{!isError ? (
- {evaluatorResult?.score} 分 + {I18n.t('x_score', { num: evaluatorResult?.score ?? '-' })} - 得分仅预览效果,非实际结果。 + {I18n.t('score_only_for_preview')}
) : null} @@ -48,7 +51,8 @@ export function EvaluatorTestRunResult({ rows: 3, }} > - {errorMsg || `原因:${evaluatorResult?.reasoning ?? '-'}`} + {errorMsg || + I18n.t('reason_is', { reason: evaluatorResult?.reasoning ?? '-' })}
); diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/evaluator-version-detail.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/evaluator-version-detail.tsx index fbadd5039..4bbd765bc 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/evaluator-version-detail.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/evaluator-version-detail.tsx @@ -3,6 +3,7 @@ import { useState } from 'react'; import classNames from 'classnames'; +import { I18n } from '@cozeloop/i18n-adapter'; import { type EvaluatorVersion } from '@cozeloop/api-schema/evaluation'; import { IconCozArrowRight, IconCozEmpty } from '@coze-arch/coze-design/icons'; import { EmptyState, Loading } from '@coze-arch/coze-design'; @@ -32,7 +33,7 @@ export function EvaluatorVersionDetail({ )} onClick={() => setOpen(pre => !pre)} > - {'Prompt 详情'} + {I18n.t('prompt_detail')}
@@ -56,7 +57,7 @@ export function EvaluatorVersionDetail({ } - title="暂无数据" + title={I18n.t('no_data')} className={emptyStyles['empty-state']} // description="请选择评估器和版本号后再查看" /> diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/model-config-info/index.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/model-config-info/index.tsx index 2757e3717..b7687c9f5 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/model-config-info/index.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/evaluator/model-config-info/index.tsx @@ -1,5 +1,6 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { type ModelConfig } from '@cozeloop/api-schema/evaluation'; import { useGlobalEvalConfig } from '@/stores/eval-global-config'; @@ -9,7 +10,9 @@ export function ModelConfigInfo({ data }: { data?: ModelConfig }) { return ( <> -
{'模型'}
+
+ {I18n.t('model')} +
{ModelConfigEditor && data ? (
- {'输出'} - + {I18n.t('output')} +
- {'得分:'} + {I18n.t('score_is')} {toolsDescription?.score}
- {'原因:'} + + {I18n.t('reason_is', { reason: '' })} + {toolsDescription?.reason}
diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/experiments/contrast-chart/index.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/experiments/contrast-chart/index.tsx index 005f1079b..8839382a6 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/experiments/contrast-chart/index.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/experiments/contrast-chart/index.tsx @@ -5,6 +5,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { isEqual } from 'lodash-es'; import { useRequest } from 'ahooks'; import { type ISpec } from '@visactor/vchart'; +import { I18n } from '@cozeloop/i18n-adapter'; import { type Experiment, type Evaluator, @@ -192,8 +193,8 @@ function EvaluatorChart({ } - title="暂无数据" - description="实验完成后,再刷新重试" + title={I18n.t('no_data')} + description={I18n.t('refresh_after_experiment')} /> ) : ( -
总览
+
{I18n.t('overview')}
@@ -184,7 +185,7 @@ export function DatasetRelatedExperiment({ updateChartConfig('chartType', e.target.value); }} > - + - +
- 已选 {experiments.length} 条数据{' '} + {I18n.t('x_data_item_selected', { num: experiments.length })} { onCancelSelect?.(); }} > - 取消选择 + {I18n.t('unselect')}
@@ -65,10 +66,12 @@ export function ExperimentRowSelectionActions({ return; } Modal.confirm({ - title: '批量删除实验', - content: `确认批量删除 ${experiments.length} 条实验数据吗?此修改将不可逆。`, - okText: '删除', - cancelText: '取消', + title: I18n.t('batch_delete_experiment'), + content: I18n.t('confirm_batch_delete_x_experiment', { + num: experiments.length, + }), + okText: I18n.t('delete'), + cancelText: I18n.t('Cancel'), okButtonColor: 'red', width: 420, autoLoading: true, @@ -82,7 +85,7 @@ export function ExperimentRowSelectionActions({ }); }} > - 删除 + {I18n.t('delete')} diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/experiments/previews/experiment-list-empty-state.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/experiments/previews/experiment-list-empty-state.tsx index bc5d8d2c7..73ee2ae08 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/experiments/previews/experiment-list-empty-state.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/experiments/previews/experiment-list-empty-state.tsx @@ -1,5 +1,6 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { IconCozIllusAdd } from '@coze-arch/coze-design/illustrations'; import { EmptyState } from '@coze-arch/coze-design'; @@ -12,11 +13,15 @@ export function ExperimentListEmptyState({ } - title={hasFilterCondition ? '未能找到相关结果' : '暂无实验'} + title={ + hasFilterCondition + ? I18n.t('failed_to_find_related_results') + : I18n.t('no_experiment') + } description={ hasFilterCondition - ? '请尝试其他关键词或修改筛选项' - : '点击右上角新建实验按钮进行创建' + ? I18n.t('try_other_keywords_or_modify_filter_options') + : I18n.t('click_to_create_experiment') } /> ); diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/experiments/previews/experiment-run-status.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/experiments/previews/experiment-run-status.tsx index c43ff17d4..5f22f556a 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/experiments/previews/experiment-run-status.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/experiments/previews/experiment-run-status.tsx @@ -1,5 +1,6 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { type Experiment, ExptStatus } from '@cozeloop/api-schema/evaluation'; import { Divider, Popover, Tag, type TagProps } from '@coze-arch/coze-design'; @@ -71,21 +72,23 @@ export function ExperimentRunStatus({ position="top" content={
-
总条数 {totalCount || 0}
- 成功 {success_turn_cnt} + {I18n.t('total')} {totalCount || 0} +
+
+ {I18n.t('success')} {success_turn_cnt} - 失败 {fail_turn_cnt} + {I18n.t('failure')} {fail_turn_cnt} {terminated_turn_cnt ? ( <> - 中止 {terminated_turn_cnt} + {I18n.t('abort')} {terminated_turn_cnt} - 执行中 {processing_turn_cnt} + {I18n.t('execution_in_progress')} {processing_turn_cnt} ) : null} - 待执行 {pending_turn_cnt} + {I18n.t('to_be_executed')} {pending_turn_cnt}
} diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/experiments/selectors/evaluator-select-local-data.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/experiments/selectors/evaluator-select-local-data.tsx index ee66df70a..bc75d48b0 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/experiments/selectors/evaluator-select-local-data.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/experiments/selectors/evaluator-select-local-data.tsx @@ -1,6 +1,7 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 import cls from 'classnames'; +import { I18n } from '@cozeloop/i18n-adapter'; import { type Evaluator } from '@cozeloop/api-schema/evaluation'; import { Select, type SelectProps } from '@coze-arch/coze-design'; @@ -16,8 +17,8 @@ export function EvaluatorSelectLocalData({ }: SelectProps & { evaluators?: Evaluator[]; showVersion?: boolean }) { return ( ; + return ( + + ); } function NumberSetter(props: DataTypeSetterProps) { const { value, onChange, ...rest } = props; return ( = {enableLinkJump ? ( - +
) : null} {enableLinkJump ? ( - +
diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/previews/evaluator-preview.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/previews/evaluator-preview.tsx index 3ff73371f..b17fe080c 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/previews/evaluator-preview.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/previews/evaluator-preview.tsx @@ -1,6 +1,7 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 import classNames from 'classnames'; +import { I18n } from '@cozeloop/i18n-adapter'; import { JumpIconButton } from '@cozeloop/components'; import { useBaseURL } from '@cozeloop/biz-hooks-adapter'; import { type Evaluator } from '@cozeloop/api-schema/evaluation'; @@ -59,7 +60,7 @@ export function EvaluatorPreview({ ) : null} {enableLinkJump ? ( - +
- {'新建评测集'} + {I18n.t('new_evaluation_set')}
) : null diff --git a/frontend/packages/cozeloop/evaluate-components/src/components/selectors/evaluate-set-version-select.tsx b/frontend/packages/cozeloop/evaluate-components/src/components/selectors/evaluate-set-version-select.tsx index 2e02072d5..e1f2f2a7c 100644 --- a/frontend/packages/cozeloop/evaluate-components/src/components/selectors/evaluate-set-version-select.tsx +++ b/frontend/packages/cozeloop/evaluate-components/src/components/selectors/evaluate-set-version-select.tsx @@ -7,6 +7,7 @@ import { StoneEvaluationApi } from '@cozeloop/api-schema'; import { type FormSelect, Typography } from '@coze-arch/coze-design'; import NoVersionJumper from '../common/no-version-jumper'; +import { I18n } from '@cozeloop/i18n-adapter'; export function EvaluateSetVersionSelect({ evaluationSetId, @@ -73,7 +74,9 @@ export function EvaluateSetVersionSelect({ return ( { const item: EvaluationSet = { id: createId(), - name: `百科知识数据集 ${index}`, + name: I18n.t('pedia_dataset', { index }), base_info: { created_at: new Date().toLocaleString(), created_by: { @@ -133,7 +134,7 @@ export async function listEvaluationSetVersions( const item: EvaluationSetVersion = { id: createId(), version: `0.0.${index + 1}`, - description: '版本描述', + description: I18n.t('version_description'), }; return item; }); diff --git a/frontend/packages/cozeloop/evaluate/src/components/mapping-item-field/index.tsx b/frontend/packages/cozeloop/evaluate/src/components/mapping-item-field/index.tsx index d962593a0..eb9e84f97 100644 --- a/frontend/packages/cozeloop/evaluate/src/components/mapping-item-field/index.tsx +++ b/frontend/packages/cozeloop/evaluate/src/components/mapping-item-field/index.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { type FC } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { EqualItem, ReadonlyItem, @@ -74,7 +75,7 @@ export const MappingItemField: FC = 请选择模型 + {I18n.t('choose_model')} )}
{props.disabled ? (
- {'查看参数'} + {I18n.t('check_parameters')}
) : ( diff --git a/frontend/packages/cozeloop/evaluate/src/pages/dataset/detail/index.tsx b/frontend/packages/cozeloop/evaluate/src/pages/dataset/detail/index.tsx index fcc795333..a532562bb 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/dataset/detail/index.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/dataset/detail/index.tsx @@ -15,6 +15,7 @@ import { type Version } from '@cozeloop/components'; import { useSpace } from '@cozeloop/biz-hooks-adapter'; import { useBreadcrumb } from '@cozeloop/base-hooks'; import { Layout, Loading, Tabs } from '@coze-arch/coze-design'; +import { I18n } from '@cozeloop/i18n-adapter'; enum TabKey { EVAL = 'eval', @@ -52,7 +53,7 @@ export default function EvaluateSetDetailPage() { itemKey={TabKey.EVAL} tab={ <> - 评测集 + {I18n.t('evaluation_set')} ) : null} - + - {'调试'} + {I18n.t('debug')} {debugValue ? ( - {'预览与调试'} - + {I18n.t('preview_and_debug')} +
@@ -144,7 +154,7 @@ export function DebugModal({
- {'配置信息'} + {I18n.t('config_info')}
- {'构造测试数据'} + {I18n.t('construct_test_data')}
{variables.length ? (
@@ -194,7 +204,7 @@ export function DebugModal({ ) : ( )} @@ -210,7 +220,7 @@ export function DebugModal({ ); }} > - {'清空'} + {I18n.t('clear')} - {'运行'} + {I18n.t('run')}
@@ -236,14 +246,14 @@ export function DebugModal({ ) : null}
- {'内容由AI生成,无法确保真实准确,仅供参考。'} + {I18n.t('generated_by_ai_tip')}
) : ( } - title="评估器缺少输入" + title={I18n.t('evaluator_lacks_input')} /> )}
diff --git a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/evaluator-detail.tsx b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/evaluator-detail.tsx index 0112f84aa..357c5b060 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/evaluator-detail.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/evaluator-detail.tsx @@ -6,6 +6,7 @@ import { useEffect, useRef, useState } from 'react'; import { set } from 'lodash-es'; import { useRequest } from 'ahooks'; +import { I18n } from '@cozeloop/i18n-adapter'; import { GuardPoint, Guard } from '@cozeloop/guard'; import { sourceNameRuleValidator } from '@cozeloop/evaluate-components'; import { RouteBackAction } from '@cozeloop/components'; @@ -41,18 +42,18 @@ function EvaluatorCreatePage() { useEffect(() => { if (blocker.state === 'blocked') { Modal.warning({ - title: '信息未保存', - content: '离开当前页面,信息将不被保存。', - cancelText: '取消', + title: I18n.t('information_unsaved'), + content: I18n.t('leave_page_tip'), + cancelText: I18n.t('Cancel'), onCancel: blocker.reset, - okText: '确认', + okText: I18n.t('confirm'), onOk: blocker.proceed, }); } }, [blocker.state]); useBreadcrumb({ - text: '新建评估器', + text: I18n.t('new_evaluator'), }); const formRef = useRef(null); @@ -111,17 +112,20 @@ function EvaluatorCreatePage() { }} >
- {'基础信息'} + {I18n.t('basic_info')}
- {'新建评估器'} + {I18n.t('new_evaluator')} {sourceService.loading ? ( @@ -178,7 +184,7 @@ function EvaluatorCreatePage() { /> diff --git a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/prompt-config-field.tsx b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/prompt-config-field.tsx index 2c6a01608..1e2b8311f 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/prompt-config-field.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/prompt-config-field.tsx @@ -1,5 +1,7 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; + import { ConfigContent } from './config-content'; interface Props { @@ -11,7 +13,7 @@ export function PromptConfigField({ disabled, refreshEditorModelKey }: Props) { return ( <>
- {'配置信息'} + {I18n.t('config_info')}
} onClick={() => setTemplateVisible(true)} > - {`选择模板${ + {`${I18n.t('select_template')}${ promptEvaluator?.prompt_template_name ? `(${promptEvaluator.prompt_template_name})` : '' @@ -125,13 +126,13 @@ export function PromptField({ icon={} disabled={disabled} > - {'清空'} + {I18n.t('clear')} ) : ( { promptEvaluatorFieldApi.setValue({ @@ -156,7 +157,7 @@ export function PromptField({ className="!px-[3px] !h-5" icon={} > - {'清空'} + {I18n.t('clear')} )} @@ -171,7 +172,9 @@ export function PromptField({ } disabled={disabled} noLabel - rules={[{ required: true, message: 'System Prompt 不可为空' }]} + rules={[ + { required: true, message: I18n.t('system_prompt_not_empty') }, + ]} minHeight={300} maxHeight={500} dragBtnHidden @@ -206,7 +209,9 @@ export function PromptField({ } noLabel disabled={disabled} - rules={[{ required: true, message: 'User Prompt 不可为空' }]} + rules={[ + { required: true, message: I18n.t('user_prompt_not_empty') }, + ]} maxHeight={500} messageTypeDisabled={true} messageTypeList={messageTypeList} @@ -230,10 +235,10 @@ export function PromptField({ }} rightActionBtns={ { const messageList = promptEvaluator?.message_list || []; @@ -273,7 +278,7 @@ export function PromptField({ disabled={disabled} icon={} > - {'添加 User Prompt'} + {I18n.t('add_user_prompt')} )} diff --git a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/submit-version-modal.tsx b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/submit-version-modal.tsx index 7970e1748..9afd6a66c 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/submit-version-modal.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/submit-version-modal.tsx @@ -5,6 +5,7 @@ import { useEffect, useRef } from 'react'; import { nanoid } from 'nanoid'; import { merge } from 'lodash-es'; +import { I18n } from '@cozeloop/i18n-adapter'; import { useSpace } from '@cozeloop/biz-hooks-adapter'; import { EVENT_NAMES, sendEvent } from '@cozeloop/tea-adapter'; import { type Evaluator } from '@cozeloop/api-schema/evaluation'; @@ -100,36 +101,40 @@ export function SubmitVersionModal({ return ( + ), }} field="current_version.version" - placeholder={'请输入版本号'} + placeholder={I18n.t('please_input', { field: I18n.t('version') })} rules={[ { validator: (_rule, value) => { if (!value) { - return new Error('请输入版本号'); + return new Error( + I18n.t('please_input', { field: I18n.t('version') }), + ); } const reg = /^\d{1,4}\.\d{1,4}\.\d{1,4}$/; if (!reg.test(value)) { - return new Error('版本号格式为a.b.c,且每段为0-9999'); + return new Error(I18n.t('version_number_format')); } if (type === 'append') { const latestVersion = evaluator?.latest_version; @@ -138,7 +143,9 @@ export function SubmitVersionModal({ compareVersions(value, latestVersion) <= 0 ) { return new Error( - `版本号必须大于当前版本号:${latestVersion}`, + I18n.t('version_number_gt_current', { + version: latestVersion, + }), ); } } @@ -149,9 +156,11 @@ export function SubmitVersionModal({ ]} /> diff --git a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/template-modal.tsx b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/template-modal.tsx index b31889abb..3e39f78ba 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/template-modal.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-create/template-modal.tsx @@ -5,6 +5,7 @@ import { useEffect, useState } from 'react'; import classNames from 'classnames'; import { useRequest } from 'ahooks'; +import { I18n } from '@cozeloop/i18n-adapter'; import { TemplateInfo } from '@cozeloop/evaluate-components'; import { TemplateType, @@ -95,7 +96,7 @@ export function TemplateModal({ >
- {'选择模板'} + {I18n.t('select_template')}
{listService.loading ? ( @@ -108,7 +109,7 @@ export function TemplateModal({ ) : ( <>
- {'预置评估器'} + {I18n.t('preset_evaluator')}
{listService.data?.builtin_template_keys?.map((t, idx) => (
- {'预览'} + {I18n.t('preview')} } @@ -155,14 +156,14 @@ export function TemplateModal({
diff --git a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/base-info-modal.tsx b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/base-info-modal.tsx index b0faf3d4f..d3197eaa3 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/base-info-modal.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/base-info-modal.tsx @@ -3,6 +3,7 @@ import { useEffect, useRef } from 'react'; import { useRequest } from 'ahooks'; +import { I18n } from '@cozeloop/i18n-adapter'; import { useSpace } from '@cozeloop/biz-hooks-adapter'; import { sourceNameRuleValidator } from '@cozeloop/evaluate-components'; import { EvaluatorType, type Evaluator } from '@cozeloop/api-schema/evaluation'; @@ -63,11 +64,11 @@ export function BaseInfoModal({ return ( { @@ -92,7 +96,9 @@ export function BaseInfoModal({ name: value, }); if (!pass) { - throw new Error('名称已存在'); + throw new Error( + I18n.t('field_exists', { field: I18n.t('name') }), + ); } } }, @@ -100,9 +106,9 @@ export function BaseInfoModal({ ]} /> diff --git a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/header.tsx b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/header.tsx index c6dae6ca6..86f77edd1 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/header.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/header.tsx @@ -19,6 +19,7 @@ import { type DebugButtonProps, } from '../evaluator-create/debug-button'; import { type BaseInfo, BaseInfoModal } from './base-info-modal'; +import { I18n } from '@cozeloop/i18n-adapter'; export function Header({ evaluator, @@ -53,13 +54,17 @@ export function Header({ tagContent = ( <> - {'草稿自动保存中'} + {I18n.t('draft_auto_saving')} ); } else if (autoSaveService.error) { - tagContent = '草稿自动保存失败'; + tagContent = I18n.t('draft_auto_save_failed'); } else if (autoSaveService.data?.lastSaveTime) { - tagContent = `草稿已自动保存于 ${dayjs(Number(autoSaveService.data.lastSaveTime)).format('YYYY-MM-DD HH:mm:ss')}`; + tagContent = I18n.t('draft_auto_saved_date', { + date: dayjs(Number(autoSaveService.data.lastSaveTime)).format( + 'YYYY-MM-DD HH:mm:ss', + ), + }); } if (tagContent) { @@ -87,14 +92,14 @@ export function Header({
- {'提交时间:'} + {I18n.t('submission_time')} {dayjs(Number(selectedVersion.base_info?.created_at)).format( 'YYYY-MM-DD HH:mm:ss', )}
- {'提交人:'} + {I18n.t('submitter')} - {'修改未提交'} + {I18n.t('changes_not_submitted')} ) : null} @@ -135,7 +140,7 @@ export function Header({
- 描述:{evaluator?.description || '-'} + {I18n.t('description')}: {evaluator?.description || '-'}
{renderExtra()} @@ -144,13 +149,13 @@ export function Header({
{selectedVersion ? null : } {selectedVersion ? null : ( )} diff --git a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/index.tsx b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/index.tsx index 28ff0d1a1..42418de00 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/index.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/index.tsx @@ -5,6 +5,7 @@ import { useParams } from 'react-router-dom'; import { useRef, useState } from 'react'; import { useRequest } from 'ahooks'; +import { I18n } from '@cozeloop/i18n-adapter'; import { GuardPoint, useGuard } from '@cozeloop/guard'; import { ModelConfigInfo, TemplateInfo } from '@cozeloop/evaluate-components'; import { useDemoSpace, useSpace } from '@cozeloop/biz-hooks-adapter'; @@ -128,7 +129,7 @@ function EvaluatorDetailPage() { return (
- {'配置信息'} + {I18n.t('config_info')}
setSubmitModalVisible(false)} onSuccess={(_, newEvaluator) => { setSubmitModalVisible(false); - Toast.success('版本提交成功'); + Toast.success(I18n.t('version_submit_success')); service.mutate(() => newEvaluator); if (versionListVisible) { setVersionListRefreshFlag([]); diff --git a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/version-list-pane.tsx b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/version-list-pane.tsx index f501e8f70..0ad2634c6 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/version-list-pane.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-detail/version-list-pane.tsx @@ -1,6 +1,7 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 import { useRequest } from 'ahooks'; +import { I18n } from '@cozeloop/i18n-adapter'; import { VersionItem } from '@cozeloop/components'; import { type EvaluatorVersion, @@ -38,7 +39,9 @@ export function VersionListPane({ return (
-
{'版本记录'}
+
+ {I18n.t('version_record')} +
} field="search_name" - placeholder="搜索名称" + placeholder={I18n.t('search_name')} fieldClassName="!mr-0 !pr-0" className="!w-full" autoComplete="off" diff --git a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-list/evaluator-list-page.tsx b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-list/evaluator-list-page.tsx index 4460323c5..c876262c8 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-list/evaluator-list-page.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/evaluator/evaluator-list/evaluator-list-page.tsx @@ -8,6 +8,7 @@ import { useMemo, useState } from 'react'; import { isEmpty } from 'lodash-es'; import dayjs from 'dayjs'; import { usePagination, useRequest } from 'ahooks'; +import { I18n } from '@cozeloop/i18n-adapter'; import { GuardPoint, useGuards } from '@cozeloop/guard'; import { type ColumnItem, @@ -83,12 +84,14 @@ function EvaluatorListPage() { Modal.info({ size: 'large', className: 'w-[420px]', - title: '复制评估器配置', - content: `复制${record.name}配置,并新建评估器`, + title: 'copy_evaluator_config', + content: I18n.t('copy_and_create_evaluator', { + name: record.name, + }), onOk: () => navigate(`create/${record.evaluator_id}`), showCancelButton: true, - cancelText: '取消', - okText: '确认', + cancelText: I18n.t('Cancel'), + okText: I18n.t('confirm'), }); }; @@ -107,8 +110,8 @@ function EvaluatorListPage() { const columns: ColumnItem[] = useMemo(() => { const newDefaultColumns: ColumnItem[] = [ { - title: '评估器名称', - value: '评估器名称', + title: I18n.t('evaluator_name'), + value: I18n.t('evaluator_name'), dataIndex: 'name', key: 'name', width: 200, @@ -128,7 +131,7 @@ function EvaluatorListPage() { color="yellow" className="ml-2 flex-shrink-0 !h-5 !px-2 !py-[2px] rounded-[3px] " > - {'修改未提交'} + {I18n.t('changes_not_submitted')} ) : null}
@@ -137,8 +140,8 @@ function EvaluatorListPage() { disabled: true, }, { - title: '最新版本', - value: '最新版本', + title: I18n.t('latest_version'), + value: I18n.t('latest_version'), dataIndex: 'latest_version', key: 'latest_version', width: 100, @@ -173,8 +176,8 @@ function EvaluatorListPage() { // ), // }, { - title: '描述', - value: '描述', + title: I18n.t('description'), + value: I18n.t('description'), dataIndex: 'description', key: 'description', width: 285, @@ -189,8 +192,8 @@ function EvaluatorListPage() { checked: true, }, { - title: '更新人', - value: '更新人', + title: I18n.t('updated_person'), + value: I18n.t('updated_person'), dataIndex: 'base_info.updated_by', key: 'updated_by', width: 170, @@ -203,8 +206,8 @@ function EvaluatorListPage() { checked: true, }, { - title: '更新时间', - value: '更新时间', + title: I18n.t('update_time'), + value: I18n.t('update_time'), dataIndex: 'base_info.updated_at', sorter: true, key: 'updated_at', @@ -214,8 +217,8 @@ function EvaluatorListPage() { checked: true, }, { - title: '创建人', - value: '创建人', + title: I18n.t('creator'), + value: I18n.t('creator'), dataIndex: 'base_info.created_by', key: 'created_by', width: 170, @@ -228,8 +231,8 @@ function EvaluatorListPage() { checked: true, }, { - title: '创建时间', - value: '创建时间', + title: I18n.t('create_time'), + value: I18n.t('create_time'), dataIndex: 'base_info.created_at', key: 'created_at', sorter: true, @@ -239,8 +242,8 @@ function EvaluatorListPage() { checked: true, }, { - title: '操作', - value: '操作', + title: I18n.t('operation'), + value: I18n.t('operation'), key: 'action', width: 142, fixed: 'right', @@ -248,17 +251,17 @@ function EvaluatorListPage() { navigate(`${record.evaluator_id}`), }, { - label: '复制', + label: I18n.t('copy'), disabled: guards.data[GuardPoint['eval.evaluators.copy']].readonly, onClick: () => handleCopy(record), }, { - label: '删除', + label: I18n.t('delete'), type: 'danger', disabled: guards.data[GuardPoint['eval.evaluators.delete']].readonly, @@ -266,12 +269,14 @@ function EvaluatorListPage() { Modal.error({ size: 'large', className: 'w-[420px]', - title: `确定删除评估器:${record.name}?`, - content: '此操作不可逆,请慎重操作', + title: I18n.t('confirm_delete_evaluator', { + name: record.name, + }), + content: I18n.t('caution_of_operation'), onOk: () => deleteService.runAsync(record), showCancelButton: true, - cancelText: '取消', - okText: '删除', + cancelText: I18n.t('Cancel'), + okText: I18n.t('delete'), }), }, ]} @@ -295,7 +300,7 @@ function EvaluatorListPage() { return (
- +
@@ -376,15 +381,17 @@ function EvaluatorListPage() { } - title="未能找到相关结果" - description={'请尝试其他关键词或修改筛选项'} + title={I18n.t('failed_to_find_related_results')} + description={I18n.t( + 'try_other_keywords_or_modify_filter_options', + )} /> ) : ( } - title="暂无评估器" - description={'点击右上角创建按钮进行创建'} + title={I18n.t('no_evaluator')} + description={I18n.t('click_to_create')} /> ) } diff --git a/frontend/packages/cozeloop/evaluate/src/pages/experiment/contrast/components/add-contrast-experiment.tsx b/frontend/packages/cozeloop/evaluate/src/pages/experiment/contrast/components/add-contrast-experiment.tsx index 04868a85a..18d61bdc3 100644 --- a/frontend/packages/cozeloop/evaluate/src/pages/experiment/contrast/components/add-contrast-experiment.tsx +++ b/frontend/packages/cozeloop/evaluate/src/pages/experiment/contrast/components/add-contrast-experiment.tsx @@ -3,6 +3,7 @@ import { useState } from 'react'; import { EVENT_NAMES, sendEvent } from '@cozeloop/tea-adapter'; +import { I18n } from '@cozeloop/i18n-adapter'; import { ExptStatus, type Experiment } from '@cozeloop/api-schema/evaluation'; import { IconCozPlus } from '@coze-arch/coze-design/icons'; import { Button } from '@coze-arch/coze-design'; @@ -29,7 +30,7 @@ export default function AddContrastExperiment({ setVisible(true); }} > - 添加对比实验 + {I18n.t('add_comparison_experiment')} {visible ? ( -
对比{experimentCount}个实验
+
+ {I18n.t('compare_x_experiments', { num: experimentCount })} +
{ const trimValue = value.trim(); @@ -263,7 +263,7 @@ export const FilterSelectUI = (props: FilterSelectUIProps) => { setSaveViewVisible(false); }} > - 取消 + {I18n.t('cancel')}
@@ -327,12 +327,12 @@ export const FilterSelectUI = (props: FilterSelectUIProps) => {
- 过滤器 + {I18n.t('filter')}
@@ -344,7 +344,7 @@ export const FilterSelectUI = (props: FilterSelectUIProps) => { setLocalFilters({}); }} > - 清空筛选 + {I18n.t('clear')}
{ 'calc((100% - ((100% - 80px) / 2) - 16px) / 2 + (100% - 80px) / 2 - 14px)', }} > - 且 + {I18n.t('observation_and')}
@@ -439,7 +439,7 @@ export const FilterSelectUI = (props: FilterSelectUIProps) => { }); }} > - 保存至当前视图 + {I18n.t('save_to_current_view')} { setSaveViewNameVisible(true); }} > - 另存为视图 + {I18n.t('save_as_view')} @@ -481,7 +481,7 @@ export const FilterSelectUI = (props: FilterSelectUIProps) => { }} >
- 保存视图 + {I18n.t('save_view')}
@@ -508,7 +508,7 @@ export const FilterSelectUI = (props: FilterSelectUIProps) => { setSaveViewNameVisible(true); }} > - 保存视图 + {I18n.t('save_view')} )} @@ -520,7 +520,7 @@ export const FilterSelectUI = (props: FilterSelectUIProps) => { onClick={handleApply} disabled={disableApply} > - 应用 + {I18n.t('apply')} )} @@ -545,7 +545,7 @@ export const FilterSelectUI = (props: FilterSelectUIProps) => { >
-
过滤器
+
{I18n.t('filter')}
> = { success: { - label: I18n.t('fornax_analytics_threads_options_success'), + label: I18n.t('observation_threads_options_success'), }, error: { - label: I18n.t('fornax_analytics_threads_options_fail'), + label: I18n.t('observation_threads_options_fail'), }, }; @@ -133,9 +133,9 @@ export const BOT_ENV_RECORDS: Partial< > > = { [BotEnv.DEV]: { - label: I18n.t('fornax_analytics_threads_options_dev'), + label: I18n.t('observation_threads_options_dev'), }, [BotEnv.ONLINE]: { - label: I18n.t('fornax_analytics_threads_options_online'), + label: I18n.t('observation_threads_options_online'), }, }; diff --git a/frontend/packages/cozeloop/observation/trace-list/src/components/logic-expr/error-msg-render.tsx b/frontend/packages/cozeloop/observation/trace-list/src/components/logic-expr/error-msg-render.tsx index 929b0c461..fdd794f7c 100644 --- a/frontend/packages/cozeloop/observation/trace-list/src/components/logic-expr/error-msg-render.tsx +++ b/frontend/packages/cozeloop/observation/trace-list/src/components/logic-expr/error-msg-render.tsx @@ -3,6 +3,7 @@ import { type OptionProps } from '@coze-arch/coze-design'; import { checkValueIsEmpty } from './right-render'; +import { I18n } from '@cozeloop/i18n-adapter'; interface ErrorMsgRenderProps { expr: { @@ -28,7 +29,7 @@ export const ErrorMsgRender = ({ if (isInvalidateExpr) { return (
- {leftname ?? left} 过滤项冲突 + {leftname ?? left} {I18n.t('filter_item_conflict')}
); } @@ -36,7 +37,7 @@ export const ErrorMsgRender = ({ if (checkValueIsEmpty(right) && left && valueChangeMap[left]) { return (
- 不允许为空 + {I18n.t('not_allowed_to_be_empty')}
); } diff --git a/frontend/packages/cozeloop/observation/trace-list/src/components/logic-expr/operator-render.tsx b/frontend/packages/cozeloop/observation/trace-list/src/components/logic-expr/operator-render.tsx index 8aeeda2b7..bdd6a467b 100644 --- a/frontend/packages/cozeloop/observation/trace-list/src/components/logic-expr/operator-render.tsx +++ b/frontend/packages/cozeloop/observation/trace-list/src/components/logic-expr/operator-render.tsx @@ -4,7 +4,7 @@ import { useCallback, useMemo, useEffect } from 'react'; import { isEmpty } from 'lodash-es'; import classNames from 'classnames'; -import { I18n, type I18nKeysNoOptionsType } from '@cozeloop/i18n-adapter'; +import { I18n } from '@cozeloop/i18n-adapter'; import { type FieldMeta } from '@cozeloop/api-schema/observation'; import { type OptionProps, Select } from '@coze-arch/coze-design'; @@ -45,9 +45,7 @@ export const OperatorRenderer = ({ const tagOperatorOption: OptionProps[] = useMemo( () => tagFilterRecord[left]?.filter_types?.map(item => ({ - label: I18n.t( - (LOGIC_OPERATOR_RECORDS[item]?.label ?? '') as I18nKeysNoOptionsType, - ), + label: I18n.unsafeT(LOGIC_OPERATOR_RECORDS[item]?.label ?? ''), value: item, })) ?? [], [left, tagFilterRecord], diff --git a/frontend/packages/cozeloop/observation/trace-list/src/components/queries/table/index.tsx b/frontend/packages/cozeloop/observation/trace-list/src/components/queries/table/index.tsx index a7856ad8d..de7456626 100644 --- a/frontend/packages/cozeloop/observation/trace-list/src/components/queries/table/index.tsx +++ b/frontend/packages/cozeloop/observation/trace-list/src/components/queries/table/index.tsx @@ -249,31 +249,27 @@ export const QueryTable = ({ } - title={I18n.t('fornax_analytics_data_empty')} + title={I18n.t('observation_data_empty')} description={
{traceListCode === TRACE_EXPIRED_CODE ? ( - 当前Trace已过期无法查看 + {I18n.t('current_trace_expired_to_view')} ) : ( - <> - {selectedPlatform === 'cozeloop' && ( - <> - 请查看 - - -  扣子罗盘 SDK 接入指南;  - - - 或 - - )} - 尝试修改更大的时间范围,修改过滤器中的过滤条件 - + selectedPlatform === 'cozeloop' && + I18n.t('trace_empty_tip', { + manual: ( + + +  {I18n.t('cozeloop_sdk_manual')}  + + + ), + }) )}
} diff --git a/frontend/packages/cozeloop/observation/trace-list/src/components/table-cell-text/index.tsx b/frontend/packages/cozeloop/observation/trace-list/src/components/table-cell-text/index.tsx index 667485ef7..e2326b92e 100644 --- a/frontend/packages/cozeloop/observation/trace-list/src/components/table-cell-text/index.tsx +++ b/frontend/packages/cozeloop/observation/trace-list/src/components/table-cell-text/index.tsx @@ -7,6 +7,7 @@ import { type MouseEvent, } from 'react'; +import { I18n } from '@cozeloop/i18n-adapter'; import { handleCopy as copy } from '@cozeloop/components'; import { IconCozCopy } from '@coze-arch/coze-design/icons'; import { type PopoverProps, type TooltipProps } from '@coze-arch/coze-design'; @@ -69,7 +70,7 @@ export const CustomTableTooltip = ({ {children !== undefined ? children : '-'} {enableCopy ? ( - + new Date(), end: () => new Date(), }, [PresetRange.Min5]: { - text: I18n.t('fornax_analytics_time_last_minutes', { + text: I18n.t('observation_time_last_minutes', { count: 5, }), start: () => new Date(new Date().valueOf() - 1000 * 60 * 5), end: () => new Date(), }, [PresetRange.Min15]: { - text: I18n.t('fornax_analytics_time_last_minutes', { + text: I18n.t('observation_time_last_minutes', { count: 15, }), start: () => new Date(new Date().valueOf() - 1000 * 60 * 15), end: () => new Date(), }, [PresetRange.Min30]: { - text: I18n.t('fornax_analytics_time_last_minutes', { + text: I18n.t('observation_time_last_minutes', { count: 30, }), start: () => new Date(new Date().valueOf() - 1000 * 60 * 30), end: () => new Date(), }, [PresetRange.Hour1]: { - text: I18n.t('fornax_analytics_time_last_hours', { + text: I18n.t('observation_time_last_hours', { count: 1, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 1), end: () => new Date(), }, [PresetRange.Hour2]: { - text: I18n.t('fornax_analytics_time_last_hours', { + text: I18n.t('observation_time_last_hours', { count: 2, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 2), end: () => new Date(), }, [PresetRange.Hour3]: { - text: I18n.t('fornax_analytics_time_last_hours', { + text: I18n.t('observation_time_last_hours', { count: 3, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 3), end: () => new Date(), }, [PresetRange.Hour6]: { - text: I18n.t('fornax_analytics_time_last_hours', { + text: I18n.t('observation_time_last_hours', { count: 6, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 6), end: () => new Date(), }, [PresetRange.Hour12]: { - text: I18n.t('fornax_analytics_time_last_hours', { + text: I18n.t('observation_time_last_hours', { count: 12, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 12), end: () => new Date(), }, [PresetRange.Hour24]: { - text: I18n.t('fornax_analytics_time_last_hours', { + text: I18n.t('observation_time_last_hours', { count: 24, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 24), end: () => new Date(), }, [PresetRange.Day1]: { - text: I18n.t('fornax_analytics_time_last_days', { + text: I18n.t('observation_time_last_days', { count: 1, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 24), end: () => new Date(), }, [PresetRange.Day2]: { - text: I18n.t('fornax_analytics_time_last_days', { + text: I18n.t('observation_time_last_days', { count: 2, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 24 * 2), end: () => new Date(), }, [PresetRange.Day3]: { - text: I18n.t('fornax_analytics_time_last_days', { + text: I18n.t('observation_time_last_days', { count: 3, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 24 * 3), end: () => new Date(), }, [PresetRange.Day5]: { - text: I18n.t('fornax_analytics_time_last_days', { + text: I18n.t('observation_time_last_days', { count: 5, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 24 * 5), end: () => new Date(), }, [PresetRange.Day7]: { - text: I18n.t('fornax_analytics_time_last_days', { + text: I18n.t('observation_time_last_days', { count: 7, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 24 * 7), end: () => new Date(), }, [PresetRange.Day15]: { - text: I18n.t('fornax_analytics_time_last_days', { + text: I18n.t('observation_time_last_days', { count: 15, }), start: () => new Date(new Date().valueOf() - 1000 * 3600 * 24 * 15), end: () => new Date(), }, [PresetRange.Month1]: { - text: I18n.t('fornax_analytics_time_past_month'), + text: I18n.t('observation_time_past_month'), start: () => dayjs().subtract(1, 'month').toDate(), end: () => dayjs().toDate(), }, [PresetRange.Month3]: { - text: I18n.t('fornax_analytics_time_past_3_months'), + text: I18n.t('observation_time_past_3_months'), start: () => dayjs().subtract(3, 'month').toDate(), end: () => dayjs().toDate(), }, [PresetRange.DayToNow]: { - text: I18n.t('fornax_analytics_time_today_so_far'), + text: I18n.t('observation_time_today_so_far'), start: () => getDateAtZeroClock(new Date()), end: () => new Date(), }, [PresetRange.Yesterday]: { - text: I18n.t('fornax_analytics_time_yesterday'), + text: I18n.t('observation_time_yesterday'), start: () => getDateAtZeroClock(new Date(new Date().valueOf() - 1000 * 3600 * 24)), end: () => getDateAtZeroClock(new Date()), }, [PresetRange.BeforeYesterday]: { - text: I18n.t('fornax_analytics_time_day_before_yesterday'), + text: I18n.t('observation_time_day_before_yesterday'), start: () => getDateAtZeroClock(new Date(new Date().valueOf() - 1000 * 3600 * 24 * 2)), end: () => getDateAtZeroClock(new Date(new Date().valueOf() - 1000 * 3600 * 24)), }, [PresetRange.WeekToNow]: { - text: I18n.t('fornax_analytics_time_week_so_far'), + text: I18n.t('observation_time_week_so_far'), start: () => { const now = new Date(); const day = now.getDay(); @@ -202,55 +202,55 @@ export const timePickerPresets = { end: () => new Date(), }, [PresetRange.YesterdayExcludeToday]: { - text: I18n.t('fornax_analytics_time_yesterday'), + text: I18n.t('observation_time_yesterday'), start: () => getDateAtZeroClock(new Date(new Date().valueOf() - 1000 * 3600 * 24)), end: () => getDayjsEndOfYesterday().toDate(), }, [PresetRange.PastWeek]: { - text: I18n.t('fornax_analytics_time_past_week'), + text: I18n.t('observation_time_past_week'), start: () => getDayjsStartOfToday().subtract(7, 'day').toDate(), end: () => getDayjsEndOfYesterday().toDate(), }, [PresetRange.PastMonth]: { - text: I18n.t('fornax_analytics_time_past_month'), + text: I18n.t('observation_time_past_month'), start: () => getDayjsStartOfToday().subtract(1, 'month').toDate(), end: () => getDayjsEndOfYesterday().toDate(), }, [PresetRange.PastYear]: { - text: I18n.t('fornax_analytics_time_past_year'), + text: I18n.t('observation_time_past_year'), start: () => getDayjsStartOfToday().subtract(1, 'year').toDate(), end: () => getDayjsEndOfYesterday().toDate(), }, [PresetRange.MonthToNow]: { - text: I18n.t('fornax_analytics_range_this_month'), + text: I18n.t('observation_range_this_month'), start: () => dayjs().startOf('month').toDate(), end: () => dayjs().toDate(), }, [PresetRange.Day30]: { - text: I18n.t('fornax_analytics_time_last_days', { + text: I18n.t('observation_time_last_days', { count: 30, }), start: () => dayjs().subtract(30, 'd').toDate(), end: () => dayjs().toDate(), }, [PresetRange.Day90]: { - text: I18n.t('fornax_analytics_time_last_days', { + text: I18n.t('observation_time_last_days', { count: 90, }), start: () => dayjs().subtract(90, 'd').toDate(), end: () => dayjs().toDate(), }, [PresetRange.Day180]: { - text: I18n.t('fornax_analytics_time_last_days', { + text: I18n.t('observation_time_last_days', { count: 180, }), start: () => dayjs().subtract(180, 'd').toDate(), end: () => dayjs().toDate(), }, [PresetRange.Day365]: { - text: I18n.t('fornax_analytics_time_last_days', { + text: I18n.t('observation_time_last_days', { count: 365, }), start: () => dayjs().subtract(365, 'd').toDate(), diff --git a/frontend/packages/cozeloop/observation/trace-list/src/hooks/use-fetch-meta-info.ts b/frontend/packages/cozeloop/observation/trace-list/src/hooks/use-fetch-meta-info.ts index 4fb10508d..2f66eaf59 100644 --- a/frontend/packages/cozeloop/observation/trace-list/src/hooks/use-fetch-meta-info.ts +++ b/frontend/packages/cozeloop/observation/trace-list/src/hooks/use-fetch-meta-info.ts @@ -33,7 +33,7 @@ export const useFetchMetaInfo = () => { refreshDeps: [selectedPlatform, selectedSpanType], onError(e) { Toast.error( - I18n.t('fornax_analytics_fetch_meta_error', { + I18n.t('observation_fetch_meta_error', { msg: e.message || '', }), ); diff --git a/frontend/packages/cozeloop/observation/trace-list/src/index.tsx b/frontend/packages/cozeloop/observation/trace-list/src/index.tsx index 7ce4a6723..b5315ac18 100644 --- a/frontend/packages/cozeloop/observation/trace-list/src/index.tsx +++ b/frontend/packages/cozeloop/observation/trace-list/src/index.tsx @@ -1,5 +1,6 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { PrimaryPage } from '@cozeloop/components'; import { useTraceTimeRangeOptions } from '@/hooks/use-trace-time-range-options'; @@ -19,11 +20,11 @@ import { Queries } from './components/queries'; import { QueryFilterBar } from './components/filter-bar'; import { CozeLoopTraceBanner } from './components/banner'; -const TOOLTIP_CONTENT = { - all_span: '查询所有 SpanID,以上报埋点为粒度进行展示', - root_span: '根据 TraceID 查询,以调用入口为粒度进行展示', - llm_span: '仅查询和模型调用相关的埋点', -}; +const getTooltipContent = () => ({ + all_span: I18n.t('all_span_tip'), + root_span: I18n.t('root_span_tip'), + llm_span: I18n.t('llm_span_tip'), +}); const TraceListApp = () => { usePageStay(); @@ -60,7 +61,7 @@ const TraceListApp = () => { onColumnsChange={onColumnsChange} platformEnumOptionList={PLATFORM_ENUM_OPTION_LIST} spanListTypeEnumOptionList={SPAN_TAB_OPTION_LIST} - tooltipContent={TOOLTIP_CONTENT} + tooltipContent={getTooltipContent()} /> } className="!pb-0" diff --git a/frontend/packages/cozeloop/observation/trace-list/stories/demo.stories.tsx b/frontend/packages/cozeloop/observation/trace-list/stories/demo.stories.tsx deleted file mode 100644 index b848cdfcb..000000000 --- a/frontend/packages/cozeloop/observation/trace-list/stories/demo.stories.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates -// SPDX-License-Identifier: Apache-2.0 -import { DemoComponent } from '../src'; - -export default { - title: 'Example/Demo', - component: DemoComponent, - parameters: { - // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout - layout: 'centered', - }, - // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs - tags: ['autodocs'], - // More on argTypes: https://storybook.js.org/docs/api/argtypes - argTypes: {}, -}; - -// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args -export const Base = { - args: { - name: 'tecvan', - }, -}; diff --git a/frontend/packages/cozeloop/observation/trace-list/stories/hello.mdx b/frontend/packages/cozeloop/observation/trace-list/stories/hello.mdx deleted file mode 100644 index 66edadc6d..000000000 --- a/frontend/packages/cozeloop/observation/trace-list/stories/hello.mdx +++ /dev/null @@ -1,34 +0,0 @@ -import { Meta } from "@storybook/blocks"; - - - -
-
- # Hello world - - Hello world -
-
- - diff --git a/frontend/packages/cozeloop/observation/trace-list/tsconfig.misc.json b/frontend/packages/cozeloop/observation/trace-list/tsconfig.misc.json index 7bc9c63e7..267b83c4f 100644 --- a/frontend/packages/cozeloop/observation/trace-list/tsconfig.misc.json +++ b/frontend/packages/cozeloop/observation/trace-list/tsconfig.misc.json @@ -10,7 +10,7 @@ "target": "ES2020", "moduleResolution": "bundler" }, - "include": ["__tests__", "vitest.config.ts", "stories"], + "include": ["__tests__", "vitest.config.ts"], "exclude": ["./dist"], "references": [ { diff --git a/frontend/packages/cozeloop/observation/trace-struct-data/.storybook/main.js b/frontend/packages/cozeloop/observation/trace-struct-data/.storybook/main.js deleted file mode 100644 index d5c408cbb..000000000 --- a/frontend/packages/cozeloop/observation/trace-struct-data/.storybook/main.js +++ /dev/null @@ -1,31 +0,0 @@ -import { mergeConfig } from 'vite'; -import svgr from 'vite-plugin-svgr'; - -/** @type { import('@storybook/react-vite').StorybookConfig } */ -const config = { - stories: ['../stories/**/*.mdx', '../stories/**/*.stories.tsx'], - addons: [ - '@storybook/addon-links', - '@storybook/addon-essentials', - '@storybook/addon-onboarding', - '@storybook/addon-interactions', - ], - framework: { - name: '@storybook/react-vite', - options: {}, - }, - docs: { - autodocs: 'tag', - }, - viteFinal: config => - mergeConfig(config, { - plugins: [ - svgr({ - svgrOptions: { - native: false, - }, - }), - ], - }), -}; -export default config; diff --git a/frontend/packages/cozeloop/observation/trace-struct-data/.storybook/preview.js b/frontend/packages/cozeloop/observation/trace-struct-data/.storybook/preview.js deleted file mode 100644 index 1f07be963..000000000 --- a/frontend/packages/cozeloop/observation/trace-struct-data/.storybook/preview.js +++ /dev/null @@ -1,14 +0,0 @@ -/** @type { import('@storybook/react').Preview } */ -const preview = { - parameters: { - actions: { argTypesRegex: "^on[A-Z].*" }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/i, - }, - }, - }, -}; - -export default preview; diff --git a/frontend/packages/cozeloop/observation/trace-struct-data/src/components/image.tsx b/frontend/packages/cozeloop/observation/trace-struct-data/src/components/image.tsx index dacbf1cde..061041e65 100644 --- a/frontend/packages/cozeloop/observation/trace-struct-data/src/components/image.tsx +++ b/frontend/packages/cozeloop/observation/trace-struct-data/src/components/image.tsx @@ -1,8 +1,8 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { IconCozCrossCircleFill } from '@coze-arch/coze-design/icons'; import { Image, Tooltip, Tag } from '@coze-arch/coze-design'; -import { I18n } from '@cozeloop/i18n-adapter'; import { useFetchResource } from '../hooks/use-fetch-resource'; @@ -16,7 +16,7 @@ export const TraceImage = ({ url }: { url: string }) => { - 图片加载失败 + {I18n.t('image_load_failed')}
diff --git a/frontend/packages/cozeloop/observation/trace-struct-data/src/components/plain-text.tsx b/frontend/packages/cozeloop/observation/trace-struct-data/src/components/plain-text.tsx index 51a6b9286..c5703502d 100644 --- a/frontend/packages/cozeloop/observation/trace-struct-data/src/components/plain-text.tsx +++ b/frontend/packages/cozeloop/observation/trace-struct-data/src/components/plain-text.tsx @@ -3,6 +3,7 @@ import { isObject } from 'lodash-es'; import classNames from 'classnames'; import { JsonViewer, type JsonViewerProps } from '@textea/json-viewer'; +import { I18n } from '@cozeloop/i18n-adapter'; import { Tag } from '@coze-arch/coze-design'; import { JSON_VIEW_CONFIG } from '../consts/json-view'; @@ -34,7 +35,7 @@ export const renderJsonContent = ( ) : ( <> - 非法JSON + {I18n.t('invalid_json')} diff --git a/frontend/packages/cozeloop/observation/trace-struct-data/src/components/raw-content.tsx b/frontend/packages/cozeloop/observation/trace-struct-data/src/components/raw-content.tsx index 2292b827b..962c5de69 100644 --- a/frontend/packages/cozeloop/observation/trace-struct-data/src/components/raw-content.tsx +++ b/frontend/packages/cozeloop/observation/trace-struct-data/src/components/raw-content.tsx @@ -19,6 +19,7 @@ import { JSON_VIEW_CONFIG } from '../consts/json-view'; import { ViewAllModal } from './view-all'; import styles from './index.module.less'; +import { I18n } from '@cozeloop/i18n-adapter'; interface RawContentProps { structuredContent: string | object; tagType?: TagType; @@ -77,7 +78,7 @@ export const RawContent: React.FC = ({ className="!text-[rgb(var(--coze-up-brand-9))] text-xs leading-4 font-medium cursor-pointer" onClick={handleViewAll} > - 查看全部 + {I18n.t('view_all')}
) : null} diff --git a/frontend/packages/cozeloop/observation/trace-struct-data/src/components/span-content-container.tsx b/frontend/packages/cozeloop/observation/trace-struct-data/src/components/span-content-container.tsx index 4243baecc..7265a6002 100644 --- a/frontend/packages/cozeloop/observation/trace-struct-data/src/components/span-content-container.tsx +++ b/frontend/packages/cozeloop/observation/trace-struct-data/src/components/span-content-container.tsx @@ -5,6 +5,7 @@ import { useEffect, useState } from 'react'; import { isObject } from 'lodash-es'; import classNames from 'classnames'; import { type JsonViewerProps } from '@textea/json-viewer'; +import { I18n } from '@cozeloop/i18n-adapter'; import { handleCopy as copy } from '@cozeloop/components'; import { IconCozCopy, IconCozCorner } from '@coze-arch/coze-design/icons'; import { Button, SegmentTab, Tooltip } from '@coze-arch/coze-design'; @@ -82,7 +83,7 @@ export const SpanContentContainer = (props: SpanContentContainerProps) => {
{title} {structuredContent ? ( - +
) : null} diff --git a/frontend/packages/cozeloop/observation/trace-struct-data/src/components/view-all.tsx b/frontend/packages/cozeloop/observation/trace-struct-data/src/components/view-all.tsx index 648f0d41b..60132bcc0 100644 --- a/frontend/packages/cozeloop/observation/trace-struct-data/src/components/view-all.tsx +++ b/frontend/packages/cozeloop/observation/trace-struct-data/src/components/view-all.tsx @@ -10,6 +10,7 @@ import { Button, Divider, Spin, Typography, Empty } from '@coze-arch/coze-design import { TagType, type Span } from '../types'; import { useFetchResource } from '../hooks/use-fetch-resource'; +import { I18n } from '@cozeloop/i18n-adapter'; interface ViewAllProps { onViewAllClick: (show: boolean) => void; @@ -95,8 +96,8 @@ const InputOrOutputTextRender = (props: InputOrOutputTextProps) => { return ( } /> diff --git a/frontend/packages/cozeloop/observation/trace-struct-data/src/span-definition/model/render.tsx b/frontend/packages/cozeloop/observation/trace-struct-data/src/span-definition/model/render.tsx index 603fd65b1..c638b3bd9 100644 --- a/frontend/packages/cozeloop/observation/trace-struct-data/src/span-definition/model/render.tsx +++ b/frontend/packages/cozeloop/observation/trace-struct-data/src/span-definition/model/render.tsx @@ -65,7 +65,7 @@ const ModelTool = (tool?: Tool) => { {raw?.function?.name} - +
diff --git a/frontend/packages/cozeloop/prompt-pages/src/components/prompt-header/index.tsx b/frontend/packages/cozeloop/prompt-pages/src/components/prompt-header/index.tsx index 066733c0d..68aa7cb16 100644 --- a/frontend/packages/cozeloop/prompt-pages/src/components/prompt-header/index.tsx +++ b/frontend/packages/cozeloop/prompt-pages/src/components/prompt-header/index.tsx @@ -14,6 +14,7 @@ import { getPlaceholderErrorContent, PromptCreate, } from '@cozeloop/prompt-components'; +import { I18n } from '@cozeloop/i18n-adapter'; import { EditIconButton, getBaseUrl, @@ -178,7 +179,7 @@ export function PromptHeader() { loading={versionChangeLoading} disabled={streaming} > - 返回草稿版本 + {I18n.t('revert_draft_version')} ); } @@ -190,7 +191,9 @@ export function PromptHeader() { return ( - 提交新版本 + {I18n.t('submit_new_version')} ); @@ -263,11 +266,11 @@ export function PromptHeader() { className="!py-0.5" prefixIcon={} > - 草稿保存中... + {I18n.t('draft_saving')} ) : ( - 草稿已自动保存于 + {I18n.t('draft_auto_saved_in')} {promptInfo?.prompt_draft?.draft_info?.updated_at ? convertDisplayTime( promptInfo?.prompt_draft?.draft_info?.updated_at, @@ -315,7 +318,7 @@ export function PromptHeader() { @@ -328,14 +331,16 @@ export function PromptHeader() { color={isDraftEdit ? 'yellow' : 'brand'} className="!py-0.5" > - {isDraftEdit ? '修改未提交' : '已提交'} + {isDraftEdit + ? I18n.t('changes_not_submitted') + : I18n.t('submitted')} ) : ( - 修改未提交 + {I18n.t('changes_not_submitted')} )} {autoSaving ? ( @@ -344,11 +349,11 @@ export function PromptHeader() { className="!py-0.5" prefixIcon={} > - 草稿保存中... + {I18n.t('draft_saving')} ) : isDraftEdit ? ( - 草稿已自动保存于 + {I18n.t('draft_auto_saved_in')} {promptInfo?.prompt_draft?.draft_info?.updated_at || promptInfo?.prompt_commit?.commit_info?.committed_at ? convertDisplayTime( @@ -384,7 +389,7 @@ export function PromptHeader() { icon={} disabled={streaming || versionChangeLoading || readonly} > - 进入自由对比模式 + {I18n.t('enter_free_comparison_mode')} {promptInfo?.prompt_key ? ( ) : null} {promptInfo?.prompt_key ? null : ( @@ -424,7 +429,7 @@ export function PromptHeader() { }} disabled={hasPlaceholderError || streaming} > - 快捷创建 + {I18n.t('quick_create')} )} @@ -441,7 +446,7 @@ export function PromptHeader() { className="!px-2" onClick={() => setExecuteHistoryVisible(true)} > - 调试历史 + {I18n.t('debug_history')} {readonly ? ( - 创建副本 + {I18n.t('create_copy')} ) : null} onDeletePrompt(promptInfo)} disabled={streaming} > - 删除 + + {I18n.t('delete')} + } @@ -483,7 +490,7 @@ export function PromptHeader() { icon={} disabled={streaming} > - 退出自由对比模式 + {I18n.t('exit_free_comparison_mode')} )} diff --git a/frontend/packages/cozeloop/prompt-pages/src/components/prompt-submit/diff-content.tsx b/frontend/packages/cozeloop/prompt-pages/src/components/prompt-submit/diff-content.tsx index e7d7a71c3..45ad2665c 100644 --- a/frontend/packages/cozeloop/prompt-pages/src/components/prompt-submit/diff-content.tsx +++ b/frontend/packages/cozeloop/prompt-pages/src/components/prompt-submit/diff-content.tsx @@ -10,6 +10,7 @@ import { type ReactNode, useMemo } from 'react'; import { isEqual } from 'lodash-es'; import { useRequest } from 'ahooks'; import { PromptDiffEditor } from '@cozeloop/prompt-components'; +import { I18n } from '@cozeloop/i18n-adapter'; import { useSpace } from '@cozeloop/biz-hooks-adapter'; import { type Prompt, ToolChoiceType } from '@cozeloop/api-schema/prompt'; import { Scenario } from '@cozeloop/api-schema/llm-manage'; @@ -96,7 +97,7 @@ export function DiffContent({ }; addDiffItem( - '模型 ID', + I18n.t('model_id'), baseItem.modelConfig?.model_id, currentItem.modelConfig?.model_id, ); @@ -109,21 +110,25 @@ export function DiffContent({ ); if (baseModel?.name !== currentModel?.name) { - addDiffItem('模型名称', baseModel?.name || '', currentModel?.name || ''); + addDiffItem( + I18n.t('model_name'), + baseModel?.name || '', + currentModel?.name || '', + ); } addDiffItem( - '回复随机性', + I18n.t('temperature'), baseItem.modelConfig?.temperature, currentItem.modelConfig?.temperature, ); addDiffItem( - '最大回复长度', + I18n.t('max_tokens'), baseItem.modelConfig?.max_tokens, currentItem.modelConfig?.max_tokens, ); addDiffItem( - 'Top P', + I18n.t('top_p'), baseItem.modelConfig?.top_p, currentItem.modelConfig?.top_p, ); @@ -155,7 +160,7 @@ export function DiffContent({ key: item.key || '', value: (
- 删除 + {I18n.t('delete')} {item.key} @@ -169,7 +174,7 @@ export function DiffContent({ key: item.key || '', value: (
- 新增 + {I18n.t('add')} {item.key} @@ -193,7 +198,7 @@ export function DiffContent({ } darkModeIcon={} - title="本次提交无版本差异" + title={I18n.t('submission_no_version_diff')} />
); @@ -202,7 +207,9 @@ export function DiffContent({
{modelDiffData.length ? (
- 模型设置 + + {I18n.t('model_config')} +
{modelDiffData.map(it => (
@@ -215,7 +222,7 @@ export function DiffContent({ {!templateIsSame ? (
- Prompt 模板 + {I18n.t('prompt_template')}
@@ -231,7 +238,7 @@ export function DiffContent({ size="small" strong > - 草稿 + {I18n.t('draft')}
@@ -263,7 +270,9 @@ export function DiffContent({ ) : null} {variabdlesDiffData.length ? (
- 变量设置 + + {I18n.t('variable_setting')} +
{variabdlesDiffData.map(it => (
@@ -275,22 +284,24 @@ export function DiffContent({ ) : null} {!toolCallConfigIsSame || !toolsIsSame ? (
- 函数 + + {I18n.t('function')} + {toolCallConfigIsSame ? null : (
- 函数 + {I18n.t('function')} {baseItem.toolCallConfig?.tool_choice === ToolChoiceType.Auto - ? '打开 启用函数' - : '关闭 启用函数'} + ? I18n.t('open_enable_function') + : I18n.t('close_enable_function')} {currentItem.toolCallConfig?.tool_choice === ToolChoiceType.Auto - ? '打开 启用函数' - : '关闭 启用函数'} + ? I18n.t('open_enable_function') + : I18n.t('close_enable_function')}
@@ -311,7 +322,7 @@ export function DiffContent({ size="small" strong > - 草稿 + {I18n.t('draft')}
diff --git a/frontend/packages/cozeloop/prompt-pages/src/components/prompt-submit/index.tsx b/frontend/packages/cozeloop/prompt-pages/src/components/prompt-submit/index.tsx index e8215d747..da5a059f5 100644 --- a/frontend/packages/cozeloop/prompt-pages/src/components/prompt-submit/index.tsx +++ b/frontend/packages/cozeloop/prompt-pages/src/components/prompt-submit/index.tsx @@ -10,6 +10,7 @@ import { useShallow } from 'zustand/react/shallow'; import classNames from 'classnames'; import { useRequest } from 'ahooks'; import { EVENT_NAMES, sendEvent } from '@cozeloop/tea-adapter'; +import { I18n } from '@cozeloop/i18n-adapter'; import { getBaseUrl } from '@cozeloop/components'; import { useSpace } from '@cozeloop/biz-hooks-adapter'; import { type Prompt } from '@cozeloop/api-schema/prompt'; @@ -78,7 +79,7 @@ export function PromptSubmit({ const showSuccessModal = () => { const modal = Modal.info({ - title: '提交新版本', + title: I18n.t('submit_new_version'), width: 960, closable: true, content: ( @@ -88,13 +89,13 @@ export function PromptSubmit({ darkModeIcon={} title={ - 提交成功 + {I18n.t('version_submit_success')} } description={
- 接入 CozeLoop SDK 上报数据,进行数据观测 + {I18n.t('cozeloop_sdk_data_report_observation')} { @@ -102,11 +103,11 @@ export function PromptSubmit({ modal.destroy(); }} > - 立即前往 + {I18n.t('go_immediately')} - 对 Prompt 进行效果评估,提升应用效果 + {I18n.t('prompt_effect_evaluation')} { @@ -114,7 +115,7 @@ export function PromptSubmit({ modal.destroy(); }} > - 立即前往 + {I18n.t('go_immediately')}
@@ -122,7 +123,7 @@ export function PromptSubmit({ />
), - okText: '关闭', + okText: I18n.t('close'), }); }; @@ -173,7 +174,7 @@ export function PromptSubmit({ }); }); } else { - setOkButtonText('继续'); + setOkButtonText(I18n.t('continue')); setBasePrompt(undefined); setCurrentPrompt(undefined); formApi.current?.reset(); @@ -187,18 +188,20 @@ export function PromptSubmit({ > versionValidate(val, initVersion)} - placeholder="请输入版本号,版本号格式为a.b.c, 且每段为0-9999" + placeholder={I18n.t('input_version_number')} /> { - if (okButtonText === '继续') { - setOkButtonText('提交'); + if (okButtonText === I18n.t('continue')) { + setOkButtonText(I18n.t('submit')); } else { submitRunAsync(); } @@ -219,10 +222,10 @@ export function PromptSubmit({ className="min-h-[calc(100vh - 140px)]" width={900} visible={visible} - title="提交新版本" + title={I18n.t('submit_new_version')} onCancel={onCancel} - okText={basePrompt ? okButtonText : '提交'} - cancelText="取消" + okText={basePrompt ? okButtonText : I18n.t('submit')} + cancelText={I18n.t('cancel')} onOk={basePrompt ? handleSubmit : submitRunAsync} okButtonProps={{ loading: submitLoading }} height="fit-content" @@ -248,7 +251,7 @@ export function PromptSubmit({ 'cursor-pointer', )} icon={ - okButtonText === '提交' ? ( + okButtonText === I18n.t('submit') ? ( @@ -256,21 +259,21 @@ export function PromptSubmit({ 1 ) } - onClick={() => setOkButtonText('继续')} + onClick={() => setOkButtonText(I18n.t('continue'))} > - 确认版本差异 + {I18n.t('confirm_version_difference')} 2} > - 确认版本信息 + {I18n.t('confirm_version_info')}
- {okButtonText === '继续' ? ( + {okButtonText === I18n.t('continue') ? ( ) : ( submitForm diff --git a/frontend/packages/cozeloop/prompt-pages/src/components/send-msg-area/index.tsx b/frontend/packages/cozeloop/prompt-pages/src/components/send-msg-area/index.tsx index 07c63658e..9e920b866 100644 --- a/frontend/packages/cozeloop/prompt-pages/src/components/send-msg-area/index.tsx +++ b/frontend/packages/cozeloop/prompt-pages/src/components/send-msg-area/index.tsx @@ -17,6 +17,7 @@ import { Prec, PromptBasicEditor, } from '@cozeloop/prompt-components'; +import { I18n } from '@cozeloop/i18n-adapter'; import { useSpace } from '@cozeloop/biz-hooks-adapter'; import { uploadFile } from '@cozeloop/biz-components-adapter'; import { @@ -187,7 +188,7 @@ export function SendMsgArea({ })); } catch (error) { console.info('error', error); - Toast.error('图片上传失败,请稍后重试'); + Toast.error(I18n.t('image_upload_error')); setQueryMsg(v => ({ ...v, parts: (v?.parts || []).filter((it: ContentPartLoop) => it.uid !== uid), @@ -211,13 +212,19 @@ export function SendMsgArea({ for (const item of Array.from(items)) { if (item.type.includes('image')) { if (isMaxImgSizeRef.current) { - Toast.warning(`最多上传${MAX_IMAGE_FILE}张图片`); + Toast.warning( + I18n.t('max_upload_picture_num', { num: MAX_IMAGE_FILE }), + ); return; } const file = item.getAsFile(); if (file) { if (file.size / 1024 > MAX_FILE_SIZE) { - Toast.error(`图片大小不能超过${MAX_FILE_SIZE_MB}MB`); + Toast.error( + I18n.t('image_size_not_exceed_num_mb', { + num: MAX_FILE_SIZE_MB, + }), + ); return; } uploadRef.current?.insert([file], 0); @@ -299,13 +306,13 @@ export function SendMsgArea({ size="mini" onClick={stopStreaming} > - 停止响应 + {I18n.t('stop_respond')} ) : null}
{isCompare ? null : ( - + } onClick={clearHistoricChat} @@ -362,7 +369,7 @@ export function SendMsgArea({ height={44} variables={variables?.filter(it => it.type === VariableType.String)} readOnly={streaming || inputReadonly} - linePlaceholder="请输入问题测试大模型回复,回车发送,Shift+回车换行" + linePlaceholder={I18n.t('input_question_tip')} customExtensions={extensions} onFocus={() => setEditorActive(true)} onBlur={() => setEditorActive(false)} @@ -371,7 +378,7 @@ export function SendMsgArea({
{isCompare ? ( - + } onClick={clearHistoricChat} @@ -390,9 +397,19 @@ export function SendMsgArea({ maxSize={MAX_FILE_SIZE} limit={canUploadFileSize} onSizeError={() => - Toast.error(`图片大小不能超过${MAX_FILE_SIZE_MB}MB`) + Toast.error( + Toast.error( + I18n.t('image_size_not_exceed_num_mb', { + num: MAX_FILE_SIZE_MB, + }), + ), + ) + } + onExceed={() => + Toast.warning( + I18n.t('max_upload_picture_num', { num: MAX_IMAGE_FILE }), + ) } - onExceed={() => Toast.warning(`最多上传${MAX_IMAGE_FILE}张图片`)} multiple fileList={imgParts.map(it => ({ uid: it.uid || '', @@ -418,7 +435,7 @@ export function SendMsgArea({ type="tertiary" icon={} > - 该模型不支持上传图片 + {I18n.t('model_not_support_picture')} )}
@@ -427,12 +444,12 @@ export function SendMsgArea({ onClick={handleSendMessage} disabled={executeDisabled} > - 运行 + {I18n.t('run')}
- 内容由AI生成,无法确保真实准确,仅供参考。 + {I18n.t('generated_by_ai_tip')}
); diff --git a/frontend/packages/cozeloop/prompt-pages/src/components/tools-card/index.tsx b/frontend/packages/cozeloop/prompt-pages/src/components/tools-card/index.tsx index cb2744d50..4871ff4af 100644 --- a/frontend/packages/cozeloop/prompt-pages/src/components/tools-card/index.tsx +++ b/frontend/packages/cozeloop/prompt-pages/src/components/tools-card/index.tsx @@ -4,10 +4,14 @@ /* eslint-disable complexity */ import { useShallow } from 'zustand/react/shallow'; import { EVENT_NAMES, sendEvent } from '@cozeloop/tea-adapter'; +import { I18n } from '@cozeloop/i18n-adapter'; import { CollapseCard } from '@cozeloop/components'; import { useModalData } from '@cozeloop/base-hooks'; import { ToolChoiceType } from '@cozeloop/api-schema/prompt'; -import { IconCozPlus, IconCozWarningCircle } from '@coze-arch/coze-design/icons'; +import { + IconCozPlus, + IconCozWarningCircle, +} from '@coze-arch/coze-design/icons'; import { Button, Space, Switch, Tag, Typography } from '@coze-arch/coze-design'; import { usePromptStore } from '@/store/use-prompt-store'; @@ -82,11 +86,11 @@ export function ToolsCard({ uid, defaultVisible }: ToolsCardProps) { subInfo={ functionCallEnabled || !currentModel ? null : ( }> - 模型不支持 + {I18n.t('model_not_support')} ) } - title={函数} + title={{I18n.t('function')}} extra={
- 启用函数 + + {I18n.t('enable_function')} +
{isCompare ? null : (
- 单步调试 + + {I18n.t('single_step_debugging')} +
)}
@@ -163,7 +171,7 @@ export function ToolsCard({ uid, defaultVisible }: ToolsCardProps) { onClick={() => toolModal.open()} disabled={currentReadonly || !functionCallEnabled} > - 新增函数 + {I18n.t('new_function')}
diff --git a/frontend/packages/cozeloop/prompt-pages/src/components/tools-item/index.tsx b/frontend/packages/cozeloop/prompt-pages/src/components/tools-item/index.tsx index 162fbfd78..3a49a63ce 100644 --- a/frontend/packages/cozeloop/prompt-pages/src/components/tools-item/index.tsx +++ b/frontend/packages/cozeloop/prompt-pages/src/components/tools-item/index.tsx @@ -1,5 +1,6 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: Apache-2.0 +import { I18n } from '@cozeloop/i18n-adapter'; import { type Tool } from '@cozeloop/api-schema/prompt'; import { IconCozTrashCan } from '@coze-arch/coze-design/icons'; import { IconButton, Popconfirm, Typography } from '@coze-arch/coze-design'; @@ -39,10 +40,10 @@ export function ToolItem({ {!showDelete ? null : ( { @@ -75,7 +76,7 @@ export function ToolItem({
- 模拟值: + {I18n.t('mock_value')}: @@ -250,7 +251,7 @@ export function ToolModal({ setMockValue('Sunny'); }} > - 插入模版 + {I18n.t('insert_template')} )}
@@ -265,7 +266,7 @@ export function ToolModal({
- 默认模拟值 + {I18n.t('default_mock_value')}