@liujitcn/kratos-admin-core 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package/declarations/src/api/base/language.d.ts +3 -3
- package/dist/package/declarations/src/components/Dict/index.vue.d.ts +4 -3
- package/dist/package/declarations/src/components/Dict/value.d.ts +11 -0
- package/dist/package/declarations/src/locales/generated.d.ts +3382 -0
- package/dist/package/declarations/src/locales/index.d.ts +11 -21
- package/dist/package/declarations/src/rpc/base/v1/config.d.ts +11 -1
- package/dist/package/declarations/src/rpc/base/v1/language.d.ts +7 -13
- package/dist/package/declarations/src/rpc/base/v1/login.d.ts +13 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +1 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +7 -77
- package/dist/package/declarations/src/rpc/system/admin/v1/base_translation.d.ts +54 -81
- package/dist/package/declarations/src/rpc/system/admin/v1/common.d.ts +13 -0
- package/dist/package/declarations/src/stores/modules/auth.d.ts +6 -6
- package/dist/package/declarations/src/utils/passwordCrypto.d.ts +1 -1
- package/dist/package/src/App.vue +2 -8
- package/dist/package/src/api/base/language.ts +4 -4
- package/dist/package/src/bootstrap.ts +1 -1
- package/dist/package/src/components/CronExpression/index.vue +19 -19
- package/dist/package/src/components/Dialog/FormDialog.vue +1 -1
- package/dist/package/src/components/Dict/index.vue +21 -7
- package/dist/package/src/components/Dict/value.ts +18 -0
- package/dist/package/src/components/ImportExcel/index.vue +10 -10
- package/dist/package/src/components/LocaleSwitch/index.vue +1 -1
- package/dist/package/src/components/ProForm/components/DynamicList.vue +1 -1
- package/dist/package/src/components/ProForm/components/KvList.vue +2 -2
- package/dist/package/src/components/ProForm/index.vue +2 -2
- package/dist/package/src/components/ProTable/components/ColSetting.vue +3 -3
- package/dist/package/src/components/ProTable/components/TableColumn.vue +1 -1
- package/dist/package/src/components/ProTable/index.vue +4 -4
- package/dist/package/src/components/SearchForm/components/SearchFormItem.vue +2 -2
- package/dist/package/src/components/SelectFilter/index.vue +1 -1
- package/dist/package/src/components/TreeFilter/index.vue +4 -4
- package/dist/package/src/components/Upload/File.vue +6 -6
- package/dist/package/src/components/Upload/Files.vue +7 -7
- package/dist/package/src/components/Upload/Img.vue +4 -4
- package/dist/package/src/components/Upload/Imgs.vue +5 -5
- package/dist/package/src/components/WangEditor/index.vue +1 -1
- package/dist/package/src/hooks/useDownload.ts +1 -1
- package/dist/package/src/hooks/useHandleData.ts +2 -2
- package/dist/package/src/hooks/useTheme.ts +1 -1
- package/dist/package/src/layouts/components/Header/components/AssemblySize.vue +1 -1
- package/dist/package/src/layouts/components/Header/components/Avatar.vue +5 -5
- package/dist/package/src/layouts/components/Header/components/Breadcrumb.vue +2 -2
- package/dist/package/src/layouts/components/Header/components/Fullscreen.vue +2 -2
- package/dist/package/src/layouts/components/Header/components/PasswordDialog.vue +1 -1
- package/dist/package/src/layouts/components/Header/components/SearchMenu.vue +3 -3
- package/dist/package/src/layouts/components/Main/index.vue +1 -0
- package/dist/package/src/layouts/components/Tabs/components/MoreButton.vue +5 -5
- package/dist/package/src/layouts/components/Tabs/index.vue +15 -1
- package/dist/package/src/layouts/components/ThemeDrawer/index.vue +7 -7
- package/dist/package/src/locales/README.md +2 -2
- package/dist/package/src/locales/en-US.json +142 -117
- package/dist/package/src/locales/es-ES.json +226 -201
- package/dist/package/src/locales/fr-FR.json +226 -201
- package/dist/package/src/locales/generated.ts +57 -0
- package/dist/package/src/locales/index.ts +54 -55
- package/dist/package/src/locales/ja-JP.json +177 -152
- package/dist/package/src/locales/ko-KR.json +221 -196
- package/dist/package/src/locales/zh-CN.json +142 -117
- package/dist/package/src/locales/zh-TW.json +147 -122
- package/dist/package/src/modules/kratosAdmin.ts +3 -17
- package/dist/package/src/routers/modules/dynamicRouter.ts +4 -4
- package/dist/package/src/routers/modules/staticRouter.ts +2 -2
- package/dist/package/src/rpc/base/v1/config.ts +12 -1
- package/dist/package/src/rpc/base/v1/language.ts +7 -13
- package/dist/package/src/rpc/base/v1/login.ts +14 -1
- package/dist/package/src/rpc/system/admin/v1/auth.ts +1 -1
- package/dist/package/src/rpc/system/admin/v1/base_dict.ts +7 -79
- package/dist/package/src/rpc/system/admin/v1/base_translation.ts +54 -81
- package/dist/package/src/rpc/system/admin/v1/common.ts +21 -0
- package/dist/package/src/stores/modules/config.ts +2 -2
- package/dist/package/src/stores/modules/user.ts +1 -1
- package/dist/package/src/styles/element.scss +2 -0
- package/dist/package/src/utils/color.ts +4 -4
- package/dist/package/src/utils/eleValidate.ts +2 -2
- package/dist/package/src/utils/index.ts +3 -3
- package/dist/package/src/utils/passwordCrypto.ts +2 -2
- package/dist/package/src/utils/request.ts +6 -6
- package/dist/package/src/views/login/components/LoginForm.vue +15 -12
- package/package.json +2 -2
- package/vite.config.ts +12 -8
- package/dist/package/declarations/src/rpc/base/v1/enum.d.ts +0 -43
- package/dist/package/declarations/src/rpc/system/common/v1/enum.d.ts +0 -67
- package/dist/package/src/rpc/base/v1/enum.ts +0 -54
- package/dist/package/src/rpc/system/common/v1/enum.ts +0 -80
|
@@ -3,22 +3,21 @@
|
|
|
3
3
|
* 各语言 JSON 由对应模块定义文件导入,不能在 JSON 文件内添加注释。
|
|
4
4
|
*/
|
|
5
5
|
import dayjs from "dayjs";
|
|
6
|
-
import "dayjs/locale/en";
|
|
7
|
-
import "dayjs/locale/ja";
|
|
8
|
-
import "dayjs/locale/zh-cn";
|
|
9
|
-
import "dayjs/locale/zh-tw";
|
|
10
|
-
import "dayjs/locale/ko";
|
|
11
|
-
import "dayjs/locale/fr";
|
|
12
|
-
import "dayjs/locale/es";
|
|
13
6
|
import { computed, readonly, ref } from "vue";
|
|
14
7
|
import { createI18n } from "vue-i18n";
|
|
15
8
|
import type { AdminModule } from "../modules";
|
|
16
|
-
import type {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
import type { OptionLanguageResponse } from "../rpc/base/v1/language";
|
|
10
|
+
import {
|
|
11
|
+
DAYJS_LOCALE_MAP,
|
|
12
|
+
DEFAULT_LOCALE as GENERATED_DEFAULT_LOCALE,
|
|
13
|
+
SUPPORTED_LOCALES as GENERATED_SUPPORTED_LOCALES,
|
|
14
|
+
type GeneratedLocale,
|
|
15
|
+
} from "./generated";
|
|
16
|
+
|
|
17
|
+
/** 管理端已打包的语言区域;运行时可切换列表由 base_language 接口决定。 */
|
|
18
|
+
export const SUPPORTED_LOCALES = GENERATED_SUPPORTED_LOCALES;
|
|
20
19
|
/** 管理端支持的语言区域类型。 */
|
|
21
|
-
export type SupportedLocale =
|
|
20
|
+
export type SupportedLocale = GeneratedLocale;
|
|
22
21
|
/** 单个模块的扁平语言包。 */
|
|
23
22
|
export type LocaleMessages = Record<string, string>;
|
|
24
23
|
/** 翻译插值参数。 */
|
|
@@ -28,15 +27,11 @@ export type LocaleParams = Record<string, string | number>;
|
|
|
28
27
|
export interface LocaleOption {
|
|
29
28
|
/** 标准语言代码。 */
|
|
30
29
|
language_code: SupportedLocale;
|
|
31
|
-
/** 语言名称。 */
|
|
32
|
-
language_name: string;
|
|
33
30
|
/** 本地语言名称。 */
|
|
34
31
|
native_name: string;
|
|
35
|
-
/** 排序值。 */
|
|
36
|
-
sort: number;
|
|
37
32
|
}
|
|
38
33
|
|
|
39
|
-
export const DEFAULT_LOCALE: SupportedLocale =
|
|
34
|
+
export const DEFAULT_LOCALE: SupportedLocale = GENERATED_DEFAULT_LOCALE;
|
|
40
35
|
export const LOCALE_STORAGE_KEY = "kratos-admin:locale";
|
|
41
36
|
|
|
42
37
|
const mutableLocale = ref<SupportedLocale>(DEFAULT_LOCALE);
|
|
@@ -48,7 +43,6 @@ export const adminI18n = createI18n({
|
|
|
48
43
|
legacy: false,
|
|
49
44
|
locale: DEFAULT_LOCALE,
|
|
50
45
|
fallbackLocale: DEFAULT_LOCALE,
|
|
51
|
-
flatJson: true,
|
|
52
46
|
messages: {},
|
|
53
47
|
missingWarn: false,
|
|
54
48
|
fallbackWarn: false
|
|
@@ -56,48 +50,37 @@ export const adminI18n = createI18n({
|
|
|
56
50
|
|
|
57
51
|
/** 规范化任意语言输入到管理端白名单。 */
|
|
58
52
|
export function normalizeLocale(value?: string): SupportedLocale {
|
|
59
|
-
|
|
60
|
-
.replace("_", "-")
|
|
61
|
-
.toLowerCase();
|
|
62
|
-
if (normalized.startsWith("ja")) return "ja-JP";
|
|
63
|
-
if (normalized.startsWith("en")) return "en-US";
|
|
64
|
-
if (normalized.startsWith("zh-tw") || normalized.startsWith("zh-hk") || normalized.startsWith("zh-mo")) return "zh-TW";
|
|
65
|
-
if (normalized.startsWith("ko")) return "ko-KR";
|
|
66
|
-
if (normalized.startsWith("fr")) return "fr-FR";
|
|
67
|
-
if (normalized.startsWith("es")) return "es-ES";
|
|
68
|
-
return DEFAULT_LOCALE;
|
|
53
|
+
return parseSupportedLocale(value) ?? DEFAULT_LOCALE;
|
|
69
54
|
}
|
|
70
55
|
|
|
71
56
|
/** 将接口或系统语言代码解析为已打包的语言区域。 */
|
|
72
57
|
function parseSupportedLocale(value?: string): SupportedLocale | undefined {
|
|
73
58
|
const normalized = String(value ?? "").replace("_", "-").toLowerCase();
|
|
74
|
-
if (normalized
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (normalized.startsWith("es")) return "es-ES";
|
|
81
|
-
return undefined;
|
|
59
|
+
if (!normalized) return undefined;
|
|
60
|
+
const alias = normalized.startsWith("zh-hk") || normalized.startsWith("zh-mo") ? "zh-tw" : normalized;
|
|
61
|
+
const exact = SUPPORTED_LOCALES.find(locale => locale.toLowerCase() === alias);
|
|
62
|
+
if (exact) return exact;
|
|
63
|
+
const language = alias.split("-", 1)[0];
|
|
64
|
+
return SUPPORTED_LOCALES.find(locale => locale.toLowerCase().split("-", 1)[0] === language);
|
|
82
65
|
}
|
|
83
66
|
|
|
84
|
-
/**
|
|
67
|
+
/** 注册模块语言包并校验语言键、占位符和命名空间。 */
|
|
85
68
|
export function registerLocaleMessages(modules: AdminModule[]): void {
|
|
86
69
|
const merged = new Map<SupportedLocale, LocaleMessages>(SUPPORTED_LOCALES.map(locale => [locale, {}]));
|
|
87
70
|
|
|
88
71
|
modules.forEach(module => {
|
|
89
72
|
if (!module.messages) return;
|
|
90
|
-
const expectedKeys =
|
|
73
|
+
const expectedKeys = requiredLocaleKeys(module.messages[DEFAULT_LOCALE] ?? {});
|
|
91
74
|
SUPPORTED_LOCALES.forEach(locale => {
|
|
92
75
|
const messages = module.messages?.[locale];
|
|
93
76
|
if (!messages) throw new Error(`${module.name} 缺少 ${locale} 语言包`);
|
|
94
|
-
const keys =
|
|
77
|
+
const keys = requiredLocaleKeys(messages);
|
|
95
78
|
if (keys.join("\u0000") !== expectedKeys.join("\u0000")) {
|
|
96
79
|
throw new Error(`${module.name} 的 ${locale} 语言包键集合不一致`);
|
|
97
80
|
}
|
|
98
81
|
|
|
99
82
|
const target = merged.get(locale) as LocaleMessages;
|
|
100
|
-
keys.forEach(key => {
|
|
83
|
+
Object.keys(messages).forEach(key => {
|
|
101
84
|
assertLocaleKeyNamespace(module.name, key);
|
|
102
85
|
if (Object.prototype.hasOwnProperty.call(target, key)) {
|
|
103
86
|
throw new Error(`${locale} 语言键重复: ${key}`);
|
|
@@ -119,24 +102,21 @@ export function initializeLocale(): SupportedLocale {
|
|
|
119
102
|
return mutableLocale.value;
|
|
120
103
|
}
|
|
121
104
|
|
|
122
|
-
/**
|
|
123
|
-
export function applyLanguageConfig(response:
|
|
105
|
+
/** 应用后端语言配置,并在当前语言不可用时回退到接口第一项。 */
|
|
106
|
+
export function applyLanguageConfig(response: OptionLanguageResponse): void {
|
|
124
107
|
const options = response.languages.reduce<LocaleOption[]>((items, item) => {
|
|
125
108
|
const languageCode = parseSupportedLocale(item.language_code);
|
|
126
109
|
if (!languageCode || items.some((option) => option.language_code === languageCode)) return items;
|
|
127
110
|
items.push({
|
|
128
111
|
language_code: languageCode,
|
|
129
|
-
|
|
130
|
-
native_name: item.native_name || item.language_name || languageCode,
|
|
131
|
-
sort: item.sort,
|
|
112
|
+
native_name: item.native_name || languageCode,
|
|
132
113
|
});
|
|
133
114
|
return items;
|
|
134
115
|
}, []);
|
|
135
|
-
mutableLanguageOptions.value = options.length ? options
|
|
116
|
+
mutableLanguageOptions.value = options.length ? options : getFallbackLanguageOptions();
|
|
136
117
|
const availableLocales = getSupportedLocales();
|
|
137
|
-
const primaryLocale = parseSupportedLocale(response.primary_language_code);
|
|
138
118
|
if (!availableLocales.includes(mutableLocale.value)) {
|
|
139
|
-
applyLocale(
|
|
119
|
+
applyLocale(availableLocales[0] ?? DEFAULT_LOCALE);
|
|
140
120
|
}
|
|
141
121
|
}
|
|
142
122
|
|
|
@@ -194,18 +174,31 @@ export function useLocaleStore() {
|
|
|
194
174
|
}
|
|
195
175
|
|
|
196
176
|
function getFallbackLanguageOptions(): LocaleOption[] {
|
|
197
|
-
return SUPPORTED_LOCALES.map(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
})
|
|
177
|
+
return SUPPORTED_LOCALES.map(languageCode => {
|
|
178
|
+
return {
|
|
179
|
+
language_code: languageCode,
|
|
180
|
+
native_name: fallbackNativeLanguageName(languageCode),
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function fallbackNativeLanguageName(languageCode: SupportedLocale): string {
|
|
186
|
+
return {
|
|
187
|
+
"zh-CN": "简体中文",
|
|
188
|
+
"zh-TW": "繁體中文",
|
|
189
|
+
"en-US": "English",
|
|
190
|
+
"ja-JP": "日本語",
|
|
191
|
+
"ko-KR": "한국어",
|
|
192
|
+
"fr-FR": "Français",
|
|
193
|
+
"es-ES": "Español",
|
|
194
|
+
}[languageCode];
|
|
203
195
|
}
|
|
204
196
|
|
|
205
197
|
function applyLocale(locale: SupportedLocale): void {
|
|
206
198
|
mutableLocale.value = locale;
|
|
207
199
|
adminI18n.global.locale.value = locale;
|
|
208
|
-
|
|
200
|
+
const dayjsLocale = DAYJS_LOCALE_MAP[locale];
|
|
201
|
+
if (dayjsLocale) dayjs.locale(dayjsLocale);
|
|
209
202
|
document.documentElement.lang = locale;
|
|
210
203
|
}
|
|
211
204
|
|
|
@@ -215,6 +208,12 @@ function assertLocaleKeyNamespace(moduleName: string, key: string): void {
|
|
|
215
208
|
if (!valid) throw new Error(`${moduleName} 的语言键命名空间无效: ${key}`);
|
|
216
209
|
}
|
|
217
210
|
|
|
211
|
+
function requiredLocaleKeys(messages: LocaleMessages): string[] {
|
|
212
|
+
return Object.keys(messages)
|
|
213
|
+
.filter(key => !key.startsWith("common.language."))
|
|
214
|
+
.sort();
|
|
215
|
+
}
|
|
216
|
+
|
|
218
217
|
function assertLocalePlaceholders(moduleName: string, key: string, message: string, sourceMessage: string): void {
|
|
219
218
|
const placeholders = (value: string) => [...value.matchAll(/\{([A-Za-z0-9_]+)\}/g)].map(match => match[1]).sort();
|
|
220
219
|
if (placeholders(message).join("\u0000") !== placeholders(sourceMessage).join("\u0000")) {
|