diff --git a/public/locales/en-US/application.json b/public/locales/en-US/application.json index 955be78..360e024 100644 --- a/public/locales/en-US/application.json +++ b/public/locales/en-US/application.json @@ -448,6 +448,7 @@ "fileName": "File name", "shareDate": "Shared at", "downloadNumber": "Downloads", - "viewNumber": "Views" + "viewNumber": "Views", + "language": "Language" } } \ No newline at end of file diff --git a/public/locales/zh-CN/application.json b/public/locales/zh-CN/application.json index 6366cf2..fb0f511 100644 --- a/public/locales/zh-CN/application.json +++ b/public/locales/zh-CN/application.json @@ -439,6 +439,7 @@ "fileName": "文件名", "shareDate": "分享日期", "downloadNumber": "下载次数", - "viewNumber": "浏览次数" + "viewNumber": "浏览次数", + "language": "语言" } } \ No newline at end of file diff --git a/src/component/Modals/OptionSelector.js b/src/component/Modals/OptionSelector.js index c85713b..00fc7aa 100644 --- a/src/component/Modals/OptionSelector.js +++ b/src/component/Modals/OptionSelector.js @@ -13,7 +13,11 @@ import { import { useSelector } from "react-redux"; import { useTranslation } from "react-i18next"; -const useStyles = makeStyles((theme) => ({})); +const useStyles = makeStyles((theme) => ({ + content: { + minWidth: 250, + }, +})); export default function OptionSelector() { const { t } = useTranslation("common"); diff --git a/src/component/Setting/UserSetting.js b/src/component/Setting/UserSetting.js index 9689e56..d6372dd 100644 --- a/src/component/Setting/UserSetting.js +++ b/src/component/Setting/UserSetting.js @@ -49,6 +49,7 @@ import { ListAlt, PermContactCalendar, Schedule, + Translate, } from "@material-ui/icons"; import Authn from "./Authn"; import { formatLocalTime, timeZone } from "../../utils/datetime"; @@ -60,6 +61,8 @@ import { toggleSnackbar, } from "../../redux/explorer"; import { Trans, withTranslation } from "react-i18next"; +import { selectLanguage } from "../../redux/viewUpdate/action"; +import OptionSelector from "../Modals/OptionSelector"; const styles = (theme) => ({ layout: { @@ -191,6 +194,9 @@ const mapDispatchToProps = (dispatch) => { changeView: (method) => { dispatch(changeViewMethod(method)); }, + selectLanguage: () => { + dispatch(selectLanguage()); + }, }; }; @@ -1076,6 +1082,24 @@ class UserSettingCompoment extends Component { + + + + + + this.props.selectLanguage()} + button + > + + + + + @@ -1371,6 +1395,7 @@ class UserSettingCompoment extends Component { + ); } diff --git a/src/i18n.ts b/src/i18n.ts index 28b27a9..06f37b8 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -22,4 +22,15 @@ i18n.on("languageChanged", (lng) => { document.documentElement.setAttribute("lang", lng); }); +export const languages = [ + { + code: "en-US", + displayName: "English", + }, + { + code: "zh-CN", + displayName: "简体中文", + }, +]; + export default i18n; diff --git a/src/redux/viewUpdate/action.ts b/src/redux/viewUpdate/action.ts index 67d66e8..e870ec7 100644 --- a/src/redux/viewUpdate/action.ts +++ b/src/redux/viewUpdate/action.ts @@ -1,6 +1,8 @@ import { ThunkAction } from "redux-thunk"; import { AnyAction } from "redux"; import Auth from "../../middleware/Auth"; +import { askForOption } from "../explorer/async"; +import i18next, { languages } from "../../i18n"; export interface ActionSetSubtitle extends AnyAction { type: "SET_SUBTITLE"; @@ -99,3 +101,27 @@ export const changePageSize = ( ); }; }; + +export const selectLanguage = (): ThunkAction => { + return async (dispatch, getState) => { + let option: any; + let lng = ""; + try { + const allOptions = languages.map((e) => { + return { + key: e.code, + name: e.displayName, + }; + }); + option = await dispatch( + askForOption(allOptions, i18next.t("setting.language")) + ); + } catch (e) { + console.log(e); + return; + } + + lng = option.key; + await i18next.changeLanguage(lng); + }; +};