chore: update i18n (#215)

This commit is contained in:
ChasLui 2022-09-15 06:53:51 +08:00 committed by GitHub
parent 54db6eda04
commit 7e8d1128f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 109 additions and 43 deletions

View File

@ -20,6 +20,7 @@ const ArchivedMemo: React.FC<Props> = (props: Props) => {
archivedAtStr: utils.getDateTimeString(propsMemo.updatedTs ?? Date.now()), archivedAtStr: utils.getDateTimeString(propsMemo.updatedTs ?? Date.now()),
}; };
const { t } = useI18n(); const { t } = useI18n();
const [showConfirmDeleteBtn, toggleConfirmDeleteBtn] = useToggle(false); const [showConfirmDeleteBtn, toggleConfirmDeleteBtn] = useToggle(false);
const handleDeleteMemoClick = async () => { const handleDeleteMemoClick = async () => {
@ -43,7 +44,7 @@ const ArchivedMemo: React.FC<Props> = (props: Props) => {
rowStatus: "NORMAL", rowStatus: "NORMAL",
}); });
await memoService.fetchMemos(); await memoService.fetchMemos();
toastHelper.info("Restored successfully"); toastHelper.info(t("common.restored-successfully"));
} catch (error: any) { } catch (error: any) {
console.error(error); console.error(error);
toastHelper.error(error.response.data.message); toastHelper.error(error.response.data.message);
@ -59,7 +60,9 @@ const ArchivedMemo: React.FC<Props> = (props: Props) => {
return ( return (
<div className={`memo-wrapper archived-memo ${"memos-" + memo.id}`} onMouseLeave={handleMouseLeaveMemoWrapper}> <div className={`memo-wrapper archived-memo ${"memos-" + memo.id}`} onMouseLeave={handleMouseLeaveMemoWrapper}>
<div className="memo-top-wrapper"> <div className="memo-top-wrapper">
<span className="time-text">Archived at {memo.archivedAtStr}</span> <span className="time-text">
{t("common.archived-at")} {memo.archivedAtStr}
</span>
<div className="btns-container"> <div className="btns-container">
<span className="btn restore-btn" onClick={handleRestoreMemoClick}> <span className="btn restore-btn" onClick={handleRestoreMemoClick}>
{t("common.restore")} {t("common.restore")}

View File

@ -23,7 +23,7 @@ const ChangeMemoCreatedTsDialog: React.FC<Props> = (props: Props) => {
const datetime = dayjs(memo.createdTs).format("YYYY-MM-DDTHH:mm"); const datetime = dayjs(memo.createdTs).format("YYYY-MM-DDTHH:mm");
setCreatedAt(datetime); setCreatedAt(datetime);
} else { } else {
toastHelper.error("Memo not found."); toastHelper.error(t("common.memo-not-found"));
destroy(); destroy();
} }
}, []); }, []);
@ -42,7 +42,7 @@ const ChangeMemoCreatedTsDialog: React.FC<Props> = (props: Props) => {
const createdTs = dayjs(createdAt).unix(); const createdTs = dayjs(createdAt).unix();
if (createdTs > nowTs) { if (createdTs > nowTs) {
toastHelper.error("Invalid created datetime."); toastHelper.error(t("common.invalid-created-datetime"));
return; return;
} }
@ -51,7 +51,7 @@ const ChangeMemoCreatedTsDialog: React.FC<Props> = (props: Props) => {
id: memoId, id: memoId,
createdTs, createdTs,
}); });
toastHelper.info("Memo created datetime changed."); toastHelper.info(t("common.memo-updated-datetime"));
handleCloseBtnClick(); handleCloseBtnClick();
} catch (error: any) { } catch (error: any) {
console.error(error); console.error(error);
@ -62,7 +62,7 @@ const ChangeMemoCreatedTsDialog: React.FC<Props> = (props: Props) => {
return ( return (
<> <>
<div className="dialog-header-container"> <div className="dialog-header-container">
<p className="title-text">Change memo created time</p> <p className="title-text">{t("common.change-memo-created-time")}</p>
<button className="btn close-btn" onClick={handleCloseBtnClick}> <button className="btn close-btn" onClick={handleCloseBtnClick}>
<Icon.X /> <Icon.X />
</button> </button>

View File

@ -17,7 +17,7 @@ const validateConfig: ValidatorConfig = {
type Props = DialogProps; type Props = DialogProps;
const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => { const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
const { t } = useI18n(); const { t, locale } = useI18n();
const [newPassword, setNewPassword] = useState(""); const [newPassword, setNewPassword] = useState("");
const [newPasswordAgain, setNewPasswordAgain] = useState(""); const [newPasswordAgain, setNewPasswordAgain] = useState("");
@ -41,19 +41,19 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
const handleSaveBtnClick = async () => { const handleSaveBtnClick = async () => {
if (newPassword === "" || newPasswordAgain === "") { if (newPassword === "" || newPasswordAgain === "") {
toastHelper.error("Please fill in all fields."); toastHelper.error(t("common.fill-all"));
return; return;
} }
if (newPassword !== newPasswordAgain) { if (newPassword !== newPasswordAgain) {
toastHelper.error("New passwords do not match."); toastHelper.error(t("common.new-password-not-match"));
setNewPasswordAgain(""); setNewPasswordAgain("");
return; return;
} }
const passwordValidResult = validate(newPassword, validateConfig); const passwordValidResult = validate(newPassword, validateConfig);
if (!passwordValidResult.result) { if (!passwordValidResult.result) {
toastHelper.error("Password " + passwordValidResult.reason); toastHelper.error(t("common.password") + locale === "zh" ? "" : " " + passwordValidResult.reason);
return; return;
} }
@ -63,7 +63,7 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
id: user.id, id: user.id,
password: newPassword, password: newPassword,
}); });
toastHelper.info("Password changed."); toastHelper.info(t("common.password") + t("common.changed"));
handleCloseBtnClick(); handleCloseBtnClick();
} catch (error: any) { } catch (error: any) {
console.error(error); console.error(error);
@ -74,17 +74,22 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
return ( return (
<> <>
<div className="dialog-header-container"> <div className="dialog-header-container">
<p className="title-text">Change Password</p> <p className="title-text">{t("common.password" + " " + t("common.change"))}</p>
<button className="btn close-btn" onClick={handleCloseBtnClick}> <button className="btn close-btn" onClick={handleCloseBtnClick}>
<Icon.X /> <Icon.X />
</button> </button>
</div> </div>
<div className="dialog-content-container"> <div className="dialog-content-container">
<label className="form-label input-form-label"> <label className="form-label input-form-label">
<input type="password" placeholder="New passworld" value={newPassword} onChange={handleNewPasswordChanged} /> <input type="password" placeholder={t("common.new-password")} value={newPassword} onChange={handleNewPasswordChanged} />
</label> </label>
<label className="form-label input-form-label"> <label className="form-label input-form-label">
<input type="password" placeholder="Repeat the new password" value={newPasswordAgain} onChange={handleNewPasswordAgainChanged} /> <input
type="password"
placeholder={t("common.repeat-new-password")}
value={newPasswordAgain}
onChange={handleNewPasswordAgainChanged}
/>
</label> </label>
<div className="btns-container"> <div className="btns-container">
<span className="btn cancel-btn" onClick={handleCloseBtnClick}> <span className="btn cancel-btn" onClick={handleCloseBtnClick}>

View File

@ -45,7 +45,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
const handleSaveBtnClick = async () => { const handleSaveBtnClick = async () => {
if (!title) { if (!title) {
toastHelper.error("Title is required"); toastHelper.error(t("shortcut-list.title-required"));
return; return;
} }
@ -73,7 +73,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
if (filters.length > 0) { if (filters.length > 0) {
const lastFilter = filters[filters.length - 1]; const lastFilter = filters[filters.length - 1];
if (lastFilter.value.value === "") { if (lastFilter.value.value === "") {
toastHelper.info("Please fill in previous filter value"); toastHelper.info(t("shortcut-list.fill-previous"));
return; return;
} }
} }
@ -110,7 +110,13 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
<div className="dialog-content-container"> <div className="dialog-content-container">
<div className="form-item-container input-form-container"> <div className="form-item-container input-form-container">
<span className="normal-text">{t("common.title")}</span> <span className="normal-text">{t("common.title")}</span>
<input className="title-input" type="text" placeholder="shortcut title" value={title} onChange={handleTitleInputChange} /> <input
className="title-input"
type="text"
placeholder={t("common.shortcut-title")}
value={title}
onChange={handleTitleInputChange}
/>
</div> </div>
<div className="form-item-container filter-form-container"> <div className="form-item-container filter-form-container">
<span className="normal-text">{t("common.filter")}</span> <span className="normal-text">{t("common.filter")}</span>

View File

@ -105,7 +105,7 @@ const Memo: React.FC<Props> = (props: Props) => {
if (memoTemp) { if (memoTemp) {
showMemoCardDialog(memoTemp); showMemoCardDialog(memoTemp);
} else { } else {
toastHelper.error("Memo Not Found"); toastHelper.error(t("common.memo-not-found"));
targetEl.classList.remove("memo-link-text"); targetEl.classList.remove("memo-link-text");
} }
} else if (targetEl.className === "tag-span") { } else if (targetEl.className === "tag-span") {

View File

@ -12,6 +12,7 @@ import Selector from "./common/Selector";
import MemoContent from "./MemoContent"; import MemoContent from "./MemoContent";
import MemoResources from "./MemoResources"; import MemoResources from "./MemoResources";
import showChangeMemoCreatedTsDialog from "./ChangeMemoCreatedTsDialog"; import showChangeMemoCreatedTsDialog from "./ChangeMemoCreatedTsDialog";
import useI18n from "../hooks/useI18n";
import "../less/memo-card-dialog.less"; import "../less/memo-card-dialog.less";
interface LinkedMemo extends Memo { interface LinkedMemo extends Memo {
@ -30,6 +31,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
}); });
const [linkMemos, setLinkMemos] = useState<LinkedMemo[]>([]); const [linkMemos, setLinkMemos] = useState<LinkedMemo[]>([]);
const [linkedMemos, setLinkedMemos] = useState<LinkedMemo[]>([]); const [linkedMemos, setLinkedMemos] = useState<LinkedMemo[]>([]);
const { t } = useI18n();
useEffect(() => { useEffect(() => {
const fetchLinkedMemos = async () => { const fetchLinkedMemos = async () => {
@ -95,7 +97,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
setLinkedMemos([]); setLinkedMemos([]);
setMemo(nextMemo); setMemo(nextMemo);
} else { } else {
toastHelper.error("Memo Not Found"); toastHelper.error(t("common.memo-not-found"));
targetEl.classList.remove("memo-link-text"); targetEl.classList.remove("memo-link-text");
} }
} }

View File

@ -110,7 +110,7 @@ const MemoEditor = () => {
const { type } = file; const { type } = file;
if (!type.startsWith("image")) { if (!type.startsWith("image")) {
toastHelper.error("Only image file supported."); toastHelper.error(t("editor.only-image-supported"));
return; return;
} }
@ -133,7 +133,7 @@ const MemoEditor = () => {
const handleSaveBtnClick = async (content: string) => { const handleSaveBtnClick = async (content: string) => {
if (content === "") { if (content === "") {
toastHelper.error("Content can't be empty"); toastHelper.error(t("editor.cant-empty"));
return; return;
} }

View File

@ -108,7 +108,7 @@ const MemoList = () => {
))} ))}
<Only when={!isFetching}> <Only when={!isFetching}>
<div className="status-text-container"> <div className="status-text-container">
<p className="status-text">{sortedMemos.length === 0 ? "no memos 🌃" : showMemoFilter ? "" : "all memos are ready 🎉"}</p> <p className="status-text">{sortedMemos.length === 0 ? t("common.no-memos") : showMemoFilter ? "" : t("common.memos-ready")}</p>
</div> </div>
</Only> </Only>
</div> </div>

View File

@ -48,7 +48,7 @@ const PreferencesSection = () => {
const handleCreateUserBtnClick = async () => { const handleCreateUserBtnClick = async () => {
if (isEmpty(state.createUserEmail) || isEmpty(state.createUserPassword)) { if (isEmpty(state.createUserEmail) || isEmpty(state.createUserPassword)) {
toastHelper.error("Please fill out this form"); toastHelper.error(t("common.fill-form"));
return; return;
} }
@ -125,10 +125,10 @@ const PreferencesSection = () => {
<button onClick={handleCreateUserBtnClick}>{t("common.create")}</button> <button onClick={handleCreateUserBtnClick}>{t("common.create")}</button>
</div> </div>
</div> </div>
<p className="title-text">Member list</p> <p className="title-text">{t("setting.member-list")}</p>
<div className="member-container field-container"> <div className="member-container field-container">
<span className="field-text">ID</span> <span className="field-text">ID</span>
<span className="field-text">EMAIL</span> <span className="field-text">{t("common.email")}</span>
<span></span> <span></span>
</div> </div>
{userList.map((user) => ( {userList.map((user) => (
@ -137,7 +137,7 @@ const PreferencesSection = () => {
<span className="field-text email-text">{user.email}</span> <span className="field-text email-text">{user.email}</span>
<div className="buttons-container"> <div className="buttons-container">
{currentUser?.id === user.id ? ( {currentUser?.id === user.id ? (
<span className="tip-text">Yourself</span> <span className="tip-text">{t("common.yourself")}</span>
) : ( ) : (
<Dropdown className="actions-dropdown"> <Dropdown className="actions-dropdown">
{user.rowStatus === "NORMAL" ? ( {user.rowStatus === "NORMAL" ? (

View File

@ -16,7 +16,7 @@ const validateConfig: ValidatorConfig = {
}; };
const MyAccountSection = () => { const MyAccountSection = () => {
const { t } = useI18n(); const { t, locale } = useI18n();
const user = useAppSelector((state) => state.user.user as User); const user = useAppSelector((state) => state.user.user as User);
const [username, setUsername] = useState<string>(user.name); const [username, setUsername] = useState<string>(user.name);
const openAPIRoute = `${window.location.origin}/api/memo?openId=${user.openId}`; const openAPIRoute = `${window.location.origin}/api/memo?openId=${user.openId}`;
@ -33,7 +33,7 @@ const MyAccountSection = () => {
const usernameValidResult = validate(username, validateConfig); const usernameValidResult = validate(username, validateConfig);
if (!usernameValidResult.result) { if (!usernameValidResult.result) {
toastHelper.error("Username " + usernameValidResult.reason); toastHelper.error(t("common.username") + locale === "zh" ? "" : " " + usernameValidResult.reason);
return; return;
} }
@ -42,7 +42,7 @@ const MyAccountSection = () => {
id: user.id, id: user.id,
name: username, name: username,
}); });
toastHelper.info("Username changed"); toastHelper.info(t("common.username") + locale === "zh" ? "" : " " + t("common.changed"));
} catch (error: any) { } catch (error: any) {
console.error(error); console.error(error);
toastHelper.error(error.response.data.message); toastHelper.error(error.response.data.message);

View File

@ -59,7 +59,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
const handleImageOnLoad = (event: React.SyntheticEvent<HTMLImageElement>) => { const handleImageOnLoad = (event: React.SyntheticEvent<HTMLImageElement>) => {
if (event.type === "error") { if (event.type === "error") {
toastHelper.error("Image load failed"); toastHelper.error(t("common.image-load-failed"));
(event.target as HTMLImageElement).remove(); (event.target as HTMLImageElement).remove();
} }
setImgAmount(imgAmount - 1); setImgAmount(imgAmount - 1);

View File

@ -3,6 +3,8 @@
"about": "About", "about": "About",
"email": "Email", "email": "Email",
"password": "Password", "password": "Password",
"new-password": "New passworld",
"repeat-new-password": "Repeat the new password",
"username": "Username", "username": "Username",
"save": "Save", "save": "Save",
"cancel": "Cancel", "cancel": "Cancel",
@ -28,9 +30,27 @@
"back-to-home": "Back to Home", "back-to-home": "Back to Home",
"type": "Type", "type": "Type",
"shortcuts": "Shortcuts", "shortcuts": "Shortcuts",
"shortcut-title": "shortcut title",
"title": "Title", "title": "Title",
"filter": "Filter", "filter": "Filter",
"tags": "Tags" "tags": "Tags",
"no-memos": "no memos 🌃",
"memos-ready": "all memos are ready 🎉",
"yourself": "Yourself",
"archived-at": "Archived at",
"restored-successfully": "Restored successfully",
"memo-updated-datetime":"Memo created datetime changed.",
"invalid-created-datetime": "Invalid created datetime.",
"change-memo-created-time": "Change memo created time",
"memo-not-found": "Memo not found.",
"fill-all": "Please fill in all fields.",
"new-password-not-match": "New passwords do not match.",
"changed": "changed",
"image-load-failed": "Image load failed",
"fill-form": "Please fill out this form",
"login-failed": "Login failed",
"signup-failed": "Signup failed",
"user-not-found": "User not found"
}, },
"slogan": "An open source, self-hosted knowledge base that works with a SQLite db file.", "slogan": "An open source, self-hosted knowledge base that works with a SQLite db file.",
"auth": { "auth": {
@ -63,7 +83,9 @@
"editor": { "editor": {
"editing": "Editing...", "editing": "Editing...",
"save": "Save", "save": "Save",
"placeholder": "Any thoughts..." "placeholder": "Any thoughts...",
"only-image-supported": "Only image file supported.",
"cant-empty": "Content can't be empty"
}, },
"memo": { "memo": {
"view-story": "View Story" "view-story": "View Story"
@ -75,7 +97,9 @@
"create-shortcut": "Create Shortcut", "create-shortcut": "Create Shortcut",
"edit-shortcut": "Edit Shortcut", "edit-shortcut": "Edit Shortcut",
"new-filter": "New Filter", "new-filter": "New Filter",
"eligible-memo": "eligible memo" "eligible-memo": "eligible memo",
"fill-previous": "Please fill in previous filter value",
"title-required": "Title is required"
}, },
"tag-list": { "tag-list": {
"tip-text": "Enter `#tag ` to create" "tip-text": "Enter `#tag ` to create"
@ -87,6 +111,7 @@
"my-account": "My Account", "my-account": "My Account",
"preference": "Preference", "preference": "Preference",
"member": "Member", "member": "Member",
"member-list": "Member list",
"account-section": { "account-section": {
"title": "Account Information" "title": "Account Information"
}, },

View File

@ -3,6 +3,8 @@
"about": "关于", "about": "关于",
"email": "邮箱", "email": "邮箱",
"password": "密码", "password": "密码",
"new-password": "新密码",
"repeat-new-password": "重复新密码",
"username": "用户名", "username": "用户名",
"save": "保存", "save": "保存",
"cancel": "退出", "cancel": "退出",
@ -28,9 +30,27 @@
"back-to-home": "回到主页", "back-to-home": "回到主页",
"type": "类型", "type": "类型",
"shortcuts": "捷径", "shortcuts": "捷径",
"shortcut-title": "捷径标题",
"title": "标题", "title": "标题",
"filter": "过滤器", "filter": "过滤器",
"tags": "全部标签" "tags": "全部标签",
"no-memos": "没有 memo 了 🌃",
"memos-ready": "所有 memo 已就绪 🎉",
"yourself": "你自己",
"archived-at": "归档于",
"restored-successfully": "恢复成功",
"memo-updated-datetime": "Memo创建日期时间已更改。",
"invalid-created-datetime": "创建的日期时间无效。",
"change-memo-created-time": "更改Memo创建时间",
"memo-not-found": "找不到Memo。",
"fill-all": "请填写所有字段。",
"new-password-not-match": "新密码不匹配。",
"changed": "已更改",
"image-load-failed": "图片加载失败",
"fill-form": "请填写此表单",
"login-failed": "登录失败",
"signup-failed": "注册失败",
"user-not-found": "未找到用户"
}, },
"slogan": "一个开源的、支持私有化部署的碎片化知识卡片管理工具。", "slogan": "一个开源的、支持私有化部署的碎片化知识卡片管理工具。",
"auth": { "auth": {
@ -63,7 +83,9 @@
"editor": { "editor": {
"editing": "编辑中...", "editing": "编辑中...",
"save": "记下", "save": "记下",
"placeholder": "现在的想法是..." "placeholder": "现在的想法是...",
"only-image-supported": "仅支持图片文件。",
"cant-empty": "Content can't be empty"
}, },
"memo": { "memo": {
"view-story": "查看详情" "view-story": "查看详情"
@ -75,7 +97,9 @@
"create-shortcut": "创建捷径", "create-shortcut": "创建捷径",
"edit-shortcut": "编辑捷径", "edit-shortcut": "编辑捷径",
"new-filter": "新建过滤器", "new-filter": "新建过滤器",
"eligible-memo": "符合条件的 memo" "eligible-memo": "符合条件的 memo",
"fill-previous": "请填写之前的过滤值",
"title-required": "标题是必填项。"
}, },
"tag-list": { "tag-list": {
"tip-text": "输入`#tag `来创建标签" "tip-text": "输入`#tag `来创建标签"
@ -87,6 +111,7 @@
"my-account": "我的账号", "my-account": "我的账号",
"preference": "偏好设置", "preference": "偏好设置",
"member": "成员", "member": "成员",
"member-list": "成员列表",
"account-section": { "account-section": {
"title": "账号信息" "title": "账号信息"
}, },

View File

@ -53,13 +53,13 @@ const Auth = () => {
const emailValidResult = validate(email, validateConfig); const emailValidResult = validate(email, validateConfig);
if (!emailValidResult.result) { if (!emailValidResult.result) {
toastHelper.error("Email: " + emailValidResult.reason); toastHelper.error(t("common.email") + ": " + emailValidResult.reason);
return; return;
} }
const passwordValidResult = validate(password, validateConfig); const passwordValidResult = validate(password, validateConfig);
if (!passwordValidResult.result) { if (!passwordValidResult.result) {
toastHelper.error("Password: " + passwordValidResult.reason); toastHelper.error(t("common.password") + ": " + passwordValidResult.reason);
return; return;
} }
@ -70,7 +70,7 @@ const Auth = () => {
if (user) { if (user) {
locationService.replaceHistory("/"); locationService.replaceHistory("/");
} else { } else {
toastHelper.error("Login failed"); toastHelper.error(t("common.login-failed"));
} }
} catch (error: any) { } catch (error: any) {
console.error(error); console.error(error);
@ -86,13 +86,13 @@ const Auth = () => {
const emailValidResult = validate(email, validateConfig); const emailValidResult = validate(email, validateConfig);
if (!emailValidResult.result) { if (!emailValidResult.result) {
toastHelper.error("Email: " + emailValidResult.reason); toastHelper.error(t("common.email") + ": " + emailValidResult.reason);
return; return;
} }
const passwordValidResult = validate(password, validateConfig); const passwordValidResult = validate(password, validateConfig);
if (!passwordValidResult.result) { if (!passwordValidResult.result) {
toastHelper.error("Password: " + passwordValidResult.reason); toastHelper.error(t("common.password") + ": " + passwordValidResult.reason);
return; return;
} }
@ -103,7 +103,7 @@ const Auth = () => {
if (user) { if (user) {
locationService.replaceHistory("/"); locationService.replaceHistory("/");
} else { } else {
toastHelper.error("Signup failed"); toastHelper.error(t("common.singup-failed"));
} }
} catch (error: any) { } catch (error: any) {
console.error(error); console.error(error);

View File

@ -31,7 +31,7 @@ function Home() {
if (userService.isVisitorMode()) { if (userService.isVisitorMode()) {
if (!owner) { if (!owner) {
toastHelper.error("User not found"); toastHelper.error(t("common.user-not-found"));
} }
} else { } else {
if (!user) { if (!user) {