i18n: modals in file manager

This commit is contained in:
HFO4 2022-05-08 11:03:56 +08:00
parent f2f8d7c43a
commit a08cf8ee6b
9 changed files with 372 additions and 184 deletions

View File

@ -128,5 +128,64 @@
"createShareLink": "Share",
"viewDetails": "View details",
"copy": "Copy"
},
"modals": {
"processing": "Processing...",
"duplicatedObjectName": "Duplicated object name.",
"duplicatedFolderName": "Duplicated folder name.",
"taskCreated": "Task created.",
"taskCreateFailed": "{{failed}} task(s) failed to be created{{details}}.",
"linkCopied": "Link copied.",
"getSourceLinkTitle": "Get source link",
"sourceLink": "Source link",
"folderName": "Folder name",
"create": "Create",
"fileName": "File name",
"renameDescription": "Enter the new name for <0>{{name}}</0> :",
"newName": "New name",
"moveToTitle": "Move to",
"moveToDescription": "Move to <0>{{name}}</0>",
"saveToTitle": "Save to",
"saveToTitleDescription": "Save to <0>{{name}}</0>",
"deleteTitle": "Delete objects",
"deleteOneDescription": "Are you sure to delete <0>{{name}}</0> ",
"deleteMultipleDescription": "Are you sure to remove those {{num}} objects?",
"newRemoteDownloadTitle": "New remote download task",
"remoteDownloadURL": "Download target URL",
"remoteDownloadURLDescription": "Paste the download URL, one URL per line, support HTTP(s) / FTP / Magnet link",
"remoteDownloadDst": "Select a download destination",
"createTask": "Creat task",
"downloadTo": "Download to <0>{{name}}</0>",
"decompressTo": "Decompress to",
"decompressToDst": "Decompress to <0>{{name}}</0>",
"defaultEncoding": "Default",
"chineseMajorEncoding": "",
"selectEncoding": "Select the encoding for non-UTF8 characters",
"noEncodingSelected": "No encoding method selected",
"listingFiles": "Listing files...",
"listingFileError": "Failed to list files: {{message}}",
"generatingSourceLinks": "Generating source links...",
"noFileCanGenerateSourceLink": "There is no file that can be used to generate source link",
"sourceBatchSizeExceeded": "The current user group can generate source links for a maximum of {{limit}} files at the same time.",
"zipFileName": "ZIP file name",
"shareLinkShareContent": "I shared with you: {{name}} Link: {{link}}",
"shareLinkPasswordInfo": "Password: {{password}}",
"createShareLink": "Create share link",
"usePasswordProtection": "Use password protection",
"sharePassword": "Share password",
"randomlyGenerate": "Random",
"expireAutomatically": "Automatic expiration",
"downloadLimitOptions": "{{num}} downloads",
"or": "Or after",
"5minutes": "5 minutes",
"1hour": "1 hour",
"1day": "1 day",
"7days": "7 days",
"30days": "30 days",
"downloadSuffix": "",
"allowPreview": "Enable preview",
"allowPreviewDescription": "Whether to allow preview of file content from the share link",
"shareLink": "Share link",
"sendLink": "Send the link"
}
}

View File

@ -8,6 +8,8 @@
"ok": "OK",
"cancel": "Cancel",
"select": "Select",
"copyToClipboard": "Copy",
"close": "Close",
"errors": {
"40020": "Wrong password or email address.",
"40017": "This account has been blocked.",

View File

@ -128,5 +128,64 @@
"createShareLink": "创建分享链接",
"viewDetails": "详细信息",
"copy": "复制"
},
"modals": {
"processing": "处理中...",
"duplicatedObjectName": "新名称与已有文件重复",
"duplicatedFolderName": "文件夹名称重复",
"taskCreated": "任务已创建",
"taskCreateFailed": "{{failed}} 个任务创建失败:{{details}}",
"linkCopied": "链接已复制",
"getSourceLinkTitle": "获取文件外链",
"sourceLink": "文件外链",
"folderName": "文件夹名称",
"create": "创建",
"fileName": "文件名称",
"renameDescription": "输入 <0>{{name}}</0> 的新名称:",
"newName": "新名称",
"moveToTitle": "移动至",
"moveToDescription": "移动至 <0>{{name}}</0>",
"saveToTitle": "保存至",
"saveToTitleDescription": "保存至 <0>{{name}}</0>",
"deleteTitle": "删除对象",
"deleteOneDescription": "确定要删除 <0>{{name}}</0> 吗?",
"deleteMultipleDescription": "确定要删除这 {{num}} 个对象吗?",
"newRemoteDownloadTitle": "新建离线下载任务",
"remoteDownloadURL": "文件地址",
"remoteDownloadURLDescription": "输入文件下载地址,一行一个,支持 HTTP(s) / FTP / 磁力链",
"remoteDownloadDst": "选择存储位置",
"createTask": "创建任务",
"downloadTo": "下载至 <0>{{name}}</0>",
"decompressTo": "解压缩至",
"decompressToDst": "解压缩至 <0>{{name}}</0>",
"defaultEncoding": "缺省",
"chineseMajorEncoding": "简体中文常见编码",
"selectEncoding": "选择 ZIP 文件特殊字符编码",
"noEncodingSelected": "未选择编码方式",
"listingFiles": "列取文件中...",
"listingFileError": "列取文件时出错:{{message}}",
"generatingSourceLinks": "生成外链中...",
"noFileCanGenerateSourceLink": "没有可以生成外链的文件",
"sourceBatchSizeExceeded": "当前用户组最大可同时为 {{limit}} 个文件生成外链",
"zipFileName": "ZIP 文件名",
"shareLinkShareContent": "我向你分享了:{{name}} 链接:{{link}}",
"shareLinkPasswordInfo": " 密码: {{password}}",
"createShareLink": "创建分享链接",
"usePasswordProtection": "使用密码保护",
"sharePassword": "分享密码",
"randomlyGenerate": "随机生成",
"expireAutomatically": "自动过期",
"downloadLimitOptions": "{{num}} 次下载",
"or": "或者",
"5minutes": "5 分钟",
"1hour": "1 小时",
"1day": "1 天",
"7days": "7 天",
"30days": "30 天",
"downloadSuffix": "后过期",
"allowPreview": "允许预览",
"allowPreviewDescription": "是否允许在分享页面预览文件内容",
"shareLink": "分享链接",
"sendLink": "发送链接"
}
}

View File

@ -8,6 +8,8 @@
"ok": "确定",
"cancel": "取消",
"select": "选择",
"copyToClipboard": "复制",
"close": "关闭",
"errors": {
"40020": "用户邮箱或密码错误",
"40017": "该账号已被封禁",

View File

@ -2,7 +2,7 @@ import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import PathSelector from "./PathSelector";
import API, { baseURL } from "../../middleware/Api";
import API from "../../middleware/Api";
import {
Button,
CircularProgress,
@ -18,7 +18,6 @@ import Loading from "../Modals/Loading";
import CopyDialog from "../Modals/Copy";
import CreatShare from "../Modals/CreateShare";
import { withRouter } from "react-router-dom";
import pathHelper from "../../utils/page";
import DecompressDialog from "../Modals/Decompress";
import CompressDialog from "../Modals/Compress";
import {
@ -31,6 +30,7 @@ import {
} from "../../redux/explorer";
import OptionSelector from "../Modals/OptionSelector";
import { getDownloadURL } from "../../services/file";
import { Trans, withTranslation } from "react-i18next";
const styles = (theme) => ({
wrapper: {
@ -270,7 +270,7 @@ class ModalsCompoment extends Component {
target.path === "/"
? target.path + target.name
: target.path + "/" + target.name;
this.props.openLoadingDialog("处理中...");
this.props.openLoadingDialog(this.props.t("modals.processing"));
this.submitMove();
}
};
@ -303,7 +303,7 @@ class ModalsCompoment extends Component {
this.props.toggleSnackbar(
"top",
"right",
"新名称与已有文件重复",
this.props.t("modals.duplicatedObjectName"),
"warning"
);
this.props.setModalsLoading(false);
@ -341,7 +341,7 @@ class ModalsCompoment extends Component {
this.props.toggleSnackbar(
"top",
"right",
"文件夹名称重复",
this.props.t("modals.duplicatedFolderName"),
"warning"
);
this.props.setModalsLoading(false);
@ -382,7 +382,7 @@ class ModalsCompoment extends Component {
this.props.toggleSnackbar(
"top",
"right",
"文件名称重复",
this.props.t("modals.duplicatedFolderName"),
"warning"
);
this.props.setModalsLoading(false);
@ -425,7 +425,7 @@ class ModalsCompoment extends Component {
this.props.toggleSnackbar(
"top",
"right",
"任务已创建",
this.props.t("modals.taskCreated"),
"success"
);
this.onClose();
@ -455,19 +455,22 @@ class ModalsCompoment extends Component {
.then((response) => {
const failed = response.data
.filter((r) => r.code !== 0)
.map((r) => (r.msg + r.error ? r.error : ""));
.map((r) => r.msg + (r.error ? r.error : ""));
if (failed.length > 0) {
this.props.toggleSnackbar(
"top",
"right",
`${failed.length} 个任务创建失败:${failed.join(",")}`,
this.props.t("modals.taskCreateFailed", {
failed: failed.length,
details: failed.join(","),
}),
"warning"
);
} else {
this.props.toggleSnackbar(
"top",
"right",
"任务已创建",
this.props.t("modals.taskCreated"),
"success"
);
}
@ -528,12 +531,17 @@ class ModalsCompoment extends Component {
copySource = () => {
if (navigator.clipboard) {
navigator.clipboard.writeText(this.props.modalsStatus.getSource);
this.props.toggleSnackbar("top", "right", "链接已复制", "info");
this.props.toggleSnackbar(
"top",
"right",
this.props.t("modals.linkCopied"),
"info"
);
}
};
render() {
const { classes } = this.props;
const { classes, t } = this.props;
return (
<div>
@ -546,14 +554,14 @@ class ModalsCompoment extends Component {
fullWidth
>
<DialogTitle id="form-dialog-title">
获取文件外链
{t("modals.getSourceLinkTitle")}
</DialogTitle>
<DialogContent>
<TextField
autoFocus
inputProps={{ readonly: true }}
label="文件外链"
label={t("modals.sourceLink")}
multiline
value={this.props.modalsStatus.getSource}
variant="outlined"
@ -562,9 +570,11 @@ class ModalsCompoment extends Component {
</DialogContent>
<DialogActions>
<Button onClick={this.copySource} color="secondary">
复制
{t("copyToClipboard", { ns: "common" })}
</Button>
<Button onClick={this.onClose}>
{t("close", { ns: "common" })}
</Button>
<Button onClick={this.onClose}>关闭</Button>
</DialogActions>
</Dialog>
<Dialog
@ -572,7 +582,9 @@ class ModalsCompoment extends Component {
onClose={this.onClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">新建文件夹</DialogTitle>
<DialogTitle id="form-dialog-title">
{t("fileManager.newFolder")}
</DialogTitle>
<DialogContent>
<form onSubmit={this.submitCreateNewFolder}>
@ -580,7 +592,7 @@ class ModalsCompoment extends Component {
autoFocus
margin="dense"
id="newFolderName"
label="文件夹名称"
label={t("modals.folderName")}
type="text"
value={this.state.newFolderName}
onChange={(e) => this.handleInputChange(e)}
@ -589,7 +601,9 @@ class ModalsCompoment extends Component {
</form>
</DialogContent>
<DialogActions>
<Button onClick={this.onClose}>取消</Button>
<Button onClick={this.onClose}>
{t("cancel", { ns: "common" })}
</Button>
<div className={classes.wrapper}>
<Button
onClick={this.submitCreateNewFolder}
@ -599,7 +613,7 @@ class ModalsCompoment extends Component {
this.props.modalsLoading
}
>
创建
{t("modals.create")}
{this.props.modalsLoading && (
<CircularProgress
size={24}
@ -616,7 +630,9 @@ class ModalsCompoment extends Component {
onClose={this.onClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">新建文件</DialogTitle>
<DialogTitle id="form-dialog-title">
{t("fileManager.newFile")}
</DialogTitle>
<DialogContent>
<form onSubmit={this.submitCreateNewFile}>
@ -624,7 +640,7 @@ class ModalsCompoment extends Component {
autoFocus
margin="dense"
id="newFileName"
label="文件名称"
label={t("modals.fileName")}
type="text"
value={this.state.newFileName}
onChange={(e) => this.handleInputChange(e)}
@ -633,7 +649,9 @@ class ModalsCompoment extends Component {
</form>
</DialogContent>
<DialogActions>
<Button onClick={this.onClose}>取消</Button>
<Button onClick={this.onClose}>
{t("cancel", { ns: "common" })}
</Button>
<div className={classes.wrapper}>
<Button
onClick={this.submitCreateNewFile}
@ -643,7 +661,7 @@ class ModalsCompoment extends Component {
this.props.modalsLoading
}
>
创建
{t("modals.create")}
{this.props.modalsLoading && (
<CircularProgress
size={24}
@ -662,23 +680,28 @@ class ModalsCompoment extends Component {
maxWidth="sm"
fullWidth={true}
>
<DialogTitle id="form-dialog-title">重命名</DialogTitle>
<DialogTitle id="form-dialog-title">
{t("fileManager.rename")}
</DialogTitle>
<DialogContent>
<DialogContentText>
输入{" "}
<strong>
{this.props.selected.length === 1
? this.props.selected[0].name
: ""}
</strong>{" "}
的新名称
<Trans
i18nKey="modals.renameDescription"
values={{
name:
this.props.selected.length === 1
? this.props.selected[0].name
: "",
}}
components={[<strong key={0} />]}
/>
</DialogContentText>
<form onSubmit={this.submitRename}>
<TextField
autoFocus
margin="dense"
id="newName"
label="新名称"
label={t("modals.newName")}
type="text"
value={this.state.newName}
onChange={(e) => this.handleInputChange(e)}
@ -687,7 +710,9 @@ class ModalsCompoment extends Component {
</form>
</DialogContent>
<DialogActions>
<Button onClick={this.onClose}>取消</Button>
<Button onClick={this.onClose}>
{t("cancel", { ns: "common" })}
</Button>
<div className={classes.wrapper}>
<Button
onClick={this.submitRename}
@ -697,7 +722,7 @@ class ModalsCompoment extends Component {
this.props.modalsLoading
}
>
确定
{t("ok", { ns: "common" })}
{this.props.modalsLoading && (
<CircularProgress
size={24}
@ -721,7 +746,9 @@ class ModalsCompoment extends Component {
onClose={this.onClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">移动至</DialogTitle>
<DialogTitle id="form-dialog-title">
{t("modals.moveToTitle")}
</DialogTitle>
<PathSelector
presentPath={this.props.path}
selected={this.props.selected}
@ -731,13 +758,20 @@ class ModalsCompoment extends Component {
{this.state.selectedPath !== "" && (
<DialogContent className={classes.contentFix}>
<DialogContentText>
移动至{" "}
<strong>{this.state.selectedPathName}</strong>
<Trans
i18nKey="modals.moveToDescription"
values={{
name: this.state.selectedPathName,
}}
components={[<strong key={0} />]}
/>
</DialogContentText>
</DialogContent>
)}
<DialogActions>
<Button onClick={this.onClose}>取消</Button>
<Button onClick={this.onClose}>
{t("cancel", { ns: "common" })}
</Button>
<div className={classes.wrapper}>
<Button
onClick={this.submitMove}
@ -747,7 +781,7 @@ class ModalsCompoment extends Component {
this.props.modalsLoading
}
>
确定
{t("ok", { ns: "common" })}
{this.props.modalsLoading && (
<CircularProgress
size={24}
@ -763,31 +797,38 @@ class ModalsCompoment extends Component {
onClose={this.onClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">删除对象</DialogTitle>
<DialogTitle id="form-dialog-title">
{t("modals.deleteTitle")}
</DialogTitle>
<DialogContent>
<DialogContentText>
确定要删除
{this.props.selected.length === 1 && (
<strong> {this.props.selected[0].name} </strong>
<Trans
i18nKey="modals.deleteOneDescription"
values={{
name: this.props.selected[0].name,
}}
components={[<strong key={0} />]}
/>
)}
{this.props.selected.length > 1 && (
<span>
{this.props.selected.length}个对象
</span>
)}
{this.props.selected.length > 1 &&
t("modals.deleteMultipleDescription", {
num: this.props.selected.length,
})}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={this.onClose}>取消</Button>
<Button onClick={this.onClose}>
{t("cancel", { ns: "common" })}
</Button>
<div className={classes.wrapper}>
<Button
onClick={this.submitRemove}
color="primary"
disabled={this.props.modalsLoading}
>
确定
{t("ok", { ns: "common" })}
{this.props.modalsLoading && (
<CircularProgress
size={24}
@ -806,58 +847,6 @@ class ModalsCompoment extends Component {
setModalsLoading={this.props.setModalsLoading}
selected={this.props.selected}
/>
<Dialog
open={this.props.modalsStatus.music}
onClose={this.onClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">音频播放</DialogTitle>
<DialogContent>
<DialogContentText>
{this.props.selected.length !== 0 && (
<audio
controls
src={
pathHelper.isSharePage(
this.props.location.pathname
)
? baseURL +
"/share/preview/" +
this.props.selected[0].key +
(this.props.selected[0].key
? "?path=" +
encodeURIComponent(
this.props.selected[0]
.path === "/"
? this.props
.selected[0]
.path +
this.props
.selected[0]
.name
: this.props
.selected[0]
.path +
"/" +
this.props
.selected[0]
.name
)
: "")
: baseURL +
"/file/preview/" +
this.props.selected[0].id
}
/>
)}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={this.onClose}>关闭</Button>
</DialogActions>
</Dialog>
<Dialog
open={this.props.modalsStatus.remoteDownload}
onClose={this.onClose}
@ -865,24 +854,28 @@ class ModalsCompoment extends Component {
fullWidth
>
<DialogTitle id="form-dialog-title">
新建离线下载任务
{t("modals.newRemoteDownloadTitle")}
</DialogTitle>
<DialogContent>
<DialogContentText>
<TextField
label="文件地址"
label={t("modals.remoteDownloadURL")}
autoFocus
fullWidth
multiline
id="downloadURL"
onChange={this.handleInputChange}
placeholder="输入文件下载地址,一行一个,支持 HTTP(s)/FTP/磁力链"
placeholder={t(
"modals.remoteDownloadURLDescription"
)}
/>
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={this.onClose}>关闭</Button>
<Button onClick={this.onClose}>
{t("cancel", { ns: "common" })}
</Button>
<Button
onClick={this.remoteDownloadNext}
color="primary"
@ -891,7 +884,7 @@ class ModalsCompoment extends Component {
this.state.downloadURL === ""
}
>
下一步
{t("ok", { ns: "common" })}
</Button>
</DialogActions>
</Dialog>
@ -901,7 +894,7 @@ class ModalsCompoment extends Component {
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">
选择存储位置
{t("modals.remoteDownloadDst")}
</DialogTitle>
<PathSelector
presentPath={this.props.path}
@ -912,13 +905,20 @@ class ModalsCompoment extends Component {
{this.state.selectedPath !== "" && (
<DialogContent className={classes.contentFix}>
<DialogContentText>
下载至{" "}
<strong>{this.state.selectedPathName}</strong>
<Trans
i18nKey="modals.downloadTo"
values={{
name: this.state.selectedPathName,
}}
components={[<strong key={0} />]}
/>
</DialogContentText>
</DialogContent>
)}
<DialogActions>
<Button onClick={this.onClose}>取消</Button>
<Button onClick={this.onClose}>
{t("cancel", { ns: "common" })}
</Button>
<div className={classes.wrapper}>
<Button
onClick={this.submitDownload}
@ -928,7 +928,7 @@ class ModalsCompoment extends Component {
this.props.modalsLoading
}
>
创建任务
{t("modals.createTask")}
{this.props.modalsLoading && (
<CircularProgress
size={24}
@ -945,7 +945,7 @@ class ModalsCompoment extends Component {
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">
选择存储位置
{t("modals.remoteDownloadDst")}
</DialogTitle>
<PathSelector
presentPath={this.props.path}
@ -956,13 +956,20 @@ class ModalsCompoment extends Component {
{this.state.selectedPath !== "" && (
<DialogContent className={classes.contentFix}>
<DialogContentText>
下载至{" "}
<strong>{this.state.selectedPathName}</strong>
<Trans
i18nKey="modals.downloadTo"
values={{
name: this.state.selectedPathName,
}}
components={[<strong key={0} />]}
/>
</DialogContentText>
</DialogContent>
)}
<DialogActions>
<Button onClick={this.onClose}>取消</Button>
<Button onClick={this.onClose}>
{t("cancel", { ns: "common" })}
</Button>
<div className={classes.wrapper}>
<Button
onClick={this.submitTorrentDownload}
@ -972,7 +979,7 @@ class ModalsCompoment extends Component {
this.props.modalsLoading
}
>
创建任务
{t("modals.createTask")}
{this.props.modalsLoading && (
<CircularProgress
size={24}
@ -1010,6 +1017,6 @@ ModalsCompoment.propTypes = {
const Modals = connect(
mapStateToProps,
mapDispatchToProps
)(withStyles(styles)(withRouter(ModalsCompoment)));
)(withStyles(styles)(withRouter(withTranslation()(ModalsCompoment))));
export default Modals;

View File

@ -1,20 +1,20 @@
import React, { useState, useCallback } from "react";
import { makeStyles } from "@material-ui/core";
import React, { useCallback, useState } from "react";
import {
Button,
CircularProgress,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
DialogContentText,
CircularProgress,
DialogTitle,
makeStyles,
} from "@material-ui/core";
import PathSelector from "../FileManager/PathSelector";
import { useDispatch } from "react-redux";
import API from "../../middleware/Api";
import TextField from "@material-ui/core/TextField";
import { setModalsLoading, toggleSnackbar } from "../../redux/explorer";
import { submitCompressTask } from "../../redux/explorer/action";
import { useTranslation } from "react-i18next";
const useStyles = makeStyles((theme) => ({
contentFix: {
@ -36,6 +36,7 @@ const useStyles = makeStyles((theme) => ({
}));
export default function CompressDialog(props) {
const { t } = useTranslation();
const [selectedPath, setSelectedPath] = useState("");
const [fileName, setFileName] = useState("");
// eslint-disable-next-line
@ -79,7 +80,12 @@ export default function CompressDialog(props) {
SubmitCompressTask(fileName, selectedPath)
.then(() => {
props.onClose();
ToggleSnackbar("top", "right", "压缩任务已创建", "success");
ToggleSnackbar(
"top",
"right",
t("modals.taskCreated"),
"success"
);
SetModalsLoading(false);
})
.catch((error) => {
@ -96,7 +102,9 @@ export default function CompressDialog(props) {
onClose={props.onClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">存放到</DialogTitle>
<DialogTitle id="form-dialog-title">
{t("modals.saveToTitle")}
</DialogTitle>
<PathSelector
presentPath={props.presentPath}
selected={props.selected}
@ -112,13 +120,15 @@ export default function CompressDialog(props) {
fullWidth
autoFocus
id="standard-basic"
label="压缩文件名"
label={t("modals.zipFileName")}
/>
</DialogContentText>
</DialogContent>
)}
<DialogActions>
<Button onClick={props.onClose}>取消</Button>
<Button onClick={props.onClose}>
{t("cancel", { ns: "common" })}
</Button>
<div className={classes.wrapper}>
<Button
onClick={submitMove}
@ -129,7 +139,7 @@ export default function CompressDialog(props) {
props.modalsLoading
}
>
确定
{t("ok", { ns: "common" })}
{props.modalsLoading && (
<CircularProgress
size={24}

View File

@ -37,6 +37,7 @@ import Tooltip from "@material-ui/core/Tooltip";
import MenuItem from "@material-ui/core/MenuItem";
import Select from "@material-ui/core/Select";
import ToggleIcon from "material-ui-toggle-icon";
import { useTranslation } from "react-i18next";
const useStyles = makeStyles((theme) => ({
widthAnimation: {},
@ -104,6 +105,7 @@ const ExpansionPanelDetails = withStyles((theme) => ({
}))(MuiExpansionPanelDetails);
export default function CreatShare(props) {
const { t } = useTranslation();
const dispatch = useDispatch();
const classes = useStyles();
@ -184,14 +186,19 @@ export default function CreatShare(props) {
const senLink = () => {
if (navigator.share) {
let text = `我向你分享了:${props.selected[0].name} 链接:${shareURL}`;
let text = t("modals.shareLinkShareContent", {
name: props.selected[0].name,
link: shareURL,
});
if (lastSubmit.current && lastSubmit.current.password) {
text += `密码:${lastSubmit.current.password}`;
text += t("modals.shareLinkPasswordInfo", {
password: lastSubmit.current.password,
});
}
navigator.share({ text });
} else if (navigator.clipboard) {
navigator.clipboard.writeText(shareURL);
ToggleSnackbar("top", "right", "分享链接已复制", "info");
ToggleSnackbar("top", "right", t("modals.linkCopied"), "info");
}
};
@ -240,7 +247,9 @@ export default function CreatShare(props) {
maxWidth="xs"
fullWidth
>
<DialogTitle id="form-dialog-title">创建分享链接</DialogTitle>
<DialogTitle id="form-dialog-title">
{t("modals.createShareLink")}
</DialogTitle>
{shareURL === "" && (
<>
@ -258,7 +267,11 @@ export default function CreatShare(props) {
<ListItemIcon>
<LockIcon />
</ListItemIcon>
<ListItemText primary="使用密码保护" />
<ListItemText
primary={t(
"modals.usePasswordProtection"
)}
/>
<ListItemSecondaryAction>
<Checkbox
checked={shareOption.password}
@ -274,7 +287,7 @@ export default function CreatShare(props) {
fullWidth
>
<InputLabel htmlFor="filled-adornment-password">
分享密码
{t("modals.sharePassword")}
</InputLabel>
<OutlinedInput
fullWidth
@ -288,7 +301,11 @@ export default function CreatShare(props) {
onChange={handleChange("password")}
endAdornment={
<InputAdornment position="end">
<Tooltip title="随机生成">
<Tooltip
title={t(
"modals.randomlyGenerate"
)}
>
<IconButton
aria-label="toggle password visibility"
onClick={randomPassword}
@ -334,7 +351,11 @@ export default function CreatShare(props) {
<ListItemIcon>
<TimerIcon />
</ListItemIcon>
<ListItemText primary="自动过期" />
<ListItemText
primary={t(
"modals.expireAutomatically"
)}
/>
<ListItemSecondaryAction>
<Checkbox
checked={shareOption.expire}
@ -357,23 +378,19 @@ export default function CreatShare(props) {
value={values.downloads}
onChange={handleChange("downloads")}
>
<MenuItem value={1}>1 次下载</MenuItem>
<MenuItem value={2}>2 次下载</MenuItem>
<MenuItem value={3}>3 次下载</MenuItem>
<MenuItem value={4}>4 次下载</MenuItem>
<MenuItem value={5}>5 次下载</MenuItem>
<MenuItem value={20}>
20 次下载
</MenuItem>
<MenuItem value={50}>
50 次下载
</MenuItem>
<MenuItem value={100}>
100 次下载
</MenuItem>
{[1, 2, 3, 4, 5, 20, 50, 100].map(
(v) => (
<MenuItem value={v} key={v}>
{t(
"modals.downloadLimitOptions",
{ num: v }
)}
</MenuItem>
)
)}
</Select>
</FormControl>
<Typography>或者</Typography>
<Typography>{t("modals.or")}</Typography>
<FormControl
style={{
marginRight: 10,
@ -386,20 +403,26 @@ export default function CreatShare(props) {
value={values.expires}
onChange={handleChange("expires")}
>
<MenuItem value={300}>5 分钟</MenuItem>
<MenuItem value={3600}>1 小时</MenuItem>
<MenuItem value={300}>
{t("modals.5minutes")}
</MenuItem>
<MenuItem value={3600}>
{t("modals.1hour")}
</MenuItem>
<MenuItem value={24 * 3600}>
1
{t("modals.1day")}
</MenuItem>
<MenuItem value={7 * 24 * 3600}>
7
{t("modals.7days")}
</MenuItem>
<MenuItem value={30 * 24 * 3600}>
30
{t("modals.30days")}
</MenuItem>
</Select>
</FormControl>
<Typography>后过期</Typography>
<Typography>
{t("modals.downloadSuffix")}
</Typography>
</ExpansionPanelDetails>
</ExpansionPanel>
<ExpansionPanel
@ -414,7 +437,9 @@ export default function CreatShare(props) {
<ListItemIcon>
<LockIcon />
</ListItemIcon>
<ListItemText primary="允许预览" />
<ListItemText
primary={t("modals.allowPreview")}
/>
<ListItemSecondaryAction>
<Checkbox
checked={shareOption.preview}
@ -425,7 +450,7 @@ export default function CreatShare(props) {
</ExpansionPanelSummary>
<ExpansionPanelDetails>
<Typography>
是否允许在分享页面预览文件内容
{t("modals.allowPreviewDescription")}
</Typography>
</ExpansionPanelDetails>
</ExpansionPanel>
@ -439,7 +464,7 @@ export default function CreatShare(props) {
onFocus={handleFocus}
autoFocus
inputProps={{ readonly: true }}
label="分享链接"
label={t("modals.shareLink")}
value={shareURL}
variant="outlined"
fullWidth
@ -451,11 +476,13 @@ export default function CreatShare(props) {
{shareURL !== "" && (
<div className={classes.wrapper}>
<Button onClick={senLink} color="secondary">
发送链接
{t("modals.sendLink")}
</Button>
</div>
)}
<Button onClick={onClose}>关闭</Button>
<Button onClick={onClose}>
{t("close", { ns: "common" })}
</Button>
{shareURL === "" && (
<div className={classes.wrapper}>
@ -464,7 +491,7 @@ export default function CreatShare(props) {
color="secondary"
disabled={props.modalsLoading}
>
创建分享链接
{t("modals.createShareLink")}
{props.modalsLoading && (
<CircularProgress
size={24}

View File

@ -1,20 +1,19 @@
import React, { useState, useCallback } from "react";
import { makeStyles } from "@material-ui/core";
import React, { useCallback, useState } from "react";
import {
Button,
CircularProgress,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
DialogContentText,
CircularProgress,
DialogTitle,
makeStyles,
} from "@material-ui/core";
import PathSelector from "../FileManager/PathSelector";
import { useDispatch } from "react-redux";
import API from "../../middleware/Api";
import { filePath } from "../../utils";
import { setModalsLoading, toggleSnackbar } from "../../redux/explorer";
import { submitDecompressTask } from "../../redux/explorer/action";
import { Trans, useTranslation } from "react-i18next";
const useStyles = makeStyles((theme) => ({
contentFix: {
@ -35,6 +34,7 @@ const useStyles = makeStyles((theme) => ({
}));
export default function DecompressDialog(props) {
const { t } = useTranslation();
const [selectedPath, setSelectedPath] = useState("");
const [selectedPathName, setSelectedPathName] = useState("");
@ -72,7 +72,12 @@ export default function DecompressDialog(props) {
SubmitDecompressTask(selectedPath)
.then(() => {
props.onClose();
ToggleSnackbar("top", "right", "解压缩任务已创建", "success");
ToggleSnackbar(
"top",
"right",
t("modals.taskCreated"),
"success"
);
SetModalsLoading(false);
})
.catch((error) => {
@ -89,7 +94,9 @@ export default function DecompressDialog(props) {
onClose={props.onClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">解压送至</DialogTitle>
<DialogTitle id="form-dialog-title">
{t("modals.decompressTo")}
</DialogTitle>
<PathSelector
presentPath={props.presentPath}
selected={props.selected}
@ -99,19 +106,27 @@ export default function DecompressDialog(props) {
{selectedPath !== "" && (
<DialogContent className={classes.contentFix}>
<DialogContentText>
解压缩至 <strong>{selectedPathName}</strong>
<Trans
i18nKey="modals.decompressToDst"
values={{
name: selectedPathName,
}}
components={[<strong key={0} />]}
/>
</DialogContentText>
</DialogContent>
)}
<DialogActions>
<Button onClick={props.onClose}>取消</Button>
<Button onClick={props.onClose}>
{t("cancel", { ns: "common" })}
</Button>
<div className={classes.wrapper}>
<Button
onClick={submitMove}
color="primary"
disabled={selectedPath === "" || props.modalsLoading}
>
确定
{t("ok", { ns: "common" })}
{props.modalsLoading && (
<CircularProgress
size={24}

View File

@ -24,6 +24,7 @@ import {
toggleSnackbar,
} from "./index";
import { getDownloadURL } from "../../services/file";
import i18next from "../../i18n";
export interface ActionSetFileList extends AnyAction {
type: "SET_FILE_LIST";
@ -639,20 +640,22 @@ export const submitDecompressTask = (path: string) => {
[
{
key: "",
name: "缺省",
name: i18next.t("modals.defaultEncoding"),
},
{
key: "gb18030",
name: "GB18030",
description: "中文常见编码",
description: i18next.t(
"modals.chineseMajorEncoding"
),
},
...allOptions,
],
"选择 ZIP 文件特殊字符编码"
i18next.t("modals.selectEncoding")
)
);
} catch (e) {
throw new Error("未选择编码方式");
throw new Error(i18next.t("modals.noEncodingSelected"));
}
encoding = option.key;
@ -676,7 +679,7 @@ export const batchGetSource = (): ThunkAction<any, any, any, any> => {
} = getState();
if (selected.findIndex((f) => f.type === "dir") >= 0) {
dispatch(openLoadingDialog("列取文件中..."));
dispatch(openLoadingDialog(i18next.t("modals.listingFiles")));
}
let queue: CloudreveFile[] = [];
@ -687,7 +690,9 @@ export const batchGetSource = (): ThunkAction<any, any, any, any> => {
toggleSnackbar(
"top",
"right",
`列取文件时出错:${e.message}`,
i18next.t("modals.listingFileError", {
message: e.message,
}),
"warning"
)
);
@ -695,7 +700,7 @@ export const batchGetSource = (): ThunkAction<any, any, any, any> => {
return;
}
dispatch(openLoadingDialog("生成外链中..."));
dispatch(openLoadingDialog(i18next.t("modals.generatingSourceLinks")));
const items = queue
.filter((value) => value.source_enabled && value.type === "file")
@ -706,7 +711,7 @@ export const batchGetSource = (): ThunkAction<any, any, any, any> => {
toggleSnackbar(
"top",
"right",
`没有可以生成外链的文件`,
i18next.t("modals.noFileCanGenerateSourceLink"),
"warning"
)
);
@ -720,7 +725,9 @@ export const batchGetSource = (): ThunkAction<any, any, any, any> => {
toggleSnackbar(
"top",
"right",
`当前用户组最大可同时为 ${user.group.sourceBatch} 个文件生成外链`,
i18next.t("modals.sourceBatchSizeExceeded", {
limit: user.group.sourceBatch,
}),
"warning"
)
);