From 93cb07395099aae0e5842e2ebf3a8458aaff7546 Mon Sep 17 00:00:00 2001
From: HFO4 <912394456@qq.com>
Date: Thu, 7 Jul 2022 20:16:47 +0800
Subject: [PATCH] i18n: file settings
---
public/locales/en-US/dashboard.json | 31 ++++++++++++
public/locales/zh-CN/dashboard.json | 31 ++++++++++++
src/component/Admin/Dialogs/FileFilter.js | 22 +++++---
src/component/Admin/File/File.js | 49 +++++++++---------
src/component/Admin/File/Import.js | 61 +++++++++++++----------
src/component/Admin/Group/Group.js | 2 +
6 files changed, 138 insertions(+), 58 deletions(-)
diff --git a/public/locales/en-US/dashboard.json b/public/locales/en-US/dashboard.json
index 2f7b8b6..126c9c6 100644
--- a/public/locales/en-US/dashboard.json
+++ b/public/locales/en-US/dashboard.json
@@ -683,5 +683,36 @@
"password": "Password",
"passwordDes": "Leave blank means no modification.",
"groupDes": "Group that the user belongs to."
+ },
+ "file": {
+ "name": "File name",
+ "deleteAsync": "Delete task will be executed in background.",
+ "import": "Import external files",
+ "forceDelete": "Force delete",
+ "size": "Size",
+ "uploader": "Uploader",
+ "createdAt": "Created at",
+ "uploading": "Uploading",
+ "unknownUploader": "Unknown",
+ "uploaderID": "Uploader ID",
+ "searchFileName": "Search file name",
+ "storagePolicy": "Storage policy",
+ "selectTargetUser": "Select target user",
+ "importTaskCreated": "Import task created, you can view its status in the Tasks - General.",
+ "manuallyPathOnly": "The selected storage policy only supports manually inputting path.",
+ "selectFolder": "Select folder",
+ "importExternalFolder": "Import external folders",
+ "importExternalFolderDes": "You can import existing files and directory structures from your storage policy into Cloudreve. The import operation will not take up additional physical storage, but will still deduct the user's used storage quota as normal. The import will be halted when there is not enough quota.",
+ "storagePolicyDes": "Select the storage policy where the files to be imported are currently stored.",
+ "targetUser": "Target user",
+ "targetUserDes": "Select which user's file system you want to import the files to, you can search users by nickname or email.",
+ "srcFolderPath": "Source folder path",
+ "select": "Select",
+ "selectSrcDes": "The path of the directory to be imported on the storage side.",
+ "dstFolderPath": "Destination folder path",
+ "dstFolderPathDes": "Path in the user's file system to hold all imported files.",
+ "recursivelyImport": "Recursively import",
+ "recursivelyImportDes": "Whether to import all subdirectories under the directory recursively.",
+ "createImportTask": "Create import task"
}
}
\ No newline at end of file
diff --git a/public/locales/zh-CN/dashboard.json b/public/locales/zh-CN/dashboard.json
index 0a8b512..303b8df 100644
--- a/public/locales/zh-CN/dashboard.json
+++ b/public/locales/zh-CN/dashboard.json
@@ -682,5 +682,36 @@
"password": "密码",
"passwordDes": "留空表示不修改",
"groupDes": "用户所属用户组"
+ },
+ "file": {
+ "name": "文件名",
+ "deleteAsync": "删除任务将在后台执行",
+ "import": "从外部导入",
+ "forceDelete": "强制删除",
+ "size": "大小",
+ "uploader": "上传者",
+ "createdAt": "创建于",
+ "uploading": "上传中",
+ "unknownUploader": "未知",
+ "uploaderID": "上传者 ID",
+ "searchFileName": "搜索文件名",
+ "storagePolicy": "存储策略",
+ "selectTargetUser": "请先选择目标用户",
+ "importTaskCreated": "导入任务已创建,您可以在“持久任务”中查看执行情况",
+ "manuallyPathOnly": "选择的存储策略只支持手动输入路径",
+ "selectFolder": "选择目录",
+ "importExternalFolder": "导入外部目录",
+ "importExternalFolderDes": "您可以将存储策略中已有文件、目录结构导入到 Cloudreve 中,导入操作不会额外占用物理存储空间,但仍会正常扣除用户已用容量空间,空间不足时将停止导入。",
+ "storagePolicyDes": "选择要导入文件目前存储所在的存储策略",
+ "targetUser": "目标用户",
+ "targetUserDes": "选择要将文件导入到哪个用户的文件系统中,可通过昵称、邮箱搜索用户",
+ "srcFolderPath": "原始目录路径",
+ "select": "选择",
+ "selectSrcDes": "要导入的目录在存储端的路径",
+ "dstFolderPath": "目的目录路径",
+ "dstFolderPathDes": "要将目录导入到用户文件系统中的路径",
+ "recursivelyImport": "递归导入子目录",
+ "recursivelyImportDes": "是否将目录下的所有子目录递归导入",
+ "createImportTask": "创建导入任务"
}
}
\ No newline at end of file
diff --git a/src/component/Admin/Dialogs/FileFilter.js b/src/component/Admin/Dialogs/FileFilter.js
index f665193..a15ade7 100644
--- a/src/component/Admin/Dialogs/FileFilter.js
+++ b/src/component/Admin/Dialogs/FileFilter.js
@@ -12,8 +12,12 @@ import React, { useCallback, useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { toggleSnackbar } from "../../../redux/explorer";
import API from "../../../middleware/Api";
+import { useTranslation } from "react-i18next";
export default function FileFilter({ setFilter, setSearch, open, onClose }) {
+ const { t } = useTranslation("dashboard", { keyPrefix: "file" });
+ const { t: tDashboard } = useTranslation("dashboard");
+ const { t: tCommon } = useTranslation("common");
const [input, setInput] = useState({
policy_id: "all",
user_id: "",
@@ -74,11 +78,13 @@ export default function FileFilter({ setFilter, setSearch, open, onClose }) {
fullWidth
maxWidth={"xs"}
>
- 过滤条件
+
+ {tDashboard("user.filterCondition")}
+
- 存储策略
+ {t("storagePolicy")}
@@ -109,16 +117,16 @@ export default function FileFilter({ setFilter, setSearch, open, onClose }) {
value={keywords}
onChange={(e) => setKeywords(e.target.value)}
id="standard-basic"
- label="搜索 文件名"
+ label={t("searchFileName")}
/>
diff --git a/src/component/Admin/File/File.js b/src/component/Admin/File/File.js
index c716282..e934591 100644
--- a/src/component/Admin/File/File.js
+++ b/src/component/Admin/File/File.js
@@ -27,6 +27,7 @@ import { sizeToString } from "../../../utils";
import FileFilter from "../Dialogs/FileFilter";
import { formatLocalTime } from "../../../utils/datetime";
import Chip from "@material-ui/core/Chip";
+import { useTranslation } from "react-i18next";
const useStyles = makeStyles((theme) => ({
root: {
@@ -78,6 +79,8 @@ const useStyles = makeStyles((theme) => ({
}));
export default function File() {
+ const { t } = useTranslation("dashboard", { keyPrefix: "file" });
+ const { t: tDashboard } = useTranslation("dashboard");
const classes = useStyles();
const [files, setFiles] = useState([]);
const [page, setPage] = useState(1);
@@ -127,12 +130,7 @@ export default function File() {
API.post("/admin/file/delete", { id: [id] })
.then(() => {
loadList();
- ToggleSnackbar(
- "top",
- "right",
- "删除任务将在后台执行",
- "success"
- );
+ ToggleSnackbar("top", "right", t("deleteAsync"), "success");
})
.catch((error) => {
ToggleSnackbar("top", "right", error.message, "error");
@@ -147,12 +145,7 @@ export default function File() {
API.post("/admin/file/delete", { id: selected, force: force })
.then(() => {
loadList();
- ToggleSnackbar(
- "top",
- "right",
- "删除任务将在后台执行",
- "success"
- );
+ ToggleSnackbar("top", "right", t("deleteAsync"), "success");
})
.catch((error) => {
ToggleSnackbar("top", "right", error.message, "error");
@@ -211,10 +204,10 @@ export default function File() {
alignSelf: "center",
}}
>
- 从外部导入
+ {t("import")}
-
+
setFilterDialog(true)}
@@ -236,7 +229,7 @@ export default function File() {
onClick={() => loadList()}
variant={"outlined"}
>
- 刷新
+ {tDashboard("policy.refresh")}
@@ -249,9 +242,11 @@ export default function File() {
color="inherit"
variant="subtitle1"
>
- 已选择 {selected.length} 个对象
+ {tDashboard("user.selectedObjects", {
+ num: selected.length,
+ })}
-
+
-
+
- 文件名
+ {t("name")}
{orderBy[0] === "name" ? (
- 大小
+ {t("size")}
{orderBy[0] === "size" ? (
- 上传者
+ {t("uploader")}
- 创建于
+ {t("createdAt")}
- 操作
+ {tDashboard("policy.actions")}
@@ -419,7 +414,7 @@ export default function File() {
classes.disabledBadge
}
size="small"
- label="上传中"
+ label={t("uploading")}
/>
)}
@@ -435,7 +430,7 @@ export default function File() {
>
{users[row.UserID]
? users[row.UserID].Nick
- : "未知"}
+ : t("unknownUploader")}
@@ -445,7 +440,9 @@ export default function File() {
)}
-
+
diff --git a/src/component/Admin/File/Import.js b/src/component/Admin/File/Import.js
index b456110..9c0c6f6 100644
--- a/src/component/Admin/File/Import.js
+++ b/src/component/Admin/File/Import.js
@@ -24,6 +24,7 @@ import { useHistory } from "react-router";
import { toggleSnackbar } from "../../../redux/explorer";
import API from "../../../middleware/Api";
import PathSelector from "../../FileManager/PathSelector";
+import { useTranslation } from "react-i18next";
const useStyles = makeStyles((theme) => ({
root: {
@@ -64,6 +65,9 @@ function useDebounce(value, delay) {
}
export default function Import() {
+ const { t } = useTranslation("dashboard", { keyPrefix: "file" });
+ const { t: tDashboard } = useTranslation("dashboard");
+ const { t: tCommon } = useTranslation("common");
const classes = useStyles();
const [loading, setLoading] = useState(false);
const [options, setOptions] = useState({
@@ -105,7 +109,7 @@ export default function Import() {
const submit = (e) => {
e.preventDefault();
if (user === null) {
- ToggleSnackbar("top", "right", "请先选择目标用户", "warning");
+ ToggleSnackbar("top", "right", t("selectTargetUser"), "warning");
return;
}
setLoading(true);
@@ -122,7 +126,7 @@ export default function Import() {
ToggleSnackbar(
"top",
"right",
- "导入任务已创建,您可以在“持久任务”中查看执行情况",
+ t("importTaskCreated"),
"success"
);
})
@@ -200,7 +204,7 @@ export default function Import() {
ToggleSnackbar(
"top",
"right",
- "选择的存储策略只支持手动输入路径",
+ t("manuallyPathOnly"),
"warning"
);
return;
@@ -208,7 +212,12 @@ export default function Import() {
setSelectRemote(true);
} else {
if (user === null) {
- ToggleSnackbar("top", "right", "请先选择目标用户", "warning");
+ ToggleSnackbar(
+ "top",
+ "right",
+ t("selectTargetUser"),
+ "warning"
+ );
return;
}
setSelectLocal(true);
@@ -222,7 +231,9 @@ export default function Import() {
onClose={() => setSelectRemote(false)}
aria-labelledby="form-dialog-title"
>
- 选择目录
+
+ {t("selectFolder")}
+
setSelectRemote(false)}
color="primary"
>
- 确定
+ {tCommon("ok")}
@@ -249,7 +260,9 @@ export default function Import() {
onClose={() => setSelectLocal(false)}
aria-labelledby="form-dialog-title"
>
- 选择目录
+
+ {t("selectFolder")}
+
setSelectLocal(false)}
color="primary"
>
- 确定
+ {tCommon("ok")}
diff --git a/src/component/Admin/Group/Group.js b/src/component/Admin/Group/Group.js
index 9188639..333bcdf 100644
--- a/src/component/Admin/Group/Group.js
+++ b/src/component/Admin/Group/Group.js
@@ -78,7 +78,9 @@ export default function Group() {
const [total, setTotal] = useState(0);
const [policies, setPolicies] = React.useState({});
+ const location = useLocation();
const history = useHistory();
+ const query = useQuery();
const dispatch = useDispatch();
const ToggleSnackbar = useCallback(