123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- import type { App } from 'vue';
- import type { Locale } from 'vue-i18n';
- import type {
- ImportLocaleFn,
- LoadMessageFn,
- LocaleSetupOptions,
- SupportedLanguagesType,
- } from './typing';
- import { unref } from 'vue';
- import { createI18n } from 'vue-i18n';
- import { useSimpleLocale } from '@vben-core/composables';
- const i18n = createI18n({
- globalInjection: true,
- legacy: false,
- locale: '',
- messages: {},
- });
- const modules = import.meta.glob('./langs/**/*.json');
- const { setSimpleLocale } = useSimpleLocale();
- const localesMap = loadLocalesMapFromDir(
- /\.\/langs\/([^/]+)\/(.*)\.json$/,
- modules,
- );
- let loadMessages: LoadMessageFn;
- /**
- * Load locale modules
- * @param modules
- */
- function loadLocalesMap(modules: Record<string, () => Promise<unknown>>) {
- const localesMap: Record<Locale, ImportLocaleFn> = {};
- for (const [path, loadLocale] of Object.entries(modules)) {
- const key = path.match(/([\w-]*)\.(json)/)?.[1];
- if (key) {
- localesMap[key] = loadLocale as ImportLocaleFn;
- }
- }
- return localesMap;
- }
- /**
- * Load locale modules with directory structure
- * @param regexp - Regular expression to match language and file names
- * @param modules - The modules object containing paths and import functions
- * @returns A map of locales to their corresponding import functions
- */
- function loadLocalesMapFromDir(
- regexp: RegExp,
- modules: Record<string, () => Promise<unknown>>,
- ): Record<Locale, ImportLocaleFn> {
- const localesRaw: Record<Locale, Record<string, () => Promise<unknown>>> = {};
- const localesMap: Record<Locale, ImportLocaleFn> = {};
- // Iterate over the modules to extract language and file names
- for (const path in modules) {
- const match = path.match(regexp);
- if (match) {
- const [_, locale, fileName] = match;
- if (locale && fileName) {
- if (!localesRaw[locale]) {
- localesRaw[locale] = {};
- }
- if (modules[path]) {
- localesRaw[locale][fileName] = modules[path];
- }
- }
- }
- }
- // Convert raw locale data into async import functions
- for (const [locale, files] of Object.entries(localesRaw)) {
- localesMap[locale] = async () => {
- const messages: Record<string, any> = {};
- for (const [fileName, importFn] of Object.entries(files)) {
- messages[fileName] = ((await importFn()) as any)?.default;
- }
- return { default: messages };
- };
- }
- return localesMap;
- }
- /**
- * Set i18n language
- * @param locale
- */
- function setI18nLanguage(locale: Locale) {
- i18n.global.locale.value = locale;
- document?.querySelector('html')?.setAttribute('lang', locale);
- }
- async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
- const { defaultLocale = 'zh-CN' } = options;
- // app可以自行扩展一些第三方库和组件库的国际化
- loadMessages = options.loadMessages || (async () => ({}));
- app.use(i18n);
- await loadLocaleMessages(defaultLocale);
- // 在控制台打印警告
- i18n.global.setMissingHandler((locale, key) => {
- if (options.missingWarn && key.includes('.')) {
- console.warn(
- `[intlify] Not found '${key}' key in '${locale}' locale messages.`,
- );
- }
- });
- }
- /**
- * Load locale messages
- * @param lang
- */
- async function loadLocaleMessages(lang: SupportedLanguagesType) {
- if (unref(i18n.global.locale) === lang) {
- return setI18nLanguage(lang);
- }
- setSimpleLocale(lang);
- const message = await localesMap[lang]?.();
- if (message?.default) {
- i18n.global.setLocaleMessage(lang, message.default);
- }
- const mergeMessage = await loadMessages(lang);
- i18n.global.mergeLocaleMessage(lang, mergeMessage);
- return setI18nLanguage(lang);
- }
- export {
- i18n,
- loadLocaleMessages,
- loadLocalesMap,
- loadLocalesMapFromDir,
- setupI18n,
- };
|