refactor: refactor locales, separate locales within apps,fixed #12

This commit is contained in:
vben
2024-07-07 00:17:44 +08:00
parent 3571511394
commit 208d4188fc
77 changed files with 486 additions and 394 deletions

View File

@@ -5,7 +5,6 @@ export default defineBuildConfig({
declaration: true,
entries: [
'src/index',
'src/helper',
{
builder: 'mkdist',
input: './src/langs',

View File

@@ -1,12 +1,12 @@
{
"name": "@vben/locales",
"name": "@vben-core/locales",
"version": "5.0.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
"type": "git",
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
"directory": "packages/locales"
"directory": "packages/@vben-core/forward/locales"
},
"license": "MIT",
"type": "module",
@@ -30,11 +30,6 @@
},
"./langs/*": {
"default": "./dist/langs/*"
},
"./helper": {
"types": "./src/helper.ts",
"development": "./src/helper.ts",
"default": "./dist/helper.mjs"
}
},
"publishConfig": {
@@ -45,6 +40,9 @@
}
}
},
"peerDependencies": {
"vite": "latest"
},
"dependencies": {
"@intlify/core-base": "^9.13.1",
"@vben-core/typings": "workspace:*",

View File

@@ -8,6 +8,7 @@ import { createI18n } from 'vue-i18n';
const loadedLanguages = new Set<string>();
// TODOimport.meta.env 和 import.meta.glob 是源码依赖会导致该包依赖外部项目必须是vite才可以
const i18n = createI18n({
globalInjection: true,
legacy: false,
@@ -20,13 +21,22 @@ const i18n = createI18n({
const modules = import.meta.glob('./langs/*.y(a)?ml');
const localesMap: Record<Locale, ImportLocaleFn> = {};
const localesMap = loadLocalesMap(modules);
for (const [path, loadLocale] of Object.entries(modules)) {
const key = path.match(/([\w-]*)\.y(a)?ml/)?.[1];
if (key) {
localesMap[key] = loadLocale as ImportLocaleFn;
/**
* 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-]*)\.y(a)?ml/)?.[1];
if (key) {
localesMap[key] = loadLocale as ImportLocaleFn;
}
}
return localesMap;
}
/**
@@ -52,11 +62,11 @@ async function loadI18nMessages(lang: SupportedLanguagesType) {
return setI18nLanguage(lang);
}
const messages = await localesMap[lang]();
const message = await localesMap[lang]();
i18n.global.setLocaleMessage(lang, messages.default);
i18n.global.setLocaleMessage(lang, message.default);
loadedLanguages.add(lang);
return setI18nLanguage(lang);
}
export { i18n, loadI18nMessages, setI18nLanguage };
export { i18n, loadI18nMessages, loadLocalesMap, setI18nLanguage };

View File

@@ -0,0 +1,33 @@
import type {
ImportLocaleFn,
LoadMessageFn,
LocaleSetupOptions,
SupportedLanguagesType,
} from './typing';
import type { App } from 'vue';
import { i18n, loadI18nMessages, loadLocalesMap } from './i18n';
const $t = i18n.global.t;
let loadMessages: LoadMessageFn;
async function loadLocaleMessages(lang: SupportedLanguagesType) {
const mergeMessage = await loadMessages(lang);
await loadI18nMessages(lang);
i18n.global.mergeLocaleMessage(lang, mergeMessage);
}
async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
const { defaultLocale = 'zh-CN' } = options;
// app可以自行扩展一些第三方库和组件库的国际化
loadMessages = options.loadMessages || (async () => ({}));
app.use(i18n);
await loadLocaleMessages(defaultLocale);
}
export { $t, loadLocaleMessages, loadLocalesMap, setupI18n };
export { useI18n } from 'vue-i18n';
export type { Locale } from 'vue-i18n';
export type { ImportLocaleFn };

View File

@@ -1,32 +1,4 @@
page:
demos:
title: Demos
access:
title: Access Control
frontend-control: Front-end Control
# menuVisibleWithForbidden: Menu is visible
backend-control: Backend Control
page: Page visit
button: Button control
loading-menu: In the loading menu
access-test-1: Super visit
access-test-2: Admin visit
access-test-3: User visit
nested:
title: Nested Menu
menu1: Menu 1
menu2: Menu 2
menu21: Menu 2-1
menu3: Menu 3
menu31: Menu 3-1
menu32: Menu 3-2
menu321: Menu 3-2-1
outside:
title: External Page
embedded: embedded Page
external-link: External Link
fallback:
title: Fallback Page
essentials:
login: Login
register: Register

View File

@@ -1,32 +1,4 @@
page:
demos:
title: 演示
access:
title: 访问控制
frontend-control: 前端控制
# menuVisibleWithForbidden: 菜单可见
backend-control: 后端控制
page: 页面访问
button: 按钮控制
access-test-1: Super 可见
access-test-2: Admin 可见
access-test-3: User 可见
nested:
title: 嵌套菜单
menu1: 菜单 1
menu2: 菜单 2
menu21: 菜单 2-1
menu3: 菜单 3
menu31: 菜单 3-1
menu32: 菜单 3-2
menu321: 菜单 3-2-1
outside:
title: 外部页面
embedded: 内嵌
external-link: 外链
fallback:
title: 缺省页
essentials:
login: 登陆
register: 注册

View File

@@ -2,6 +2,10 @@ import type { SupportedLanguagesType } from '@vben-core/typings';
type ImportLocaleFn = () => Promise<{ default: Record<string, string> }>;
type LoadMessageFn = (
lang: SupportedLanguagesType,
) => Promise<Record<string, string>>;
interface LocaleSetupOptions {
/**
* Default language
@@ -9,11 +13,16 @@ interface LocaleSetupOptions {
*/
defaultLocale?: SupportedLanguagesType;
/**
* Load third-party library messages
* Load message function
* @param lang
* @returns
*/
loadThirdPartyMessage?: (lang: SupportedLanguagesType) => Promise<void>;
loadMessages?: LoadMessageFn;
}
export type { ImportLocaleFn, LocaleSetupOptions, SupportedLanguagesType };
export type {
ImportLocaleFn,
LoadMessageFn,
LocaleSetupOptions,
SupportedLanguagesType,
};

View File

@@ -37,10 +37,10 @@
}
},
"dependencies": {
"@vben-core/locales": "workspace:*",
"@vben-core/preferences": "workspace:*",
"@vben-core/stores": "workspace:*",
"@vben-core/toolkit": "workspace:*",
"@vben/locales": "workspace:*",
"vue": "^3.4.31",
"vue-router": "^4.4.0"
},

View File

@@ -6,7 +6,7 @@ import type { RouteRecordRaw } from 'vue-router';
import type { GeneratorMenuAndRoutesOptions } from '../types';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import { mapTree } from '@vben-core/toolkit';
/**

View File

@@ -40,13 +40,13 @@
"@vben-core/helpers": "workspace:*",
"@vben-core/iconify": "workspace:*",
"@vben-core/layout-ui": "workspace:*",
"@vben-core/locales": "workspace:*",
"@vben-core/menu-ui": "workspace:*",
"@vben-core/preferences": "workspace:*",
"@vben-core/shadcn-ui": "workspace:*",
"@vben-core/stores": "workspace:*",
"@vben-core/tabs-ui": "workspace:*",
"@vben-core/toolkit": "workspace:*",
"@vben/locales": "workspace:*",
"@vben/widgets": "workspace:*",
"vue": "^3.4.31",
"vue-router": "^4.4.0"

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed } from 'vue';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import { preferences, usePreferences } from '@vben-core/preferences';
import AuthenticationFromView from './from-view.vue';

View File

@@ -4,8 +4,8 @@ import type { VbenDropdownMenuItem } from '@vben-core/shadcn-ui';
import { computed } from 'vue';
import { $t } from '@vben/locales';
import { MdiDockBottom, MdiDockLeft, MdiDockRight } from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import {
preferences,
updatePreferences,

View File

@@ -1,9 +1,9 @@
<script lang="ts" setup>
import { computed } from 'vue';
import { $t } from '@vben/locales';
import { PreferencesWidget } from '@vben/widgets';
import { VbenAdminLayout } from '@vben-core/layout-ui';
import { $t } from '@vben-core/locales';
import {
preferences,
updatePreferences,

View File

@@ -8,7 +8,6 @@ import type {
import { computed, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { $t, useI18n } from '@vben/locales';
import {
IcRoundClose,
IcRoundMultipleStop,
@@ -19,6 +18,7 @@ import {
MdiPin,
MdiPinOff,
} from '@vben-core/iconify';
import { $t, useI18n } from '@vben-core/locales';
import {
storeToRefs,
useCoreAccessStore,

View File

@@ -5,7 +5,7 @@ import type { IBreadcrumb } from '@vben-core/shadcn-ui';
import { computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import { VbenBackgroundBreadcrumb, VbenBreadcrumb } from '@vben-core/shadcn-ui';
interface Props {

View File

@@ -42,9 +42,9 @@
"dependencies": {
"@vben-core/design": "workspace:*",
"@vben-core/iconify": "workspace:*",
"@vben-core/locales": "workspace:*",
"@vben-core/shadcn-ui": "workspace:*",
"@vben/constants": "workspace:*",
"@vben/locales": "workspace:*",
"@vben/types": "workspace:*",
"@vueuse/integrations": "^10.11.0",
"qrcode": "^1.5.3",

View File

@@ -5,7 +5,7 @@ import { computed, onBeforeUnmount, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { LOGIN_PATH } from '@vben/constants';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import { VbenButton, VbenInput, VbenPinInput } from '@vben-core/shadcn-ui';
import Title from './auth-title.vue';

View File

@@ -3,7 +3,7 @@ import { computed, reactive } from 'vue';
import { useRouter } from 'vue-router';
import { LOGIN_PATH } from '@vben/constants';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import { VbenButton, VbenInput } from '@vben-core/shadcn-ui';
import Title from './auth-title.vue';

View File

@@ -4,7 +4,7 @@ import type { LoginEmits } from './typings';
import { computed, reactive } from 'vue';
import { useRouter } from 'vue-router';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import {
VbenButton,
VbenCheckbox,

View File

@@ -3,7 +3,7 @@ import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { LOGIN_PATH } from '@vben/constants';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import { VbenButton } from '@vben-core/shadcn-ui';
import { useQRCode } from '@vueuse/integrations/useQRCode';

View File

@@ -5,7 +5,7 @@ import { computed, reactive } from 'vue';
import { useRouter } from 'vue-router';
import { LOGIN_PATH } from '@vben/constants';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import {
VbenButton,
VbenCheckbox,

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { $t } from '@vben/locales';
import { MdiGithub, MdiGoogle, MdiQqchat, MdiWechat } from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import { VbenIconButton } from '@vben-core/shadcn-ui';
defineOptions({

View File

@@ -4,8 +4,8 @@ import type { FallbackProps } from './fallback';
import { computed, defineAsyncComponent } from 'vue';
import { useRouter } from 'vue-router';
import { $t } from '@vben/locales';
import { IcRoundArrowBackIosNew, IcRoundRefresh } from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import { VbenButton } from '@vben-core/shadcn-ui';
interface Props extends FallbackProps {}

View File

@@ -43,10 +43,10 @@
"@vben-core/colorful": "workspace:*",
"@vben-core/design": "workspace:*",
"@vben-core/iconify": "workspace:*",
"@vben-core/locales": "workspace:*",
"@vben-core/preferences": "workspace:*",
"@vben-core/shadcn-ui": "workspace:*",
"@vben-core/toolkit": "workspace:*",
"@vben/locales": "workspace:*",
"@vueuse/core": "^10.11.0",
"vue": "^3.4.31",
"vue-router": "^4.4.0"

View File

@@ -51,19 +51,19 @@ onUnmounted(() => {
});
</script>
<template>
<div ref="wrapperEl" class="coze-assistant"></div>
<div ref="wrapperEl" class="coze-vben-admin-assistant"></div>
</template>
<style>
.coze-assistant {
.coze-vben-admin-assistant {
position: fixed;
right: 30px;
bottom: 60px;
z-index: 1000;
img {
width: 42px !important;
height: 42px !important;
width: 50px !important;
height: 50px !important;
border-radius: 50%;
}
}

View File

@@ -3,7 +3,6 @@ import type { MenuRecordRaw } from '@vben/types';
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { $t } from '@vben/locales';
import {
IcRoundArrowDownward,
IcRoundArrowUpward,
@@ -11,6 +10,7 @@ import {
IcRoundSubdirectoryArrowLeft,
MdiKeyboardEsc,
} from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import {
Dialog,
DialogContent,

View File

@@ -4,8 +4,8 @@ import type { MenuRecordRaw } from '@vben/types';
import { nextTick, onMounted, ref, shallowRef, watch } from 'vue';
import { useRouter } from 'vue-router';
import { $t } from '@vben/locales';
import { IcRoundClose, IcRoundSearchOff } from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import { VbenIcon, VbenScrollbar } from '@vben-core/shadcn-ui';
import { mapTree, traverseTreeValues, uniqueByField } from '@vben-core/toolkit';

View File

@@ -1,8 +1,8 @@
<script setup lang="ts">
import type { SupportedLanguagesType } from '@vben/types';
import { loadLocaleMessages } from '@vben/locales';
import { IcBaselineLanguage } from '@vben-core/iconify';
import { loadLocaleMessages } from '@vben-core/locales';
import {
SUPPORT_LANGUAGES,
preferences,

View File

@@ -1,11 +1,11 @@
<script lang="ts" setup>
import type { NotificationItem } from './interface';
import { $t } from '@vben/locales';
import {
IcRoundMarkEmailRead,
IcRoundNotificationsNone,
} from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import {
VbenButton,
VbenIconButton,

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import SwitchItem from '../switch-item.vue';

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { SelectListItem } from '@vben/types';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import { SUPPORT_LANGUAGES } from '@vben-core/preferences';
import SelectItem from '../select-item.vue';

View File

@@ -3,7 +3,7 @@ import type { SelectListItem } from '@vben/types';
import { computed } from 'vue';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import SwitchItem from '../switch-item.vue';
import ToggleItem from '../toggle-item.vue';

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { type Component, computed } from 'vue';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import { ContentCompact, ContentWide } from '../../icons';

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import InputItem from '../input-item.vue';
import SwitchItem from '../switch-item.vue';

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import SwitchItem from '../switch-item.vue';

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { LayoutHeaderModeType, SelectListItem } from '@vben/types';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import SelectItem from '../select-item.vue';
import SwitchItem from '../switch-item.vue';

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import SwitchItem from '../switch-item.vue';

View File

@@ -3,8 +3,8 @@ import type { LayoutType } from '@vben/types';
import { type Component, computed } from 'vue';
import { $t } from '@vben/locales';
import { MdiQuestionMarkCircleOutline } from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import { VbenTooltip } from '@vben-core/shadcn-ui';
import {

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { SelectListItem } from '@vben/types';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import SwitchItem from '../switch-item.vue';
import ToggleItem from '../toggle-item.vue';

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import NumberFieldItem from '../number-field-item.vue';
import SwitchItem from '../switch-item.vue';

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import SwitchItem from '../switch-item.vue';

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed } from 'vue';
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import { isWindowsOs } from '@vben-core/toolkit';
import SwitchItem from '../switch-item.vue';

View File

@@ -3,9 +3,9 @@ import type { BuiltinThemeType } from '@vben/types';
import { computed, ref } from 'vue';
import { $t } from '@vben/locales';
import { TinyColor, convertToHsl } from '@vben-core/colorful';
import { MdiEditBoxOutline } from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import {
BUILT_IN_THEME_PRESETS,
type BuiltinThemePreset,

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import SwitchItem from '../switch-item.vue';

View File

@@ -3,12 +3,12 @@ import type { ThemeModeType } from '@vben-core/preferences';
import type { Component } from 'vue';
import { $t } from '@vben/locales';
import {
IcRoundMotionPhotosAuto,
IcRoundWbSunny,
MdiMoonAndStars,
} from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import SwitchItem from '../switch-item.vue';

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { loadLocaleMessages } from '@vben/locales';
import { loadLocaleMessages } from '@vben-core/locales';
import { preferences, updatePreferences } from '@vben-core/preferences';
import Preferences from './preferences.vue';

View File

@@ -15,8 +15,8 @@ import type { SegmentedItem } from '@vben-core/shadcn-ui';
import { computed, ref } from 'vue';
import { $t, loadLocaleMessages } from '@vben/locales';
import { IcRoundFolderCopy, IcRoundRestartAlt } from '@vben-core/iconify';
import { $t, loadLocaleMessages } from '@vben-core/locales';
import {
clearPreferencesCache,
preferences,

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { $t } from '@vben/locales';
import { $t } from '@vben-core/locales';
import { VbenButton } from '@vben-core/shadcn-ui';
import IconSetting from './icons/setting.vue';

View File

@@ -1,10 +1,10 @@
<script lang="ts" setup>
import { $t } from '@vben/locales';
import {
IcRoundMotionPhotosAuto,
IcRoundWbSunny,
MdiMoonAndStars,
} from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import {
type ThemeModeType,
preferences,

View File

@@ -4,8 +4,8 @@ import type { AnyFunction } from '@vben/types';
import type { Component } from 'vue';
import { computed, ref } from 'vue';
import { $t } from '@vben/locales';
import { IcRoundLogout, IcRoundSettingsSuggest } from '@vben-core/iconify';
import { $t } from '@vben-core/locales';
import { preferences, usePreferences } from '@vben-core/preferences';
import {
Badge,

View File

@@ -1,8 +0,0 @@
/**
* 没有任何实际作用,只用于 IDE 对I18的提示
*/
function $t(key: string) {
return key;
}
export { $t };

View File

@@ -1,26 +0,0 @@
import type { LocaleSetupOptions, SupportedLanguagesType } from './typing';
import type { App } from 'vue';
import { i18n, loadI18nMessages } from './i18n';
const $t = i18n.global.t;
let loadThirdPartyMessage: (lang: SupportedLanguagesType) => Promise<void>;
async function loadLocaleMessages(lang: SupportedLanguagesType) {
await loadI18nMessages(lang);
await loadThirdPartyMessage(lang);
}
async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
const { defaultLocale = 'zh-CN' } = options;
// app可以自行扩展一些第三方库和组件库的国际化
loadThirdPartyMessage = options.loadThirdPartyMessage || (async () => {});
app.use(i18n);
await loadLocaleMessages(defaultLocale);
}
export { $t, loadLocaleMessages, setupI18n };
export type { CompileError } from '@intlify/core-base';
export { useI18n } from 'vue-i18n';