Skip to content

Commit

Permalink
perf: 优化多语言设置逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
baimingxuan committed Apr 2, 2024
1 parent f210624 commit 84074a8
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 37 deletions.
4 changes: 3 additions & 1 deletion src/components/Application/src/AppLocalePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defineComponent, ref, unref, watchEffect } from 'vue'
import { Dropdown, Menu, MenuItem, Tooltip } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { localeList } from '@/settings/localeSetting'
import { useLocaleSetting } from '@/hooks/setting/useLocaleSetting'
import SvgIcon from '@/components/SvgIcon'
Expand All @@ -8,6 +9,7 @@ export default defineComponent({
name: 'AppLocalePicker',

setup() {
const { t } = useI18n()
const selectedKeys = ref<string[]>([localeList[0].event])
const { getLocale, changeLocale } = useLocaleSetting()

Expand All @@ -26,7 +28,7 @@ export default defineComponent({
<Dropdown trigger='click' placement='bottom'>
{{
default: () => (
<Tooltip title='多语言' placement='bottom' mouseEnterDelay={0.5}>
<Tooltip title={t('layout.feature.language')} placement='bottom' mouseEnterDelay={0.5}>
<span class='icon-btn'>
<SvgIcon name='locale' size={20} />
</span>
Expand Down
4 changes: 3 additions & 1 deletion src/components/Application/src/AppSearch/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { defineComponent, ref, unref } from 'vue'
import { Tooltip } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import SvgIcon from '@/components/SvgIcon'
import SearchModal from './Modal'

export default defineComponent({
name: 'AppSearch',
setup() {
const { t } = useI18n()
const showModal = ref(false)

function changeModal(show: boolean) {
Expand All @@ -14,7 +16,7 @@ export default defineComponent({

return () => (
<span onClick={changeModal.bind(null, true)}>
<Tooltip title='搜索' placement='bottom' mouseEnterDelay={0.5}>
<Tooltip title={t('layout.feature.search')} placement='bottom' mouseEnterDelay={0.5}>
<span class='icon-btn'>
<SvgIcon name='search' size={20} />
</span>
Expand Down
13 changes: 8 additions & 5 deletions src/hooks/setting/useLocaleSetting.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import type { LocaleType } from '@/types'
import { unref, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAppStoreWithOut } from '@/stores/modules/app'
import { setHtmlPageLang } from '@/locales/helper'
import { genLangs } from '@/locales/langs'
import { LOCALE_KEY } from '@/enums/cacheEnum'
import { createLocalStorage } from '@/utils/cache'
import { getBrowserLang } from '@/locales/helper'

const ls = createLocalStorage()

export function useLocaleSetting() {
const { locale: currentLocale, setLocaleMessage } = useI18n()
const appStore = useAppStoreWithOut()
const getLocale = computed(() => appStore.getAppLocale)
const getLocale = computed(() => ls.get(LOCALE_KEY) || getBrowserLang())

async function changeLocale(locale: LocaleType) {
if (unref(currentLocale) === locale) {
return locale
}

const langModule = await genLangs(locale)
const langModule = genLangs(locale)
if (!langModule) return

setLocaleMessage(locale, langModule.message)

appStore.setAppLocale(locale)
ls.set(LOCALE_KEY, locale)
setHtmlPageLang(locale)

return locale
Expand Down
5 changes: 4 additions & 1 deletion src/layout/feature/components/DocLink.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { defineComponent } from 'vue'
import { Tooltip } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import SvgIcon from '@/components/SvgIcon'

export default defineComponent({
name: 'DocLink',

setup() {
const { t } = useI18n()

return () => (
<span>
<Tooltip title='文档' placement='bottom' mouseEnterDelay={0.5}>
<Tooltip title={t('layout.feature.document')} placement='bottom' mouseEnterDelay={0.5}>
<span class='icon-btn'>
<SvgIcon name='document' size={20} />
</span>
Expand Down
6 changes: 4 additions & 2 deletions src/layout/feature/components/UserDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineComponent, computed, unref } from 'vue'
import { Dropdown, Menu, MenuItem } from 'ant-design-vue'
import { LockOutlined, PoweroffOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { useUserStore } from '@/stores/modules/user'
import headerImg from '@/assets/images/avatar.jpeg'

Expand All @@ -10,6 +11,7 @@ export default defineComponent({
name: 'UserDropdown',

setup() {
const { t } = useI18n()
const userStore = useUserStore()
const getUserInfo = computed(() => {
const { realName = '', avatar } = userStore.getUserInfo || {}
Expand Down Expand Up @@ -47,13 +49,13 @@ export default defineComponent({
<MenuItem key='lock'>
<span class='flex-center-v'>
<LockOutlined />
<span style='margin-left: 4px;'>锁定屏幕</span>
<span style='margin-left: 4px;'>{t('layout.feature.lockScreen')}</span>
</span>
</MenuItem>
<MenuItem key='logout'>
<span class='flex-center-v'>
<PoweroffOutlined />
<span style='margin-left: 4px;'>退出登录</span>
<span style='margin-left: 4px;'>{t('layout.feature.logout')}</span>
</span>
</MenuItem>
</Menu>
Expand Down
10 changes: 6 additions & 4 deletions src/layout/tags/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { defineComponent, computed, ref, unref, nextTick, TransitionGroup } from
import { useRouter } from 'vue-router'
import { Button, Dropdown, Menu, MenuItem } from 'ant-design-vue'
import { LeftOutlined, RightOutlined, RedoOutlined, CloseOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import { listenerRouteChange } from '@/logics/mitt/routeChange'
import { useBaseSetting } from '@/hooks/setting/useBaseSetting'
import { useMenuSetting } from '@/hooks/setting/useMenuSetting'
Expand All @@ -25,6 +26,7 @@ export default defineComponent({
}
},
setup(props) {
const { t } = useI18n()
const tagsMain = ref<ElRef>(null)
const tagsMainCont = ref<ElRef>(null)

Expand Down Expand Up @@ -216,10 +218,10 @@ export default defineComponent({
),
overlay: () => (
<Menu>
<MenuItem onClick={closeLeft}>关闭左侧</MenuItem>
<MenuItem onClick={closeRight}>关闭右侧</MenuItem>
<MenuItem onClick={closeOther}>关闭其它</MenuItem>
<MenuItem onClick={closeAll}>关闭所有</MenuItem>
<MenuItem onClick={closeLeft}>{t('layout.tags.closeLeft')}</MenuItem>
<MenuItem onClick={closeRight}>{t('layout.tags.closeRight')}</MenuItem>
<MenuItem onClick={closeOther}>{t('layout.tags.closeOther')}</MenuItem>
<MenuItem onClick={closeAll}>{t('layout.tags.closeAll')}</MenuItem>
</Menu>
)
}}
Expand Down
26 changes: 26 additions & 0 deletions src/locales/helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import type { LocaleType } from '@/types'
import { set } from 'lodash-es'
import { LocaleEnum } from '@/enums/appEnum'

type langLowerType = 'zh_cn' | 'zh_tw' | 'en_us'

export function setHtmlPageLang(locale: LocaleType) {
document.querySelector('html')?.setAttribute('lang', locale)
Expand Down Expand Up @@ -28,3 +31,26 @@ export function genMessage(langs: Record<string, Record<string, any>>, prefix =
})
return obj
}

export function getBrowserLang(): LocaleType {
const browserLang = navigator.language as LocaleType
const lowercaseBrowserLang = browserLang?.toLowerCase() as langLowerType

const localeMap = new Map<langLowerType, LocaleType>([
['zh_cn', LocaleEnum.ZH_CN],
['zh_tw', LocaleEnum.Zh_TW],
['en_us', LocaleEnum.EN_US]
])

if (localeMap.has(lowercaseBrowserLang)) {
return localeMap.get(lowercaseBrowserLang)!
}

if (lowercaseBrowserLang.includes('en')) {
return LocaleEnum.EN_US
}

return LocaleEnum.ZH_CN
}

export const t = (key: string) => key
19 changes: 13 additions & 6 deletions src/locales/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import type { App } from 'vue'
import type { I18nOptions } from 'vue-i18n'
import { LocaleEnum } from '@/enums/appEnum'
import { LOCALE_KEY } from '@/enums/cacheEnum'
import { localePool } from '@/settings/localeSetting'
import { createI18n } from 'vue-i18n'
import { setHtmlPageLang } from './helper'
import { useAppStoreWithOut } from '@/stores/modules/app'
import { setHtmlPageLang, getBrowserLang } from './helper'
import { createLocalStorage } from '@/utils/cache'
import { genLangs } from './langs'

const ls = createLocalStorage()

function createI18nOptions(): I18nOptions {
const appStore = useAppStoreWithOut()
const locale = appStore.getAppLocale
const locale = ls.get(LOCALE_KEY) || getBrowserLang()
const defaultLocal = genLangs(locale)
const message = defaultLocal?.message ?? {}

Expand All @@ -30,8 +32,13 @@ function createI18nOptions(): I18nOptions {
}
}

export function setupI18n(app: App) {
function createI18nInstance() {
const options = createI18nOptions()
const i18n = createI18n(options)
return createI18n(options)
}

export const i18n = createI18nInstance()

export function setupI18n(app: App) {
app.use(i18n)
}
21 changes: 4 additions & 17 deletions src/stores/modules/app.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import type { ThemeMode, LocaleType } from '@/types'
import type { ThemeMode } from '@/types'
import type { AppConfig, HeaderSetting, MenuSetting, TransitionSetting } from '@/interfaces/config'
import { type AppModeEnum, type ThemeEnum, LocaleEnum } from '@/enums/appEnum'
import type { AppModeEnum, ThemeEnum } from '@/enums/appEnum'
import { defineStore } from 'pinia'
import { stores } from '../index'
import { resetRouter } from '@/router'
import { deepMerge } from '@/utils'
import { createLocalStorage } from '@/utils/cache'
import { Persistent } from '@/utils/cache/persistent'
import { APP_CONFIG_KEY, APP_MODE_KEY, LOCALE_KEY } from '@/enums/cacheEnum'
import { APP_CONFIG_KEY, APP_MODE_KEY } from '@/enums/cacheEnum'
import { baseAppMode } from '@/settings/designSetting'

interface AppState {
Expand All @@ -16,18 +15,13 @@ interface AppState {
themeMode?: ThemeEnum

appConfig: AppConfig | null

appLocale: LocaleType
}

const ls = createLocalStorage()

export const useAppStore = defineStore('app', {
state: (): AppState => ({
appMode: undefined,
themeMode: undefined,
appConfig: Persistent.getLocal(APP_CONFIG_KEY),
appLocale: ls.get(LOCALE_KEY)
appConfig: Persistent.getLocal(APP_CONFIG_KEY)
}),

getters: {
Expand All @@ -40,9 +34,6 @@ export const useAppStore = defineStore('app', {
getAppConfig(): AppConfig {
return this.appConfig || ({} as AppConfig)
},
getAppLocale(): LocaleType {
return this.appLocale || LocaleEnum.EN_US
},
getHeaderSetting(): HeaderSetting {
return this.getAppConfig.headerSetting
},
Expand All @@ -66,10 +57,6 @@ export const useAppStore = defineStore('app', {
this.appConfig = deepMerge(this.appConfig || {}, config)
Persistent.setLocal(APP_CONFIG_KEY, this.appConfig, true)
},
setAppLocale(locale: LocaleType): void {
this.appLocale = locale
ls.set(LOCALE_KEY, locale)
},
async resetState() {
resetRouter()
Persistent.clearAll()
Expand Down

0 comments on commit 84074a8

Please sign in to comment.