refactor(i18n): 重构国际化模块结构
This commit is contained in:
6
auto-imports.d.ts
vendored
6
auto-imports.d.ts
vendored
@@ -53,6 +53,8 @@ declare global {
|
|||||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||||
const getCurrentWatcher: typeof import('vue')['getCurrentWatcher']
|
const getCurrentWatcher: typeof import('vue')['getCurrentWatcher']
|
||||||
const h: typeof import('vue')['h']
|
const h: typeof import('vue')['h']
|
||||||
|
const i18nInstance: typeof import('./src/locales-utils/i18n-auto-imports')['i18nInstance']
|
||||||
|
const i18nRouteMessages: typeof import('./src/locales-utils/route-messages/route-messages-auto-imports')['i18nRouteMessages']
|
||||||
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
||||||
const inject: typeof import('vue')['inject']
|
const inject: typeof import('vue')['inject']
|
||||||
const injectLocal: typeof import('@vueuse/core')['injectLocal']
|
const injectLocal: typeof import('@vueuse/core')['injectLocal']
|
||||||
@@ -62,7 +64,6 @@ declare global {
|
|||||||
const isReadonly: typeof import('vue')['isReadonly']
|
const isReadonly: typeof import('vue')['isReadonly']
|
||||||
const isRef: typeof import('vue')['isRef']
|
const isRef: typeof import('vue')['isRef']
|
||||||
const isShallow: typeof import('vue')['isShallow']
|
const isShallow: typeof import('vue')['isShallow']
|
||||||
const locales4RouteMessages: typeof import('./src/locales-4-route/_messages-auto-imports')['locales4RouteMessages']
|
|
||||||
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
|
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
|
||||||
const mapActions: typeof import('pinia')['mapActions']
|
const mapActions: typeof import('pinia')['mapActions']
|
||||||
const mapGetters: typeof import('pinia')['mapGetters']
|
const mapGetters: typeof import('pinia')['mapGetters']
|
||||||
@@ -395,6 +396,8 @@ declare module 'vue' {
|
|||||||
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
|
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
|
||||||
readonly getCurrentWatcher: UnwrapRef<typeof import('vue')['getCurrentWatcher']>
|
readonly getCurrentWatcher: UnwrapRef<typeof import('vue')['getCurrentWatcher']>
|
||||||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||||
|
readonly i18nInstance: UnwrapRef<typeof import('./src/locales-utils/i18n-auto-imports')['i18nInstance']>
|
||||||
|
readonly i18nRouteMessages: UnwrapRef<typeof import('./src/locales-utils/route-messages/route-messages-auto-imports')['i18nRouteMessages']>
|
||||||
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
||||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||||
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
||||||
@@ -404,7 +407,6 @@ declare module 'vue' {
|
|||||||
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
|
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
|
||||||
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
|
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
|
||||||
readonly isShallow: UnwrapRef<typeof import('vue')['isShallow']>
|
readonly isShallow: UnwrapRef<typeof import('vue')['isShallow']>
|
||||||
readonly locales4RouteMessages: UnwrapRef<typeof import('./src/locales-4-route/_messages-auto-imports')['locales4RouteMessages']>
|
|
||||||
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
|
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
|
||||||
readonly mapActions: UnwrapRef<typeof import('pinia')['mapActions']>
|
readonly mapActions: UnwrapRef<typeof import('pinia')['mapActions']>
|
||||||
readonly mapGetters: UnwrapRef<typeof import('pinia')['mapGetters']>
|
readonly mapGetters: UnwrapRef<typeof import('pinia')['mapGetters']>
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
"{src,packages}/**/*.{css,less,scss,vue}": [
|
"{src,packages}/**/*.{css,less,scss,vue}": [
|
||||||
"stylelint --fix"
|
"stylelint --fix"
|
||||||
],
|
],
|
||||||
"{src/locales-4-route,src/locales}/**/*": "node scripts/type-check-for-lint-staged.mjs"
|
"{src/locales-utils,src/locales}/**/*": "node scripts/type-check-for-lint-staged.mjs"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export function useMetaLayoutsNMenuOptions({ menuInstRef }: { menuInstRef: Ref<M
|
|||||||
return key;
|
return key;
|
||||||
},
|
},
|
||||||
fallbackRoot: true,
|
fallbackRoot: true,
|
||||||
messages: locales4RouteMessages,
|
messages: i18nRouteMessages,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取路由表但是不包含布局路由
|
// 获取路由表但是不包含布局路由
|
||||||
|
|||||||
28
src/locales-utils/i18n-auto-imports.ts
Normal file
28
src/locales-utils/i18n-auto-imports.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/* https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n#static-bundle-importing
|
||||||
|
* All i18n resources specified in the plugin `include` option can be loaded
|
||||||
|
* at once using the import syntax
|
||||||
|
*/
|
||||||
|
import messages from '@intlify/unplugin-vue-i18n/messages';
|
||||||
|
|
||||||
|
import { createI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const locale = useLocalStorage<string>('app-locale', navigator.language);
|
||||||
|
|
||||||
|
// https://vue-i18n.intlify.dev/guide/essentials/started.html#registering-the-i18n-plugin
|
||||||
|
export const i18nInstance = createI18n({
|
||||||
|
legacy: false, // you must set `false`, to use Composition API
|
||||||
|
locale: locale.value,
|
||||||
|
fallbackRoot: false,
|
||||||
|
// flatJson: true,
|
||||||
|
missing: (locale, key /* , instance, type */) => {
|
||||||
|
consola.warn(`缺少国际化内容: locale='${locale}', key='${key}'`);
|
||||||
|
return `[${key}]`;
|
||||||
|
},
|
||||||
|
missingWarn: !true,
|
||||||
|
fallbackWarn: !true,
|
||||||
|
messages,
|
||||||
|
});
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
locale.value = i18nInstance.global.locale.value;
|
||||||
|
});
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# `locales-4-route`
|
# route-messages
|
||||||
|
|
||||||
此目录存放专门用于**路由名称**的国际化(i18n)消息。这些消息通过一套自定义的编译时安全机制,为应用的导航菜单提供标题。
|
此目录存放专门用于**路由名称**的国际化(i18n)消息。这些消息通过一套自定义的编译时安全机制,为应用的导航菜单提供标题。
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
3. **编译时检查**:此目录下的每个语言环境文件(如 `en-US.ts`)都必须使用 `satisfies PageTitleLocalizations` 来进行类型断言。
|
3. **编译时检查**:此目录下的每个语言环境文件(如 `en-US.ts`)都必须使用 `satisfies PageTitleLocalizations` 来进行类型断言。
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// src/locales-4-route/en-US.ts
|
// ./en-US.ts
|
||||||
export default { ... } satisfies PageTitleLocalizations;
|
export default { ... } satisfies PageTitleLocalizations;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -52,13 +52,13 @@
|
|||||||
使用上一步中自动生成的 `name` 作为键,在此目录的每个语言文件中添加翻译。
|
使用上一步中自动生成的 `name` 作为键,在此目录的每个语言文件中添加翻译。
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// src/locales-4-route/zh-CN.ts
|
// ./zh-CN.ts
|
||||||
export default {
|
export default {
|
||||||
// ... 其他翻译
|
// ... 其他翻译
|
||||||
DemosApiDemo: 'API 演示',
|
DemosApiDemo: 'API 演示',
|
||||||
} satisfies PageTitleLocalizations;
|
} satisfies PageTitleLocalizations;
|
||||||
|
|
||||||
// src/locales-4-route/en-US.ts
|
// ./en-US.ts
|
||||||
export default {
|
export default {
|
||||||
// ... 其他翻译
|
// ... 其他翻译
|
||||||
DemosApiDemo: 'API Demo',
|
DemosApiDemo: 'API Demo',
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import type { I18nOptions } from 'vue-i18n';
|
import type { I18nOptions } from 'vue-i18n';
|
||||||
|
|
||||||
const modules = import.meta.glob(['./*.ts', '!./_messages-auto-imports.ts'], {
|
const modules = import.meta.glob(['./*.ts', '!./route-messages-auto-imports'], {
|
||||||
eager: true,
|
eager: true,
|
||||||
import: 'default',
|
import: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
type MessageType = Record<string, string>;
|
type MessageType = Record<string, string>;
|
||||||
|
|
||||||
export const locales4RouteMessages: I18nOptions['messages'] = Object.entries(modules).reduce(
|
export const i18nRouteMessages: I18nOptions['messages'] = Object.entries(modules).reduce(
|
||||||
(messages, [path, mod]) => {
|
(messages, [path, mod]) => {
|
||||||
const locale = path.replace(/(\.\/|\.ts)/g, '');
|
const locale = path.replace(/(\.\/|\.ts)/g, '');
|
||||||
messages[locale] = mod as MessageType;
|
messages[locale] = mod as MessageType;
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePage({
|
definePage({ meta: { order: 1 } });
|
||||||
meta: {
|
const { t, locale } = useI18n({});
|
||||||
order: 1,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const { t, locale } = useI18n();
|
|
||||||
|
|
||||||
function setLocale(newLocale: 'en-US' | 'zh-CN') {
|
function setLocale(newLocale: 'en-US' | 'zh-CN') {
|
||||||
locale.value = newLocale;
|
i18nInstance.global.locale.value = newLocale;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,3 @@
|
|||||||
/* https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n#static-bundle-importing
|
|
||||||
* All i18n resources specified in the plugin `include` option can be loaded
|
|
||||||
* at once using the import syntax
|
|
||||||
*/
|
|
||||||
import messages from '@intlify/unplugin-vue-i18n/messages';
|
|
||||||
|
|
||||||
import { createI18n } from 'vue-i18n';
|
|
||||||
|
|
||||||
export function install({ app }: { app: import('vue').App<Element> }) {
|
export function install({ app }: { app: import('vue').App<Element> }) {
|
||||||
const locale = useLocalStorage<string>('app-locale', navigator.language);
|
app.use(i18nInstance);
|
||||||
|
|
||||||
// https://vue-i18n.intlify.dev/guide/essentials/started.html#registering-the-i18n-plugin
|
|
||||||
const i18n = createI18n({
|
|
||||||
legacy: false, // you must set `false`, to use Composition API
|
|
||||||
locale: locale.value,
|
|
||||||
fallbackRoot: false,
|
|
||||||
// flatJson: true,
|
|
||||||
missing: (locale, key /* , instance, type */) => {
|
|
||||||
consola.warn(`缺少国际化内容: locale='${locale}', key='${key}'`);
|
|
||||||
return `[${key}]`;
|
|
||||||
},
|
|
||||||
missingWarn: !true,
|
|
||||||
fallbackWarn: !true,
|
|
||||||
messages,
|
|
||||||
});
|
|
||||||
watchEffect(() => {
|
|
||||||
locale.value = i18n.global.locale.value;
|
|
||||||
});
|
|
||||||
app.use(i18n);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user