From 737b1b190cf288d7ab7ad7e9bd21acb9da16cc6c Mon Sep 17 00:00:00 2001 From: vben Date: Mon, 23 Nov 2020 00:35:15 +0800 Subject: [PATCH] wip: multi-language support --- CHANGELOG.zh_CN.md | 6 ++ package.json | 1 + src/App.vue | 21 ++--- src/components/Application/index.ts | 3 + .../Application/src/AppLocalPicker.vue | 53 +++++++++++++ src/components/Dropdown/index.ts | 4 +- .../Dropdown/{ => src}/Dropdown.tsx | 18 ++--- src/components/Dropdown/{ => src}/props.ts | 7 +- src/components/Dropdown/{ => src}/types.ts | 2 + src/hooks/web/useI18n.ts | 16 ---- src/hooks/web/useLocale.ts | 79 ++++++++++++++++--- src/hooks/web/useMessage.tsx | 4 - src/layouts/default/setting/SettingDrawer.tsx | 3 +- src/layouts/logo/index.vue | 4 +- src/layouts/page/index.tsx | 4 +- src/locales/index.ts | 14 ++++ src/locales/lang/en/sys/errorLog.ts | 18 +++++ src/locales/lang/en/sys/exception.ts | 12 +++ src/locales/lang/en/sys/lock.ts | 6 ++ src/locales/lang/en/sys/login.ts | 13 +++ src/locales/lang/en/system/basic.ts | 3 - src/locales/lang/en/system/login.ts | 3 - src/locales/lang/ru/routes/menus/dashboard.ts | 3 - src/locales/lang/ru/system/basic.ts | 3 - src/locales/lang/ru/system/login.ts | 7 -- src/locales/lang/zhCN/system/basic.ts | 3 - src/locales/lang/zhCN/system/login.ts | 3 - .../{zhCN => zh_CN}/routes/menus/dashboard.ts | 0 src/locales/lang/zh_CN/sys/errorLog.ts | 18 +++++ src/locales/lang/zh_CN/sys/exception.ts | 11 +++ src/locales/lang/zh_CN/sys/lock.ts | 6 ++ src/locales/lang/zh_CN/sys/login.ts | 13 +++ src/locales/types.ts | 2 +- src/router/guard/index.ts | 6 +- src/router/guard/permissionGuard.ts | 4 +- src/router/menus/modules/demo/feat.ts | 4 - src/router/routes/modules/demo/feat.ts | 8 -- src/settings/projectSetting.ts | 21 ++--- .../useSetting.ts => settings/use/index.ts} | 18 +++-- src/settings/use/useLocaleSetting.ts | 36 +++++++++ src/setup/directives/permission.ts | 4 +- src/setup/directives/repeatClick.ts | 2 +- src/setup/error-handle/index.ts | 7 +- src/setup/i18n/index.ts | 23 +++--- src/store/modules/app.ts | 23 +++++- src/store/modules/error.ts | 6 +- src/store/modules/user.ts | 18 +---- src/types/config.d.ts | 30 +++---- src/utils/helper/envHelper.ts | 4 +- src/utils/http/axios/index.ts | 4 +- src/views/demo/feat/i18n/index.vue | 38 --------- src/views/sys/error-log/DetailModal.vue | 8 +- src/views/sys/error-log/data.tsx | 16 ++-- src/views/sys/error-log/index.vue | 32 +++++--- src/views/sys/exception/Exception.tsx | 27 ++++--- src/views/sys/lock/index.vue | 36 +++++---- src/views/sys/login/Login.vue | 34 +++++--- vite.config.ts | 7 +- yarn.lock | 5 ++ 59 files changed, 512 insertions(+), 272 deletions(-) create mode 100644 src/components/Application/index.ts create mode 100644 src/components/Application/src/AppLocalPicker.vue rename src/components/Dropdown/{ => src}/Dropdown.tsx (68%) rename src/components/Dropdown/{ => src}/props.ts (71%) rename src/components/Dropdown/{ => src}/types.ts (71%) delete mode 100644 src/hooks/web/useI18n.ts create mode 100644 src/locales/lang/en/sys/errorLog.ts create mode 100644 src/locales/lang/en/sys/exception.ts create mode 100644 src/locales/lang/en/sys/lock.ts create mode 100644 src/locales/lang/en/sys/login.ts delete mode 100644 src/locales/lang/en/system/basic.ts delete mode 100644 src/locales/lang/en/system/login.ts delete mode 100644 src/locales/lang/ru/routes/menus/dashboard.ts delete mode 100644 src/locales/lang/ru/system/basic.ts delete mode 100644 src/locales/lang/ru/system/login.ts delete mode 100644 src/locales/lang/zhCN/system/basic.ts delete mode 100644 src/locales/lang/zhCN/system/login.ts rename src/locales/lang/{zhCN => zh_CN}/routes/menus/dashboard.ts (100%) create mode 100644 src/locales/lang/zh_CN/sys/errorLog.ts create mode 100644 src/locales/lang/zh_CN/sys/exception.ts create mode 100644 src/locales/lang/zh_CN/sys/lock.ts create mode 100644 src/locales/lang/zh_CN/sys/login.ts rename src/{hooks/core/useSetting.ts => settings/use/index.ts} (76%) create mode 100644 src/settings/use/useLocaleSetting.ts delete mode 100644 src/views/demo/feat/i18n/index.vue diff --git a/CHANGELOG.zh_CN.md b/CHANGELOG.zh_CN.md index f89d9fc5..77f37eee 100644 --- a/CHANGELOG.zh_CN.md +++ b/CHANGELOG.zh_CN.md @@ -1,3 +1,9 @@ +## Wip + +### 🎫 Chores + +- 移除 messageSetting 配置 + ## 2.0.0-rc.11 (2020-11-18) ### ✨ Features diff --git a/package.json b/package.json index 0ed980cc..8b73d156 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "ant-design-vue": "2.0.0-beta.15", "apexcharts": "3.22.0", "axios": "^0.21.0", + "crypto-es": "^1.2.6", "echarts": "^4.9.0", "lodash-es": "^4.17.15", "mockjs": "^1.1.0", diff --git a/src/App.vue b/src/App.vue index 67d51272..54aa8871 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,5 +1,9 @@ @@ -7,16 +11,12 @@ + + diff --git a/src/components/Dropdown/index.ts b/src/components/Dropdown/index.ts index ddda25c6..a55ed0ba 100644 --- a/src/components/Dropdown/index.ts +++ b/src/components/Dropdown/index.ts @@ -1,2 +1,2 @@ -export { default as Dropdown } from './Dropdown'; -export * from './types'; +export { default as Dropdown } from './src/Dropdown'; +export * from './src/types'; diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/src/Dropdown.tsx similarity index 68% rename from src/components/Dropdown/Dropdown.tsx rename to src/components/Dropdown/src/Dropdown.tsx index 72a120dd..9bea06b6 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/src/Dropdown.tsx @@ -1,32 +1,33 @@ import { defineComponent, computed, unref } from 'vue'; -import { Dropdown, Menu } from 'ant-design-vue'; +import { Dropdown, Menu, Divider } from 'ant-design-vue'; import Icon from '/@/components/Icon/index'; import { basicDropdownProps } from './props'; import { getSlot } from '/@/utils/helper/tsxHelper'; +import { Trigger } from './types'; export default defineComponent({ name: 'Dropdown', props: basicDropdownProps, + emits: ['menuEvent'], setup(props, { slots, emit, attrs }) { const getMenuList = computed(() => props.dropMenuList); function handleClickMenu({ key }: any) { - const menu = unref(getMenuList)[key]; + const menu = unref(getMenuList).find((item) => item.event === key); emit('menuEvent', menu); } function renderMenus() { return ( - + {() => ( <> {unref(getMenuList).map((item, index) => { - const { disabled, icon, text, divider } = item; - + const { disabled, icon, text, divider, event } = item; return [ - + {() => ( <> {icon && } @@ -34,8 +35,7 @@ export default defineComponent({ )} , - // @ts-ignore - divider && , + divider && , ]; })} @@ -45,7 +45,7 @@ export default defineComponent({ } return () => ( - + {{ default: () => {getSlot(slots)}, overlay: () => renderMenus(), diff --git a/src/components/Dropdown/props.ts b/src/components/Dropdown/src/props.ts similarity index 71% rename from src/components/Dropdown/props.ts rename to src/components/Dropdown/src/props.ts index 90448740..cd298ef9 100644 --- a/src/components/Dropdown/props.ts +++ b/src/components/Dropdown/src/props.ts @@ -1,4 +1,5 @@ import type { PropType } from 'vue'; +import type { DropMenu } from './types'; export const dropdownProps = { /** @@ -15,7 +16,11 @@ export const dropdownProps = { }; export const basicDropdownProps = Object.assign({}, dropdownProps, { dropMenuList: { - type: Array as PropType, + type: Array as PropType, + default: () => [], + }, + selectedKeys: { + type: Array as PropType, default: () => [], }, }); diff --git a/src/components/Dropdown/types.ts b/src/components/Dropdown/src/types.ts similarity index 71% rename from src/components/Dropdown/types.ts rename to src/components/Dropdown/src/types.ts index bf23d5ec..11139fa6 100644 --- a/src/components/Dropdown/types.ts +++ b/src/components/Dropdown/src/types.ts @@ -6,3 +6,5 @@ export interface DropMenu { disabled?: boolean; divider?: boolean; } + +export type Trigger = 'click' | 'hover' | 'contextMenu'; diff --git a/src/hooks/web/useI18n.ts b/src/hooks/web/useI18n.ts deleted file mode 100644 index db9f45aa..00000000 --- a/src/hooks/web/useI18n.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { createI18n } from 'vue-i18n'; -import { ref, watch } from 'vue'; -import type { I18nOptions } from 'vue-i18n'; -export function useI18n(options?: I18nOptions) { - const i18n = createI18n(options); - - const localeRef = ref(i18n.global.locale); - - watch(localeRef, () => { - i18n.global.locale = localeRef.value as any; - }); - return { - t: i18n.global.t, - localeRef, - }; -} diff --git a/src/hooks/web/useLocale.ts b/src/hooks/web/useLocale.ts index 33e25a48..5e8122d8 100644 --- a/src/hooks/web/useLocale.ts +++ b/src/hooks/web/useLocale.ts @@ -1,21 +1,74 @@ +/** + * Multi-language related operations + */ import type { LocaleType } from '/@/locales/types'; -import { appStore } from '/@/store/modules/app'; + +import { unref, ref } from 'vue'; + +import { getI18n } from '/@/setup/i18n'; + +import { useLocaleSetting } from '/@/settings/use/useLocaleSetting'; + +import moment from 'moment'; + +import 'moment/dist/locale/zh-cn'; + +moment.locale('zh-cn'); + +const antConfigLocaleRef = ref(null); export function useLocale() { - /** - * - */ - function getLocale(): string { - return appStore.getProjectConfig.locale; + const { getLang, getLocale, setLocale: setLocalSetting } = useLocaleSetting(); + + // Switching the language will change the locale of useI18n + // And submit to configuration modification + function changeLocale(lang: LocaleType): void { + (getI18n().global.locale as any).value = lang; + setLocalSetting({ lang }); + // i18n.global.setLocaleMessage(locale, messages); + + antConfigLocaleRef.value = { a: 1 }; + switch (lang) { + // Simplified Chinese + case 'zh_CN': + import('ant-design-vue/es/locale/zh_CN').then((locale) => { + antConfigLocaleRef.value = locale.default; + }); + + moment.locale('cn'); + break; + // English + case 'en': + import('ant-design-vue/es/locale/en_US').then((locale) => { + antConfigLocaleRef.value = locale.default; + }); + moment.locale('en-us'); + break; + + // other + default: + break; + } } - /** - * - * @param locale - */ - async function changeLocale(locale: LocaleType): Promise { - appStore.commitProjectConfigState({ locale: locale }); + // initialization + function setupLocale() { + const lang = unref(getLang); + lang && changeLocale(lang); } - return { getLocale, changeLocale }; + return { + setupLocale, + getLocale, + getLang, + changeLocale, + antConfigLocale: antConfigLocaleRef, + }; +} + +/** + * For non-setup use + */ +export function useExternalI18n() { + return getI18n().global; } diff --git a/src/hooks/web/useMessage.tsx b/src/hooks/web/useMessage.tsx index a11ac003..fce05458 100644 --- a/src/hooks/web/useMessage.tsx +++ b/src/hooks/web/useMessage.tsx @@ -3,7 +3,6 @@ import type { ModalFunc, ModalFuncProps } from 'ant-design-vue/lib/modal/Modal'; import { Modal, message as Message, notification } from 'ant-design-vue'; import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons-vue'; -import { useSetting } from '/@/hooks/core/useSetting'; import { ArgsProps, ConfigProps } from 'ant-design-vue/lib/notification'; export interface NotifyApi { @@ -33,8 +32,6 @@ interface ConfirmOptions { warning: ModalFunc; } -const { projectSetting } = useSetting(); - function getIcon(iconType: string) { if (iconType === 'warning') { return ; @@ -60,7 +57,6 @@ function createConfirm(options: ModalOptionsEx): ConfirmOptions { const opt: ModalFuncProps = { centered: true, icon: getIcon(iconType), - ...projectSetting.messageSetting, ...options, }; return Modal.confirm(opt) as any; diff --git a/src/layouts/default/setting/SettingDrawer.tsx b/src/layouts/default/setting/SettingDrawer.tsx index 6c847a9b..dd9115b1 100644 --- a/src/layouts/default/setting/SettingDrawer.tsx +++ b/src/layouts/default/setting/SettingDrawer.tsx @@ -5,7 +5,6 @@ import Button from '/@/components/Button/index.vue'; import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue'; import { appStore } from '/@/store/modules/app'; -import { userStore } from '/@/store/modules/user'; import { ProjectConfig } from '/@/types/config'; import { useMessage } from '/@/hooks/web/useMessage'; @@ -97,7 +96,7 @@ export default defineComponent({ function handleClearAndRedo() { localStorage.clear(); - userStore.resumeAllState(); + appStore.resumeAllState(); location.reload(); } diff --git a/src/layouts/logo/index.vue b/src/layouts/logo/index.vue index 3cfd230b..f34d80da 100644 --- a/src/layouts/logo/index.vue +++ b/src/layouts/logo/index.vue @@ -7,7 +7,7 @@ diff --git a/src/views/sys/error-log/DetailModal.vue b/src/views/sys/error-log/DetailModal.vue index 6bde90be..d77c74aa 100644 --- a/src/views/sys/error-log/DetailModal.vue +++ b/src/views/sys/error-log/DetailModal.vue @@ -1,13 +1,16 @@