mirror of
https://github.com/usememos/memos.git
synced 2024-12-19 09:02:49 +03:00
chore: update i18n (#215)
This commit is contained in:
parent
54db6eda04
commit
7e8d1128f8
@ -20,6 +20,7 @@ const ArchivedMemo: React.FC<Props> = (props: Props) => {
|
||||
archivedAtStr: utils.getDateTimeString(propsMemo.updatedTs ?? Date.now()),
|
||||
};
|
||||
const { t } = useI18n();
|
||||
|
||||
const [showConfirmDeleteBtn, toggleConfirmDeleteBtn] = useToggle(false);
|
||||
|
||||
const handleDeleteMemoClick = async () => {
|
||||
@ -43,7 +44,7 @@ const ArchivedMemo: React.FC<Props> = (props: Props) => {
|
||||
rowStatus: "NORMAL",
|
||||
});
|
||||
await memoService.fetchMemos();
|
||||
toastHelper.info("Restored successfully");
|
||||
toastHelper.info(t("common.restored-successfully"));
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
toastHelper.error(error.response.data.message);
|
||||
@ -59,7 +60,9 @@ const ArchivedMemo: React.FC<Props> = (props: Props) => {
|
||||
return (
|
||||
<div className={`memo-wrapper archived-memo ${"memos-" + memo.id}`} onMouseLeave={handleMouseLeaveMemoWrapper}>
|
||||
<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">
|
||||
<span className="btn restore-btn" onClick={handleRestoreMemoClick}>
|
||||
{t("common.restore")}
|
||||
|
@ -23,7 +23,7 @@ const ChangeMemoCreatedTsDialog: React.FC<Props> = (props: Props) => {
|
||||
const datetime = dayjs(memo.createdTs).format("YYYY-MM-DDTHH:mm");
|
||||
setCreatedAt(datetime);
|
||||
} else {
|
||||
toastHelper.error("Memo not found.");
|
||||
toastHelper.error(t("common.memo-not-found"));
|
||||
destroy();
|
||||
}
|
||||
}, []);
|
||||
@ -42,7 +42,7 @@ const ChangeMemoCreatedTsDialog: React.FC<Props> = (props: Props) => {
|
||||
const createdTs = dayjs(createdAt).unix();
|
||||
|
||||
if (createdTs > nowTs) {
|
||||
toastHelper.error("Invalid created datetime.");
|
||||
toastHelper.error(t("common.invalid-created-datetime"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ const ChangeMemoCreatedTsDialog: React.FC<Props> = (props: Props) => {
|
||||
id: memoId,
|
||||
createdTs,
|
||||
});
|
||||
toastHelper.info("Memo created datetime changed.");
|
||||
toastHelper.info(t("common.memo-updated-datetime"));
|
||||
handleCloseBtnClick();
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
@ -62,7 +62,7 @@ const ChangeMemoCreatedTsDialog: React.FC<Props> = (props: Props) => {
|
||||
return (
|
||||
<>
|
||||
<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}>
|
||||
<Icon.X />
|
||||
</button>
|
||||
|
@ -17,7 +17,7 @@ const validateConfig: ValidatorConfig = {
|
||||
type Props = DialogProps;
|
||||
|
||||
const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
|
||||
const { t } = useI18n();
|
||||
const { t, locale } = useI18n();
|
||||
const [newPassword, setNewPassword] = useState("");
|
||||
const [newPasswordAgain, setNewPasswordAgain] = useState("");
|
||||
|
||||
@ -41,19 +41,19 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
|
||||
|
||||
const handleSaveBtnClick = async () => {
|
||||
if (newPassword === "" || newPasswordAgain === "") {
|
||||
toastHelper.error("Please fill in all fields.");
|
||||
toastHelper.error(t("common.fill-all"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword !== newPasswordAgain) {
|
||||
toastHelper.error("New passwords do not match.");
|
||||
toastHelper.error(t("common.new-password-not-match"));
|
||||
setNewPasswordAgain("");
|
||||
return;
|
||||
}
|
||||
|
||||
const passwordValidResult = validate(newPassword, validateConfig);
|
||||
if (!passwordValidResult.result) {
|
||||
toastHelper.error("Password " + passwordValidResult.reason);
|
||||
toastHelper.error(t("common.password") + locale === "zh" ? "" : " " + passwordValidResult.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
|
||||
id: user.id,
|
||||
password: newPassword,
|
||||
});
|
||||
toastHelper.info("Password changed.");
|
||||
toastHelper.info(t("common.password") + t("common.changed"));
|
||||
handleCloseBtnClick();
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
@ -74,17 +74,22 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<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}>
|
||||
<Icon.X />
|
||||
</button>
|
||||
</div>
|
||||
<div className="dialog-content-container">
|
||||
<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 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>
|
||||
<div className="btns-container">
|
||||
<span className="btn cancel-btn" onClick={handleCloseBtnClick}>
|
||||
|
@ -45,7 +45,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
|
||||
|
||||
const handleSaveBtnClick = async () => {
|
||||
if (!title) {
|
||||
toastHelper.error("Title is required");
|
||||
toastHelper.error(t("shortcut-list.title-required"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
|
||||
if (filters.length > 0) {
|
||||
const lastFilter = filters[filters.length - 1];
|
||||
if (lastFilter.value.value === "") {
|
||||
toastHelper.info("Please fill in previous filter value");
|
||||
toastHelper.info(t("shortcut-list.fill-previous"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -110,7 +110,13 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
|
||||
<div className="dialog-content-container">
|
||||
<div className="form-item-container input-form-container">
|
||||
<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 className="form-item-container filter-form-container">
|
||||
<span className="normal-text">{t("common.filter")}</span>
|
||||
|
@ -105,7 +105,7 @@ const Memo: React.FC<Props> = (props: Props) => {
|
||||
if (memoTemp) {
|
||||
showMemoCardDialog(memoTemp);
|
||||
} else {
|
||||
toastHelper.error("Memo Not Found");
|
||||
toastHelper.error(t("common.memo-not-found"));
|
||||
targetEl.classList.remove("memo-link-text");
|
||||
}
|
||||
} else if (targetEl.className === "tag-span") {
|
||||
|
@ -12,6 +12,7 @@ import Selector from "./common/Selector";
|
||||
import MemoContent from "./MemoContent";
|
||||
import MemoResources from "./MemoResources";
|
||||
import showChangeMemoCreatedTsDialog from "./ChangeMemoCreatedTsDialog";
|
||||
import useI18n from "../hooks/useI18n";
|
||||
import "../less/memo-card-dialog.less";
|
||||
|
||||
interface LinkedMemo extends Memo {
|
||||
@ -30,6 +31,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
|
||||
});
|
||||
const [linkMemos, setLinkMemos] = useState<LinkedMemo[]>([]);
|
||||
const [linkedMemos, setLinkedMemos] = useState<LinkedMemo[]>([]);
|
||||
const { t } = useI18n();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchLinkedMemos = async () => {
|
||||
@ -95,7 +97,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
|
||||
setLinkedMemos([]);
|
||||
setMemo(nextMemo);
|
||||
} else {
|
||||
toastHelper.error("Memo Not Found");
|
||||
toastHelper.error(t("common.memo-not-found"));
|
||||
targetEl.classList.remove("memo-link-text");
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ const MemoEditor = () => {
|
||||
const { type } = file;
|
||||
|
||||
if (!type.startsWith("image")) {
|
||||
toastHelper.error("Only image file supported.");
|
||||
toastHelper.error(t("editor.only-image-supported"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ const MemoEditor = () => {
|
||||
|
||||
const handleSaveBtnClick = async (content: string) => {
|
||||
if (content === "") {
|
||||
toastHelper.error("Content can't be empty");
|
||||
toastHelper.error(t("editor.cant-empty"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ const MemoList = () => {
|
||||
))}
|
||||
<Only when={!isFetching}>
|
||||
<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>
|
||||
</Only>
|
||||
</div>
|
||||
|
@ -48,7 +48,7 @@ const PreferencesSection = () => {
|
||||
|
||||
const handleCreateUserBtnClick = async () => {
|
||||
if (isEmpty(state.createUserEmail) || isEmpty(state.createUserPassword)) {
|
||||
toastHelper.error("Please fill out this form");
|
||||
toastHelper.error(t("common.fill-form"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -125,10 +125,10 @@ const PreferencesSection = () => {
|
||||
<button onClick={handleCreateUserBtnClick}>{t("common.create")}</button>
|
||||
</div>
|
||||
</div>
|
||||
<p className="title-text">Member list</p>
|
||||
<p className="title-text">{t("setting.member-list")}</p>
|
||||
<div className="member-container field-container">
|
||||
<span className="field-text">ID</span>
|
||||
<span className="field-text">EMAIL</span>
|
||||
<span className="field-text">{t("common.email")}</span>
|
||||
<span></span>
|
||||
</div>
|
||||
{userList.map((user) => (
|
||||
@ -137,7 +137,7 @@ const PreferencesSection = () => {
|
||||
<span className="field-text email-text">{user.email}</span>
|
||||
<div className="buttons-container">
|
||||
{currentUser?.id === user.id ? (
|
||||
<span className="tip-text">Yourself</span>
|
||||
<span className="tip-text">{t("common.yourself")}</span>
|
||||
) : (
|
||||
<Dropdown className="actions-dropdown">
|
||||
{user.rowStatus === "NORMAL" ? (
|
||||
|
@ -16,7 +16,7 @@ const validateConfig: ValidatorConfig = {
|
||||
};
|
||||
|
||||
const MyAccountSection = () => {
|
||||
const { t } = useI18n();
|
||||
const { t, locale } = useI18n();
|
||||
const user = useAppSelector((state) => state.user.user as User);
|
||||
const [username, setUsername] = useState<string>(user.name);
|
||||
const openAPIRoute = `${window.location.origin}/api/memo?openId=${user.openId}`;
|
||||
@ -33,7 +33,7 @@ const MyAccountSection = () => {
|
||||
|
||||
const usernameValidResult = validate(username, validateConfig);
|
||||
if (!usernameValidResult.result) {
|
||||
toastHelper.error("Username " + usernameValidResult.reason);
|
||||
toastHelper.error(t("common.username") + locale === "zh" ? "" : " " + usernameValidResult.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ const MyAccountSection = () => {
|
||||
id: user.id,
|
||||
name: username,
|
||||
});
|
||||
toastHelper.info("Username changed");
|
||||
toastHelper.info(t("common.username") + locale === "zh" ? "" : " " + t("common.changed"));
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
toastHelper.error(error.response.data.message);
|
||||
|
@ -59,7 +59,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
|
||||
|
||||
const handleImageOnLoad = (event: React.SyntheticEvent<HTMLImageElement>) => {
|
||||
if (event.type === "error") {
|
||||
toastHelper.error("Image load failed");
|
||||
toastHelper.error(t("common.image-load-failed"));
|
||||
(event.target as HTMLImageElement).remove();
|
||||
}
|
||||
setImgAmount(imgAmount - 1);
|
||||
|
@ -3,6 +3,8 @@
|
||||
"about": "About",
|
||||
"email": "Email",
|
||||
"password": "Password",
|
||||
"new-password": "New passworld",
|
||||
"repeat-new-password": "Repeat the new password",
|
||||
"username": "Username",
|
||||
"save": "Save",
|
||||
"cancel": "Cancel",
|
||||
@ -28,9 +30,27 @@
|
||||
"back-to-home": "Back to Home",
|
||||
"type": "Type",
|
||||
"shortcuts": "Shortcuts",
|
||||
"shortcut-title": "shortcut title",
|
||||
"title": "Title",
|
||||
"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.",
|
||||
"auth": {
|
||||
@ -63,7 +83,9 @@
|
||||
"editor": {
|
||||
"editing": "Editing...",
|
||||
"save": "Save",
|
||||
"placeholder": "Any thoughts..."
|
||||
"placeholder": "Any thoughts...",
|
||||
"only-image-supported": "Only image file supported.",
|
||||
"cant-empty": "Content can't be empty"
|
||||
},
|
||||
"memo": {
|
||||
"view-story": "View Story"
|
||||
@ -75,7 +97,9 @@
|
||||
"create-shortcut": "Create Shortcut",
|
||||
"edit-shortcut": "Edit Shortcut",
|
||||
"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": {
|
||||
"tip-text": "Enter `#tag ` to create"
|
||||
@ -87,6 +111,7 @@
|
||||
"my-account": "My Account",
|
||||
"preference": "Preference",
|
||||
"member": "Member",
|
||||
"member-list": "Member list",
|
||||
"account-section": {
|
||||
"title": "Account Information"
|
||||
},
|
||||
|
@ -3,6 +3,8 @@
|
||||
"about": "关于",
|
||||
"email": "邮箱",
|
||||
"password": "密码",
|
||||
"new-password": "新密码",
|
||||
"repeat-new-password": "重复新密码",
|
||||
"username": "用户名",
|
||||
"save": "保存",
|
||||
"cancel": "退出",
|
||||
@ -28,9 +30,27 @@
|
||||
"back-to-home": "回到主页",
|
||||
"type": "类型",
|
||||
"shortcuts": "捷径",
|
||||
"shortcut-title": "捷径标题",
|
||||
"title": "标题",
|
||||
"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": "一个开源的、支持私有化部署的碎片化知识卡片管理工具。",
|
||||
"auth": {
|
||||
@ -63,7 +83,9 @@
|
||||
"editor": {
|
||||
"editing": "编辑中...",
|
||||
"save": "记下",
|
||||
"placeholder": "现在的想法是..."
|
||||
"placeholder": "现在的想法是...",
|
||||
"only-image-supported": "仅支持图片文件。",
|
||||
"cant-empty": "Content can't be empty"
|
||||
},
|
||||
"memo": {
|
||||
"view-story": "查看详情"
|
||||
@ -75,7 +97,9 @@
|
||||
"create-shortcut": "创建捷径",
|
||||
"edit-shortcut": "编辑捷径",
|
||||
"new-filter": "新建过滤器",
|
||||
"eligible-memo": "符合条件的 memo"
|
||||
"eligible-memo": "符合条件的 memo",
|
||||
"fill-previous": "请填写之前的过滤值",
|
||||
"title-required": "标题是必填项。"
|
||||
},
|
||||
"tag-list": {
|
||||
"tip-text": "输入`#tag `来创建标签"
|
||||
@ -87,6 +111,7 @@
|
||||
"my-account": "我的账号",
|
||||
"preference": "偏好设置",
|
||||
"member": "成员",
|
||||
"member-list": "成员列表",
|
||||
"account-section": {
|
||||
"title": "账号信息"
|
||||
},
|
||||
|
@ -53,13 +53,13 @@ const Auth = () => {
|
||||
|
||||
const emailValidResult = validate(email, validateConfig);
|
||||
if (!emailValidResult.result) {
|
||||
toastHelper.error("Email: " + emailValidResult.reason);
|
||||
toastHelper.error(t("common.email") + ": " + emailValidResult.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
const passwordValidResult = validate(password, validateConfig);
|
||||
if (!passwordValidResult.result) {
|
||||
toastHelper.error("Password: " + passwordValidResult.reason);
|
||||
toastHelper.error(t("common.password") + ": " + passwordValidResult.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ const Auth = () => {
|
||||
if (user) {
|
||||
locationService.replaceHistory("/");
|
||||
} else {
|
||||
toastHelper.error("Login failed");
|
||||
toastHelper.error(t("common.login-failed"));
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
@ -86,13 +86,13 @@ const Auth = () => {
|
||||
|
||||
const emailValidResult = validate(email, validateConfig);
|
||||
if (!emailValidResult.result) {
|
||||
toastHelper.error("Email: " + emailValidResult.reason);
|
||||
toastHelper.error(t("common.email") + ": " + emailValidResult.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
const passwordValidResult = validate(password, validateConfig);
|
||||
if (!passwordValidResult.result) {
|
||||
toastHelper.error("Password: " + passwordValidResult.reason);
|
||||
toastHelper.error(t("common.password") + ": " + passwordValidResult.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ const Auth = () => {
|
||||
if (user) {
|
||||
locationService.replaceHistory("/");
|
||||
} else {
|
||||
toastHelper.error("Signup failed");
|
||||
toastHelper.error(t("common.singup-failed"));
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
|
@ -31,7 +31,7 @@ function Home() {
|
||||
|
||||
if (userService.isVisitorMode()) {
|
||||
if (!owner) {
|
||||
toastHelper.error("User not found");
|
||||
toastHelper.error(t("common.user-not-found"));
|
||||
}
|
||||
} else {
|
||||
if (!user) {
|
||||
|
Loading…
Reference in New Issue
Block a user