i18n.ts 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import type { Locale } from 'vue-i18n';
  2. import type {
  3. ImportLocaleFn,
  4. LoadMessageFn,
  5. LocaleSetupOptions,
  6. SupportedLanguagesType,
  7. } from './typing';
  8. import { type App, unref } from 'vue';
  9. import { createI18n } from 'vue-i18n';
  10. const loadedLanguages = new Set<string>();
  11. const i18n = createI18n({
  12. globalInjection: true,
  13. legacy: false,
  14. locale: '',
  15. messages: {},
  16. });
  17. const modules = import.meta.glob('./langs/*.json');
  18. const localesMap = loadLocalesMap(modules);
  19. let loadMessages: LoadMessageFn;
  20. /**
  21. * Load locale modules
  22. * @param modules
  23. */
  24. function loadLocalesMap(modules: Record<string, () => Promise<unknown>>) {
  25. const localesMap: Record<Locale, ImportLocaleFn> = {};
  26. for (const [path, loadLocale] of Object.entries(modules)) {
  27. const key = path.match(/([\w-]*)\.(yaml|yml|json)/)?.[1];
  28. if (key) {
  29. localesMap[key] = loadLocale as ImportLocaleFn;
  30. }
  31. }
  32. return localesMap;
  33. }
  34. /**
  35. * Set i18n language
  36. * @param locale
  37. */
  38. function setI18nLanguage(locale: Locale) {
  39. i18n.global.locale.value = locale;
  40. document?.querySelector('html')?.setAttribute('lang', locale);
  41. }
  42. async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
  43. const { defaultLocale = 'zh-CN' } = options;
  44. // app可以自行扩展一些第三方库和组件库的国际化
  45. loadMessages = options.loadMessages || (async () => ({}));
  46. app.use(i18n);
  47. await loadLocaleMessages(defaultLocale);
  48. // 在控制台打印警告
  49. i18n.global.setMissingHandler((locale, key) => {
  50. if (options.missingWarn && key.includes('.')) {
  51. console.warn(
  52. `[intlify] Not found '${key}' key in '${locale}' locale messages.`,
  53. );
  54. }
  55. });
  56. }
  57. /**
  58. * Load locale messages
  59. * @param lang
  60. */
  61. async function loadLocaleMessages(lang: SupportedLanguagesType) {
  62. if (unref(i18n.global.locale) === lang) {
  63. return setI18nLanguage(lang);
  64. }
  65. if (loadedLanguages.has(lang)) {
  66. return setI18nLanguage(lang);
  67. }
  68. const message = await localesMap[lang]?.();
  69. if (message?.default) {
  70. i18n.global.setLocaleMessage(lang, message.default);
  71. }
  72. const mergeMessage = await loadMessages(lang);
  73. i18n.global.mergeLocaleMessage(lang, mergeMessage);
  74. loadedLanguages.add(lang);
  75. return setI18nLanguage(lang);
  76. }
  77. export { i18n, loadLocaleMessages, loadLocalesMap, setupI18n };