chore: update zh i18n

This commit is contained in:
Steven 2023-09-30 09:03:52 +08:00
parent 7795b17fd1
commit 690e14e4ed
11 changed files with 113 additions and 46 deletions

View File

@ -11,7 +11,14 @@
"language": "Language",
"search": "Search",
"email": "Email",
"password": "Password"
"password": "Password",
"account": "Account"
},
"auth": {
"sign-in": "Sign in",
"sign-up": "Sign up",
"sign-out": "Sign out",
"create-your-account": "Create your account"
},
"analytics": {
"self": "Analytics",
@ -38,5 +45,30 @@
"description": "Visible to everyone on the internet"
}
}
},
"user": {
"self": "User",
"nickname": "Nickname",
"email": "Email",
"role": "Role",
"profile": "Profile",
"action": {
"add-user": "Add user"
}
},
"settings": {
"self": "Setting",
"preference": {
"self": "Preference",
"color-theme": "Color theme"
},
"workspace": {
"self": "Workspace settings",
"custom-style": "Custom style",
"enable-user-signup": {
"self": "Enable user signup",
"description": "Once enabled, other users can signup."
}
}
}
}

View File

@ -11,7 +11,14 @@
"language": "语言",
"search": "搜索",
"email": "邮箱",
"password": "密码"
"password": "密码",
"account": "账号"
},
"auth": {
"sign-in": "登录",
"sign-up": "注册",
"sign-out": "退出登录",
"create-your-account": "创建账号"
},
"analytics": {
"self": "分析",
@ -38,5 +45,30 @@
"description": "对任何人可见"
}
}
},
"user": {
"self": "用户",
"nickname": "昵称",
"email": "邮箱",
"role": "角色",
"profile": "账号",
"action": {
"add-user": "添加用户"
}
},
"settings": {
"self": "设置",
"preference": {
"self": "偏好设置",
"color-theme": "主题"
},
"workspace": {
"self": "系统设置",
"custom-style": "自定义样式",
"enable-user-signup": {
"self": "启用用户注册",
"description": "允许其他用户注册新账号"
}
}
}
}

View File

@ -1,5 +1,6 @@
import { Avatar } from "@mui/joy";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import useWorkspaceStore from "@/stores/v1/workspace";
import { PlanType } from "@/types/proto/api/v2/subscription_service";
@ -10,6 +11,7 @@ import Icon from "./Icon";
import Dropdown from "./common/Dropdown";
const Header: React.FC = () => {
const { t } = useTranslation();
const workspaceStore = useWorkspaceStore();
const currentUser = useUserStore().getCurrentUser();
const [showAboutDialog, setShowAboutDialog] = useState<boolean>(false);
@ -52,27 +54,27 @@ const Header: React.FC = () => {
to="/setting/general"
className="w-full px-2 flex flex-row justify-start items-center text-left dark:text-gray-400 leading-8 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-800 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:opacity-60"
>
<Icon.User className="w-4 h-auto mr-2" /> Profile
<Icon.User className="w-4 h-auto mr-2" /> {t("user.profile")}
</Link>
{isAdmin && (
<Link
to="/setting/workspace"
className="w-full px-2 flex flex-row justify-start items-center text-left dark:text-gray-400 leading-8 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-800 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:opacity-60"
>
<Icon.Settings className="w-4 h-auto mr-2" /> Setting
<Icon.Settings className="w-4 h-auto mr-2" /> {t("settings.self")}
</Link>
)}
<button
className="w-full px-2 flex flex-row justify-start items-center text-left dark:text-gray-400 leading-8 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-800 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:opacity-60"
onClick={() => setShowAboutDialog(true)}
>
<Icon.Info className="w-4 h-auto mr-2" /> About
<Icon.Info className="w-4 h-auto mr-2" /> {t("common.about")}
</button>
<button
className="w-full px-2 flex flex-row justify-start items-center text-left dark:text-gray-400 leading-8 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-800 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:opacity-60"
onClick={() => handleSignOutButtonClick()}
>
<Icon.LogOut className="w-4 h-auto mr-2" /> Sign out
<Icon.LogOut className="w-4 h-auto mr-2" /> {t("auth.sign-out")}
</button>
</>
}

View File

@ -15,7 +15,7 @@ const AccountSection: React.FC = () => {
return (
<>
<div className="w-full flex flex-col justify-start items-start gap-y-2">
<p className="text-base font-semibold leading-6 text-gray-900 dark:text-gray-500">Account</p>
<p className="text-base font-semibold leading-6 text-gray-900 dark:text-gray-500">{t("common.account")}</p>
<p className="flex flex-row justify-start items-center mt-2 dark:text-gray-400">
<span className="text-xl">{currentUser.nickname}</span>
{isAdmin && <span className="ml-2 bg-blue-600 text-white px-2 leading-6 text-sm rounded-full">Admin</span>}

View File

@ -1,12 +1,14 @@
import { Button, IconButton } from "@mui/joy";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
import useUserStore from "../../stores/v1/user";
import { showCommonDialog } from "../Alert";
import CreateUserDialog from "../CreateUserDialog";
import Icon from "../Icon";
const MemberSection = () => {
const { t } = useTranslation();
const userStore = useUserStore();
const [showCreateUserDialog, setShowCreateUserDialog] = useState<boolean>(false);
const [currentEditingUser, setCurrentEditingUser] = useState<User | undefined>(undefined);
@ -43,7 +45,7 @@ const MemberSection = () => {
<div className="w-full">
<div className="sm:flex sm:items-center">
<div className="sm:flex-auto">
<p className="text-base font-semibold leading-6 text-gray-900 dark:text-gray-500">Users</p>
<p className="text-base font-semibold leading-6 text-gray-900 dark:text-gray-500">{t("user.self")}</p>
<p className="mt-2 text-sm text-gray-700 dark:text-gray-600">
A list of all the users in your workspace including their nickname, email and role.
</p>
@ -57,7 +59,7 @@ const MemberSection = () => {
setCurrentEditingUser(undefined);
}}
>
Add user
{t("user.action.add-user")}
</Button>
</div>
</div>
@ -68,20 +70,20 @@ const MemberSection = () => {
<thead>
<tr>
<th scope="col" className="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 dark:text-gray-500">
Nickname
{t("user.nickname")}
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-500">
Email
{t("user.email")}
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-500">
Role
{t("user.role")}
</th>
<th scope="col" className="relative py-3.5 pl-3 pr-4">
<span className="sr-only">Edit</span>
<span className="sr-only">{t("common.edit")}</span>
</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
<tbody className="divide-y divide-gray-200 dark:divide-zinc-800">
{userList.map((user) => (
<tr key={user.email}>
<td className="whitespace-nowrap py-4 pl-4 pr-3 text-sm text-gray-900 dark:text-gray-500">{user.nickname}</td>

View File

@ -1,6 +1,5 @@
import { Option, Select } from "@mui/joy";
import { useTranslation } from "react-i18next";
import { releaseGuard } from "@/helpers/utils";
import { UserSetting, UserSetting_ColorTheme, UserSetting_Locale } from "@/types/proto/api/v2/user_setting_service";
import useUserStore from "../../stores/v1/user";
import BetaBadge from "../BetaBadge";
@ -61,10 +60,10 @@ const PreferenceSection: React.FC = () => {
return (
<>
<div className="w-full flex flex-col justify-start items-start gap-y-2">
<p className="text-base font-semibold leading-6 text-gray-900 dark:text-gray-500">Preference</p>
<p className="text-base font-semibold leading-6 text-gray-900 dark:text-gray-500">{t("settings.preference.self")}</p>
<div className="w-full flex flex-row justify-between items-center">
<div className="flex flex-row justify-start items-center gap-x-1">
<span className="dark:text-gray-400">Color Theme</span>
<span className="dark:text-gray-400">{t("settings.preference.color-theme")}</span>
</div>
<Select defaultValue={colorTheme} onChange={(_, value) => handleSelectColorTheme(value as UserSetting_ColorTheme)}>
{colorThemeOptions.map((option) => {
@ -76,23 +75,21 @@ const PreferenceSection: React.FC = () => {
})}
</Select>
</div>
{releaseGuard() && (
<div className="w-full flex flex-row justify-between items-center">
<div className="flex flex-row justify-start items-center gap-x-1">
<span className="dark:text-gray-400">{t("common.language")}</span>
<BetaBadge />
</div>
<Select defaultValue={language} onChange={(_, value) => handleSelectLanguage(value as UserSetting_Locale)}>
{languageOptions.map((option) => {
return (
<Option key={option.value} value={option.value}>
{option.label}
</Option>
);
})}
</Select>
<div className="w-full flex flex-row justify-between items-center">
<div className="flex flex-row justify-start items-center gap-x-1">
<span className="dark:text-gray-400">{t("common.language")}</span>
<BetaBadge />
</div>
)}
<Select defaultValue={language} onChange={(_, value) => handleSelectLanguage(value as UserSetting_Locale)}>
{languageOptions.map((option) => {
return (
<Option key={option.value} value={option.value}>
{option.label}
</Option>
);
})}
</Select>
</div>
</div>
</>
);

View File

@ -2,11 +2,13 @@ import { Button, Checkbox, Textarea } from "@mui/joy";
import { isEqual } from "lodash-es";
import { useRef, useState } from "react";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
import { workspaceServiceClient } from "@/grpcweb";
import useWorkspaceStore from "@/stores/v1/workspace";
import { WorkspaceSetting } from "@/types/proto/api/v2/workspace_service";
const WorkspaceSection: React.FC = () => {
const { t } = useTranslation();
const workspaceStore = useWorkspaceStore();
const [workspaceSetting, setWorkspaceSetting] = useState<WorkspaceSetting>(workspaceStore.setting);
const originalWorkspaceSetting = useRef<WorkspaceSetting>(workspaceStore.setting);
@ -56,9 +58,9 @@ const WorkspaceSection: React.FC = () => {
return (
<div className="w-full flex flex-col justify-start items-start space-y-4">
<p className="text-base font-semibold leading-6 text-gray-900 dark:text-gray-500">Workspace settings</p>
<p className="text-base font-semibold leading-6 text-gray-900 dark:text-gray-500">{t("settings.workspace.self")}</p>
<div className="w-full flex flex-col justify-start items-start">
<p className="mt-2 dark:text-gray-400">Custom style</p>
<p className="mt-2 dark:text-gray-400">{t("settings.workspace.custom-style")}</p>
<Textarea
className="w-full mt-2"
minRows={2}
@ -69,15 +71,15 @@ const WorkspaceSection: React.FC = () => {
</div>
<div className="w-full flex flex-col justify-start items-start">
<Checkbox
label="Enable user signup"
label={t("settings.workspace.enable-user-signup.self")}
checked={workspaceSetting.enableSignup}
onChange={(event) => handleEnableSignUpChange(event.target.checked)}
/>
<p className="mt-2 text-gray-500">Once enabled, other users can signup.</p>
<p className="mt-2 text-gray-500">{t("settings.workspace.enable-user-signup.description")}</p>
</div>
<div>
<Button variant="outlined" color="neutral" disabled={!allowSave} onClick={handleSaveWorkspaceSetting}>
Save
{t("common.save")}
</Button>
</div>
</div>

View File

@ -4,7 +4,7 @@ import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { Outlet } from "react-router-dom";
import useNavigateTo from "@/hooks/useNavigateTo";
import { UserSetting_ColorTheme } from "@/types/proto/api/v2/user_setting_service";
import { UserSetting_ColorTheme, UserSetting_Locale } from "@/types/proto/api/v2/user_setting_service";
import Header from "../components/Header";
import useUserStore from "../stores/v1/user";
@ -34,7 +34,7 @@ const Root: React.FC = () => {
return;
}
if (isEqual(currentUserSetting.locale, "LOCALE_ZH")) {
if (isEqual(currentUserSetting.locale, UserSetting_Locale.LOCALE_ZH)) {
i18n.changeLanguage("zh");
} else {
i18n.changeLanguage("en");

View File

@ -71,7 +71,7 @@ const Home: React.FC = () => {
{loadingState.isLoading ? (
<div className="py-12 w-full flex flex-row justify-center items-center opacity-80 dark:text-gray-500">
<Icon.Loader className="mr-2 w-5 h-auto animate-spin" />
loading
{t("common.loading")}
</div>
) : orderedShortcutList.length === 0 ? (
<div className="py-16 w-full flex flex-col justify-center items-center text-gray-400">

View File

@ -100,7 +100,7 @@ const SignIn: React.FC = () => {
disabled={actionBtnLoadingState.isLoading || !allowConfirm}
onClick={handleSigninBtnClick}
>
Sign in
{t("auth.sign-in")}
</Button>
</div>
</form>
@ -108,7 +108,7 @@ const SignIn: React.FC = () => {
<p className="w-full mt-4 text-sm">
<span className="dark:text-gray-500">{"Don't have an account yet?"}</span>
<Link to="/auth/signup" className="cursor-pointer ml-2 text-blue-600 hover:underline">
Sign up
{t("auth.sign-up")}
</Link>
</p>
)}

View File

@ -81,7 +81,7 @@ const SignUp: React.FC = () => {
<img id="logo-img" src="/logo.png" className="w-12 h-auto mr-2 -mt-1" alt="logo" />
<span className="text-3xl opacity-80 dark:text-gray-500">Slash</span>
</div>
<p className="w-full text-2xl mt-6 dark:text-gray-500">Create your account</p>
<p className="w-full text-2xl mt-6 dark:text-gray-500">{t("auth.create-your-account")}</p>
<form className="w-full mt-4" onSubmit={handleSignupBtnClick}>
<div className={`flex flex-col justify-start items-start w-full ${actionBtnLoadingState.isLoading ? "opacity-80" : ""}`}>
<div className="w-full flex flex-col mb-2">
@ -112,14 +112,14 @@ const SignUp: React.FC = () => {
disabled={actionBtnLoadingState.isLoading || !allowConfirm}
onClick={handleSignupBtnClick}
>
Sign up
{t("auth.sign-up")}
</Button>
</div>
</form>
<p className="w-full mt-4 text-sm">
<span className="dark:text-gray-500">{"Already has an account?"}</span>
<Link to="/auth" className="cursor-pointer ml-2 text-blue-600 hover:underline">
Sign in
{t("auth.sign-in")}
</Link>
</p>
</div>