element-plus/packages/hooks/use-locale/index.ts
msidolphin 66043aa3b5
refactor(components): [el-config-provider] improve componomponent extendiability (#4175)
re #4146

added button configuration
added useGlobalConfig hook
2021-11-05 18:10:07 +08:00

111 lines
2.7 KiB
TypeScript

import { computed, getCurrentInstance, inject, provide, ref } from 'vue'
import English from '@element-plus/locale/lang/en'
import { buildProp, definePropType } from '@element-plus/utils/props'
import type { InjectionKey, Ref } from 'vue'
import type { Language } from '@element-plus/locale'
export const useLocaleProps = {
locale: buildProp({
type: definePropType<Language>(Object),
}),
}
type Translator = (...args: any[]) => string
export type LocaleContext = {
locale: Ref<Language>
lang: Ref<string>
t: Translator
}
export const LocaleInjectionKey =
'ElLocaleInjection' as unknown as InjectionKey<LocaleContext>
// this is meant to fix global methods like `ElMessage(opts)`, this way we can inject current locale
// into the component as default injection value.
// refer to: https://github.com/element-plus/element-plus/issues/2610#issuecomment-887965266
let localeObjCache: LocaleContext
function translate(path, option, current) {
const paths = path.split('.')
let value
for (let i = 0, j = paths.length; i < j; i++) {
const property = paths[i]
value = current[property]
if (i === j - 1) return template(value, option)
if (!value) return ''
current = value
}
}
export const useLocale = () => {
const vm = getCurrentInstance()!
const props = vm.props as {
locale: Language
}
const locale = computed(() => props.locale || English)
const lang = computed(() => locale.value.name)
const _translator = (...args: any[]) => {
const [path, option] = args
return translate(path, option, locale.value)
}
const t = (...args: any[]) => {
return _translator(...args)
}
const provides = {
locale,
lang,
t,
} as LocaleContext
// this could be broken if someone tries to do following:
/**
* <config-provider :locale="lang1">
* <config-provider :locale="lang2">
* Something calls modal component.
* </config-provider>
* </config-provider>
*/
localeObjCache = provides
provide(LocaleInjectionKey, provides)
}
function template(str: string, option) {
if (!str || !option) return str
return str.replace(/\{(\w+)\}/g, (_, key) => {
return option[key]
})
}
export const localeProviderMaker = (locale = English) => {
const lang = ref(locale.name)
const localeRef = ref(locale)
return {
lang,
locale: localeRef,
t: (...args: any[]) => {
const [path, option] = args
return translate(path, option, localeRef.value)
},
}
}
export const useLocaleInject = () => {
return inject(
LocaleInjectionKey,
localeObjCache || {
lang: ref(English.name),
locale: ref(English),
t: (...args) => {
const [path, option] = args
return translate(path, option, English)
},
}
)
}