From 9a71edfeb06ddfa186b90ff24770dcb106c73ffc Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 10:50:31 +0000 Subject: [PATCH] feat: add i18n support for initialization page and fix plugin loading text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add language selector to register/initialization page with Chinese and English options - Add register section translations to both zh-Hans.ts and en-US.ts - Replace hardcoded Chinese texts in register page with i18n translation calls - Fix hardcoded '加载中...' text in plugin configuration dialog to use t('plugins.loading') - Follow existing login page pattern for language selector implementation - Maintain consistent UI/UX design with proper language switching functionality Co-Authored-By: Junyan Qin , 秦骏言 in Chinese, you can call me my english name Rock Chin. --- .../plugin-form/PluginForm.tsx | 2 +- web/src/app/register/page.tsx | 89 ++++++++++++++----- web/src/i18n/locales/en-US.ts | 9 ++ web/src/i18n/locales/zh-Hans.ts | 8 ++ 4 files changed, 87 insertions(+), 21 deletions(-) diff --git a/web/src/app/home/plugins/plugin-installed/plugin-form/PluginForm.tsx b/web/src/app/home/plugins/plugin-installed/plugin-form/PluginForm.tsx index 35e8be8a..7ffd6796 100644 --- a/web/src/app/home/plugins/plugin-installed/plugin-form/PluginForm.tsx +++ b/web/src/app/home/plugins/plugin-installed/plugin-form/PluginForm.tsx @@ -72,7 +72,7 @@ export default function PluginForm({ }; if (!pluginInfo || !pluginConfig) { - return
加载中...
; + return
{t('plugins.loading')}
; } function deletePlugin() { diff --git a/web/src/app/register/page.tsx b/web/src/app/register/page.tsx index c1a38f58..f5ef84bc 100644 --- a/web/src/app/register/page.tsx +++ b/web/src/app/register/page.tsx @@ -8,6 +8,13 @@ import { CardTitle, CardDescription, } from '@/components/ui/card'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import * as z from 'zod'; @@ -19,23 +26,28 @@ import { FormLabel, FormMessage, } from '@/components/ui/form'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { httpClient } from '@/app/infra/http/HttpClient'; import { useRouter } from 'next/navigation'; -import { Mail, Lock } from 'lucide-react'; +import { Mail, Lock, Globe } from 'lucide-react'; import langbotIcon from '@/app/assets/langbot-logo.webp'; import { toast } from 'sonner'; +import { useTranslation } from 'react-i18next'; +import i18n from '@/i18n'; -const formSchema = z.object({ - email: z.string().email('请输入有效的邮箱地址'), - password: z.string().min(1, '请输入密码'), -}); +const formSchema = (t: (key: string) => string) => + z.object({ + email: z.string().email(t('common.invalidEmail')), + password: z.string().min(1, t('common.emptyPassword')), + }); export default function Register() { const router = useRouter(); + const { t } = useTranslation(); + const [currentLanguage, setCurrentLanguage] = useState(i18n.language); - const form = useForm>({ - resolver: zodResolver(formSchema), + const form = useForm>>({ + resolver: zodResolver(formSchema(t)), defaultValues: { email: '', password: '', @@ -43,9 +55,31 @@ export default function Register() { }); useEffect(() => { + judgeLanguage(); getIsInitialized(); }, []); + const judgeLanguage = () => { + const language = navigator.language; + if (language) { + let lang = 'zh-Hans'; + if (language === 'zh-CN') { + lang = 'zh-Hans'; + } else { + lang = 'en-US'; + } + i18n.changeLanguage(lang); + setCurrentLanguage(lang); + localStorage.setItem('langbot_language', lang); + } + }; + + const handleLanguageChange = (value: string) => { + i18n.changeLanguage(value); + setCurrentLanguage(value); + localStorage.setItem('langbot_language', value); + }; + function getIsInitialized() { httpClient .checkIfInited() @@ -59,7 +93,7 @@ export default function Register() { }); } - function onSubmit(values: z.infer) { + function onSubmit(values: z.infer>) { handleRegister(values.email, values.password); } @@ -68,31 +102,46 @@ export default function Register() { .initUser(username, password) .then((res) => { console.log('init user success: ', res); - toast.success('初始化成功 请登录'); + toast.success(t('register.initSuccess')); router.push('/login'); }) .catch((err) => { console.log('init user error: ', err); - toast.error('初始化失败:' + err.message); + toast.error(t('register.initFailed') + err.message); }); } return (
- + +
+ +
LangBot - 初始化 LangBot 👋 + {t('register.title')} - 这是您首次启动 LangBot + {t('register.description')}
- 您填写的邮箱和密码将作为初始管理员账号 + {t('register.adminAccountNote')}
@@ -103,12 +152,12 @@ export default function Register() { name="email" render={({ field }) => ( - 邮箱 + {t('common.email')}
@@ -124,13 +173,13 @@ export default function Register() { name="password" render={({ field }) => ( - 密码 + {t('common.password')}
@@ -142,7 +191,7 @@ export default function Register() { /> diff --git a/web/src/i18n/locales/en-US.ts b/web/src/i18n/locales/en-US.ts index f6195c9e..3d025e4e 100644 --- a/web/src/i18n/locales/en-US.ts +++ b/web/src/i18n/locales/en-US.ts @@ -203,6 +203,15 @@ const enUS = { 'Are you sure you want to delete this pipeline? Bots bound to this pipeline will not work.', defaultPipelineCannotDelete: 'Default pipeline cannot be deleted', }, + register: { + title: 'Initialize LangBot 👋', + description: 'This is your first time starting LangBot', + adminAccountNote: + 'The email and password you fill in will be used as the initial administrator account', + register: 'Register', + initSuccess: 'Initialization successful, please login', + initFailed: 'Initialization failed: ', + }, }; export default enUS; diff --git a/web/src/i18n/locales/zh-Hans.ts b/web/src/i18n/locales/zh-Hans.ts index d0271c38..b8fb06ce 100644 --- a/web/src/i18n/locales/zh-Hans.ts +++ b/web/src/i18n/locales/zh-Hans.ts @@ -198,6 +198,14 @@ const zhHans = { '你确定要删除这个流水线吗?已绑定此流水线的机器人将无法使用。', defaultPipelineCannotDelete: '默认流水线不可删除', }, + register: { + title: '初始化 LangBot 👋', + description: '这是您首次启动 LangBot', + adminAccountNote: '您填写的邮箱和密码将作为初始管理员账号', + register: '注册', + initSuccess: '初始化成功 请登录', + initFailed: '初始化失败:', + }, }; export default zhHans;