mirror of
https://github.com/cool-team-official/cool-admin-midway.git
synced 2025-12-11 00:22:49 +00:00
优化eps
This commit is contained in:
parent
71ee2e7393
commit
6a499c033f
@ -75,7 +75,7 @@ export default {
|
||||
// 国际化配置
|
||||
i18n: {
|
||||
// 是否开启
|
||||
enable: false,
|
||||
enable: true,
|
||||
// 语言
|
||||
languages: ['zh-cn', 'zh-tw', 'en'],
|
||||
},
|
||||
|
||||
@ -22,6 +22,24 @@ export default {
|
||||
entities,
|
||||
subscribers: [TenantSubscriber],
|
||||
},
|
||||
// default: {
|
||||
// type: 'mysql',
|
||||
// host: '127.0.0.1',
|
||||
// port: 3306,
|
||||
// username: 'root',
|
||||
// password: '123456',
|
||||
// database: 'cool',
|
||||
// // 自动建表 注意:线上部署的时候不要使用,有可能导致数据丢失
|
||||
// synchronize: true,
|
||||
// // 打印日志
|
||||
// logging: false,
|
||||
// // 字符集
|
||||
// charset: 'utf8mb4',
|
||||
// // 是否开启缓存
|
||||
// cache: true,
|
||||
// // 实体路径
|
||||
// entities: ['**/modules/*/entity'],
|
||||
// },
|
||||
},
|
||||
},
|
||||
cool: {
|
||||
|
||||
1
src/locales/dict/.lock
Normal file
1
src/locales/dict/.lock
Normal file
@ -0,0 +1 @@
|
||||
2025-01-21T11:32:10.104Z
|
||||
11
src/locales/dict/info/en.json
Normal file
11
src/locales/dict/info/en.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"COOL": "COOL",
|
||||
"闪酷": "Flashy",
|
||||
"法师": "Mage",
|
||||
"战士": "Warrior",
|
||||
"坦克": "Tank",
|
||||
"刺客": "Assassin",
|
||||
"射手": "Shooter",
|
||||
"幻影刺客": "Phantom Assassin",
|
||||
"你好": "Hello"
|
||||
}
|
||||
11
src/locales/dict/info/zh-cn.json
Normal file
11
src/locales/dict/info/zh-cn.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"COOL": "COOL",
|
||||
"闪酷": "闪酷",
|
||||
"法师": "法师",
|
||||
"战士": "战士",
|
||||
"坦克": "坦克",
|
||||
"刺客": "刺客",
|
||||
"射手": "射手",
|
||||
"幻影刺客": "幻影刺客",
|
||||
"你好": "你好"
|
||||
}
|
||||
11
src/locales/dict/info/zh-tw.json
Normal file
11
src/locales/dict/info/zh-tw.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"COOL": "酷",
|
||||
"闪酷": "閃酷",
|
||||
"法师": "法師",
|
||||
"战士": "戰士",
|
||||
"坦克": "坦克",
|
||||
"刺客": "刺客",
|
||||
"射手": "射手",
|
||||
"幻影刺客": "幻影刺客",
|
||||
"你好": "你好"
|
||||
}
|
||||
4
src/locales/dict/type/en.json
Normal file
4
src/locales/dict/type/en.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"品牌": "Brand",
|
||||
"职业": "Job"
|
||||
}
|
||||
4
src/locales/dict/type/zh-cn.json
Normal file
4
src/locales/dict/type/zh-cn.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"品牌": "品牌",
|
||||
"职业": "职业"
|
||||
}
|
||||
4
src/locales/dict/type/zh-tw.json
Normal file
4
src/locales/dict/type/zh-tw.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"品牌": "品牌",
|
||||
"职业": "職業"
|
||||
}
|
||||
1
src/locales/menu/.lock
Normal file
1
src/locales/menu/.lock
Normal file
@ -0,0 +1 @@
|
||||
2025-01-21T11:32:17.870Z
|
||||
47
src/locales/menu/en.json
Normal file
47
src/locales/menu/en.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"系统管理": "System",
|
||||
"权限管理": "Auth",
|
||||
"菜单列表": "Menu",
|
||||
"新增": "Add",
|
||||
"删除": "Del",
|
||||
"查询": "Search",
|
||||
"参数": "Param",
|
||||
"编辑": "Edit",
|
||||
"角色列表": "Role",
|
||||
"修改": "Modify",
|
||||
"用户列表": "User",
|
||||
"部门列表": "Dept",
|
||||
"新增部门": "Add Dept",
|
||||
"更新部门": "Update Dept",
|
||||
"删除部门": "Del Dept",
|
||||
"部门排序": "Sort Dept",
|
||||
"用户转移": "Transfer",
|
||||
"参数配置": "Config",
|
||||
"参数列表": "Param List",
|
||||
"查看": "View",
|
||||
"监控管理": "Monitor",
|
||||
"请求日志": "Log",
|
||||
"权限": "Auth",
|
||||
"任务管理": "Task",
|
||||
"任务列表": "Task List",
|
||||
"框架教程": "Tutorial",
|
||||
"文档官网": "Docs",
|
||||
"crud 示例": "CRUD",
|
||||
"通用": "Common",
|
||||
"图片上传": "Upload",
|
||||
"首页": "Home",
|
||||
"数据管理": "Data",
|
||||
"字典管理": "Dict",
|
||||
"获得字典数据": "Get Dict",
|
||||
"单个信息": "Single",
|
||||
"列表查询": "List",
|
||||
"分页查询": "Page",
|
||||
"组权限": "Group",
|
||||
"字典类型": "Dict Type",
|
||||
"数据回收站": "Recycle",
|
||||
"恢复数据": "Restore",
|
||||
"文件管理": "File",
|
||||
"用户管理": "User",
|
||||
"扩展管理": "Extend",
|
||||
"插件列表": "Plugin"
|
||||
}
|
||||
47
src/locales/menu/zh-cn.json
Normal file
47
src/locales/menu/zh-cn.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"系统管理": "系统管理",
|
||||
"权限管理": "权限管理",
|
||||
"菜单列表": "菜单列表",
|
||||
"新增": "新增",
|
||||
"删除": "删除",
|
||||
"查询": "查询",
|
||||
"参数": "参数",
|
||||
"编辑": "编辑",
|
||||
"角色列表": "角色列表",
|
||||
"修改": "修改",
|
||||
"用户列表": "用户列表",
|
||||
"部门列表": "部门列表",
|
||||
"新增部门": "新增部门",
|
||||
"更新部门": "更新部门",
|
||||
"删除部门": "删除部门",
|
||||
"部门排序": "部门排序",
|
||||
"用户转移": "用户转移",
|
||||
"参数配置": "参数配置",
|
||||
"参数列表": "参数列表",
|
||||
"查看": "查看",
|
||||
"监控管理": "监控管理",
|
||||
"请求日志": "请求日志",
|
||||
"权限": "权限",
|
||||
"任务管理": "任务管理",
|
||||
"任务列表": "任务列表",
|
||||
"框架教程": "框架教程",
|
||||
"文档官网": "文档官网",
|
||||
"crud 示例": "crud 示例",
|
||||
"通用": "通用",
|
||||
"图片上传": "图片上传",
|
||||
"首页": "首页",
|
||||
"数据管理": "数据管理",
|
||||
"字典管理": "字典管理",
|
||||
"获得字典数据": "获得字典数据",
|
||||
"单个信息": "单个信息",
|
||||
"列表查询": "列表查询",
|
||||
"分页查询": "分页查询",
|
||||
"组权限": "组权限",
|
||||
"字典类型": "字典类型",
|
||||
"数据回收站": "数据回收站",
|
||||
"恢复数据": "恢复数据",
|
||||
"文件管理": "文件管理",
|
||||
"用户管理": "用户管理",
|
||||
"扩展管理": "扩展管理",
|
||||
"插件列表": "插件列表"
|
||||
}
|
||||
47
src/locales/menu/zh-tw.json
Normal file
47
src/locales/menu/zh-tw.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"系统管理": "系統管理",
|
||||
"权限管理": "權限管理",
|
||||
"菜单列表": "選單列表",
|
||||
"新增": "新增",
|
||||
"删除": "刪除",
|
||||
"查询": "查詢",
|
||||
"参数": "參數",
|
||||
"编辑": "編輯",
|
||||
"角色列表": "角色列表",
|
||||
"修改": "修改",
|
||||
"用户列表": "用戶列表",
|
||||
"部门列表": "部門列表",
|
||||
"新增部门": "新增部門",
|
||||
"更新部门": "更新部門",
|
||||
"删除部门": "刪除部門",
|
||||
"部门排序": "部門排序",
|
||||
"用户转移": "用戶轉移",
|
||||
"参数配置": "參數配置",
|
||||
"参数列表": "參數列表",
|
||||
"查看": "查看",
|
||||
"监控管理": "監控管理",
|
||||
"请求日志": "請求日誌",
|
||||
"权限": "權限",
|
||||
"任务管理": "任務管理",
|
||||
"任务列表": "任務列表",
|
||||
"框架教程": "框架教程",
|
||||
"文档官网": "文件官網",
|
||||
"crud 示例": "crud 示例",
|
||||
"通用": "通用",
|
||||
"图片上传": "圖片上傳",
|
||||
"首页": "首頁",
|
||||
"数据管理": "數據管理",
|
||||
"字典管理": "字典管理",
|
||||
"获得字典数据": "獲得字典數據",
|
||||
"单个信息": "單個信息",
|
||||
"列表查询": "列表查詢",
|
||||
"分页查询": "分頁查詢",
|
||||
"组权限": "組權限",
|
||||
"字典类型": "字典類型",
|
||||
"数据回收站": "數據回收站",
|
||||
"恢复数据": "恢復數據",
|
||||
"文件管理": "文件管理",
|
||||
"用户管理": "用戶管理",
|
||||
"扩展管理": "擴展管理",
|
||||
"插件列表": "插件列表"
|
||||
}
|
||||
1
src/locales/msg/.lock
Normal file
1
src/locales/msg/.lock
Normal file
@ -0,0 +1 @@
|
||||
2025-01-21T11:32:17.869Z
|
||||
27
src/locales/msg/en.json
Normal file
27
src/locales/msg/en.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"登录失效~": "Login expired~",
|
||||
"登录失效或无权限访问~": "Login expired or no access~",
|
||||
"账户或密码不正确~": "Incorrect account or password~",
|
||||
"该用户未设置任何角色,无法登录~": "No role set, cannot login~",
|
||||
"验证码不正确": "Incorrect code",
|
||||
"代码结构不正确,请检查": "Invalid code structure, check",
|
||||
"存在相同的keyName": "Duplicate keyName",
|
||||
"非法操作~": "Illegal operation~",
|
||||
"用户名已经存在~": "Username exists~",
|
||||
"用户不存在": "User not found",
|
||||
"原密码错误": "Wrong old password",
|
||||
"非法的key值": "Invalid key",
|
||||
"上传文件为空": "Empty upload",
|
||||
"插件信息不完整": "Incomplete plugin info",
|
||||
"插件key不能为plugin,请更换其他key": "Plugin key cannot be 'plugin', change it",
|
||||
"更新失败,参数错误或者手机号已存在": "Update failed, wrong params or phone exists",
|
||||
"验证码错误": "Wrong code",
|
||||
"图片验证码错误": "Wrong image code",
|
||||
"获得手机号失败,请检查配置": "Failed to get phone, check config",
|
||||
"token类型非refreshToken": "Token type not refreshToken",
|
||||
"账号或密码错误": "Wrong account or password",
|
||||
"发送过于频繁,请稍后再试": "Too frequent, try later",
|
||||
"用户不存在或已被禁用": "User not found or disabled",
|
||||
"登录失败,请重试": "Login failed, retry",
|
||||
"获取手机号失败,请刷新重试": "Failed to get phone, refresh and retry"
|
||||
}
|
||||
27
src/locales/msg/zh-cn.json
Normal file
27
src/locales/msg/zh-cn.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"登录失效~": "登录失效~",
|
||||
"登录失效或无权限访问~": "登录失效或无权限访问~",
|
||||
"账户或密码不正确~": "账户或密码不正确~",
|
||||
"该用户未设置任何角色,无法登录~": "该用户未设置任何角色,无法登录~",
|
||||
"验证码不正确": "验证码不正确",
|
||||
"代码结构不正确,请检查": "代码结构不正确,请检查",
|
||||
"存在相同的keyName": "存在相同的keyName",
|
||||
"非法操作~": "非法操作~",
|
||||
"用户名已经存在~": "用户名已经存在~",
|
||||
"用户不存在": "用户不存在",
|
||||
"原密码错误": "原密码错误",
|
||||
"非法的key值": "非法的key值",
|
||||
"上传文件为空": "上传文件为空",
|
||||
"插件信息不完整": "插件信息不完整",
|
||||
"插件key不能为plugin,请更换其他key": "插件key不能为plugin,请更换其他key",
|
||||
"更新失败,参数错误或者手机号已存在": "更新失败,参数错误或者手机号已存在",
|
||||
"验证码错误": "验证码错误",
|
||||
"图片验证码错误": "图片验证码错误",
|
||||
"获得手机号失败,请检查配置": "获得手机号失败,请检查配置",
|
||||
"token类型非refreshToken": "token类型非refreshToken",
|
||||
"账号或密码错误": "账号或密码错误",
|
||||
"发送过于频繁,请稍后再试": "发送过于频繁,请稍后再试",
|
||||
"用户不存在或已被禁用": "用户不存在或已被禁用",
|
||||
"登录失败,请重试": "登录失败,请重试",
|
||||
"获取手机号失败,请刷新重试": "获取手机号失败,请刷新重试"
|
||||
}
|
||||
27
src/locales/msg/zh-tw.json
Normal file
27
src/locales/msg/zh-tw.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"登录失效~": "登入失效~",
|
||||
"登录失效或无权限访问~": "登入失效或無權限訪問~",
|
||||
"账户或密码不正确~": "帳號或密碼不正確~",
|
||||
"该用户未设置任何角色,无法登录~": "該用戶未設置任何角色,無法登入~",
|
||||
"验证码不正确": "驗證碼不正確",
|
||||
"代码结构不正确,请检查": "代碼結構不正確,請檢查",
|
||||
"存在相同的keyName": "存在相同的keyName",
|
||||
"非法操作~": "非法操作~",
|
||||
"用户名已经存在~": "用戶名已經存在~",
|
||||
"用户不存在": "用戶不存在",
|
||||
"原密码错误": "原密碼錯誤",
|
||||
"非法的key值": "非法的key值",
|
||||
"上传文件为空": "上傳文件為空",
|
||||
"插件信息不完整": "插件信息不完整",
|
||||
"插件key不能为plugin,请更换其他key": "插件key不能為plugin,請更換其他key",
|
||||
"更新失败,参数错误或者手机号已存在": "更新失敗,參數錯誤或手機號已存在",
|
||||
"验证码错误": "驗證碼錯誤",
|
||||
"图片验证码错误": "圖片驗證碼錯誤",
|
||||
"获得手机号失败,请检查配置": "獲取手機號失敗,請檢查配置",
|
||||
"token类型非refreshToken": "token類型非refreshToken",
|
||||
"账号或密码错误": "帳號或密碼錯誤",
|
||||
"发送过于频繁,请稍后再试": "發送過於頻繁,請稍後再試",
|
||||
"用户不存在或已被禁用": "用戶不存在或已被禁用",
|
||||
"登录失败,请重试": "登入失敗,請重試",
|
||||
"获取手机号失败,请刷新重试": "獲取手機號失敗,請刷新重試"
|
||||
}
|
||||
@ -30,7 +30,7 @@ export class BaseTranslateMiddleware
|
||||
resolve() {
|
||||
return async (ctx, next: NextFunction) => {
|
||||
const url = ctx.url;
|
||||
const language = 'en';
|
||||
const language = ctx.get('language');
|
||||
let data;
|
||||
try {
|
||||
data = await next();
|
||||
@ -58,7 +58,6 @@ export class BaseTranslateMiddleware
|
||||
}
|
||||
// 处理菜单翻译
|
||||
if (url == '/admin/base/comm/permmenu') {
|
||||
console.log(data);
|
||||
for (const menu of data.data.menus) {
|
||||
if (menu.name) {
|
||||
menu.name = await this.baseTranslateService.translate(
|
||||
@ -69,6 +68,47 @@ export class BaseTranslateMiddleware
|
||||
}
|
||||
}
|
||||
}
|
||||
if (url == '/admin/base/sys/menu/list') {
|
||||
for (const menu of data.data) {
|
||||
if (menu.name) {
|
||||
menu.name = await this.baseTranslateService.translate(
|
||||
'menu',
|
||||
language,
|
||||
menu.name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理字典翻译
|
||||
if (url == '/admin/dict/info/list') {
|
||||
for (const dict of data.data) {
|
||||
dict.name = await this.baseTranslateService.translate(
|
||||
'dict:info',
|
||||
language,
|
||||
dict.name
|
||||
);
|
||||
}
|
||||
}
|
||||
if (url == '/admin/dict/type/page') {
|
||||
for (const dict of data.data.list) {
|
||||
dict.name = await this.baseTranslateService.translate(
|
||||
'dict:type',
|
||||
language,
|
||||
dict.name
|
||||
);
|
||||
}
|
||||
}
|
||||
if (url == '/admin/dict/info/data' || url == '/app/dict/info/data') {
|
||||
for (const key in data.data) {
|
||||
for (const item of data.data[key]) {
|
||||
item.name = await this.baseTranslateService.translate(
|
||||
'dict:info',
|
||||
language,
|
||||
item.name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,8 @@ import {
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import axios from 'axios';
|
||||
import { DictInfoEntity } from '../../dict/entity/info';
|
||||
import { DictTypeEntity } from '../../dict/entity/type';
|
||||
/**
|
||||
* 翻译服务
|
||||
*/
|
||||
@ -24,6 +26,12 @@ export class BaseTranslateService {
|
||||
@InjectEntityModel(BaseSysMenuEntity)
|
||||
baseSysMenuEntity: Repository<BaseSysMenuEntity>;
|
||||
|
||||
@InjectEntityModel(DictInfoEntity)
|
||||
dictInfoEntity: Repository<DictInfoEntity>;
|
||||
|
||||
@InjectEntityModel(DictTypeEntity)
|
||||
dictTypeEntity: Repository<DictTypeEntity>;
|
||||
|
||||
// 基础路径
|
||||
basePath: string;
|
||||
|
||||
@ -47,6 +55,9 @@ export class BaseTranslateService {
|
||||
|
||||
msgMap: Record<string, string> = {};
|
||||
|
||||
// 添加字典映射
|
||||
dictMap: Record<string, string> = {};
|
||||
|
||||
/**
|
||||
* 检查是否存在锁文件
|
||||
*/
|
||||
@ -71,33 +82,65 @@ export class BaseTranslateService {
|
||||
this.basePath = path.join(this.app.getBaseDir(), '..', 'src', 'locales');
|
||||
}
|
||||
|
||||
// 清空现有映射
|
||||
this.menuMap = {};
|
||||
this.msgMap = {};
|
||||
this.dictMap = {};
|
||||
|
||||
// 加载菜单翻译
|
||||
const menuDir = path.join(this.basePath, 'menu');
|
||||
if (fs.existsSync(menuDir)) {
|
||||
const files = fs.readdirSync(menuDir);
|
||||
await this.loadTypeTranslations('menu', this.menuMap);
|
||||
|
||||
// 加载消息翻译
|
||||
await this.loadTypeTranslations('msg', this.msgMap);
|
||||
|
||||
// 加载字典翻译
|
||||
await this.loadDictTranslations();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载指定类型的翻译
|
||||
* @param type 翻译类型
|
||||
* @param map 映射对象
|
||||
*/
|
||||
private async loadTypeTranslations(
|
||||
type: 'menu' | 'msg',
|
||||
map: Record<string, string>
|
||||
) {
|
||||
const dirPath = path.join(this.basePath, type);
|
||||
if (fs.existsSync(dirPath)) {
|
||||
const files = fs.readdirSync(dirPath);
|
||||
for (const file of files) {
|
||||
if (file.endsWith('.json')) {
|
||||
const language = file.replace('.json', '');
|
||||
const content = fs.readFileSync(path.join(menuDir, file), 'utf-8');
|
||||
const content = fs.readFileSync(path.join(dirPath, file), 'utf-8');
|
||||
const translations = JSON.parse(content);
|
||||
for (const [key, value] of Object.entries(translations)) {
|
||||
this.menuMap[`${language}:${key}`] = value as string;
|
||||
map[`${language}:${key}`] = value as string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 加载消息翻译
|
||||
const msgDir = path.join(this.basePath, 'msg');
|
||||
if (fs.existsSync(msgDir)) {
|
||||
const files = fs.readdirSync(msgDir);
|
||||
for (const file of files) {
|
||||
if (file.endsWith('.json')) {
|
||||
const language = file.replace('.json', '');
|
||||
const content = fs.readFileSync(path.join(msgDir, file), 'utf-8');
|
||||
const translations = JSON.parse(content);
|
||||
for (const [key, value] of Object.entries(translations)) {
|
||||
this.msgMap[`${language}:${key}`] = value as string;
|
||||
/**
|
||||
* 加载字典翻译
|
||||
*/
|
||||
private async loadDictTranslations() {
|
||||
const dictTypes = ['info', 'type'];
|
||||
|
||||
for (const dictType of dictTypes) {
|
||||
const dirPath = path.join(this.basePath, 'dict', dictType);
|
||||
if (fs.existsSync(dirPath)) {
|
||||
const files = fs.readdirSync(dirPath);
|
||||
for (const file of files) {
|
||||
if (file.endsWith('.json')) {
|
||||
const language = file.replace('.json', '');
|
||||
const content = fs.readFileSync(path.join(dirPath, file), 'utf-8');
|
||||
const translations = JSON.parse(content);
|
||||
for (const [key, value] of Object.entries(translations)) {
|
||||
this.dictMap[`${language}:dict:${dictType}:${key}`] =
|
||||
value as string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -126,12 +169,23 @@ export class BaseTranslateService {
|
||||
|
||||
/**
|
||||
* 翻译
|
||||
* @param type 类型 menu | msg
|
||||
* @param type 类型 menu | msg | dict
|
||||
* @param language 语言
|
||||
* @param text 原文
|
||||
* @returns 翻译后的文本
|
||||
*/
|
||||
translate(type: 'menu' | 'msg', language: string, text: string): string {
|
||||
translate(
|
||||
type: 'menu' | 'msg' | 'dict:info' | 'dict:type',
|
||||
language: string,
|
||||
text: string
|
||||
): string {
|
||||
// 处理字典翻译
|
||||
if (type === 'dict:info' || type === 'dict:type') {
|
||||
const key = `${language}:${type}:${text}`;
|
||||
return this.dictMap[key] || text.split(':').pop() || text;
|
||||
}
|
||||
|
||||
// 处理菜单和消息翻译
|
||||
const map = type === 'menu' ? this.menuMap : this.msgMap;
|
||||
const key = `${language}:${text}`;
|
||||
return map[key] || text;
|
||||
@ -146,8 +200,9 @@ export class BaseTranslateService {
|
||||
|
||||
const menuLockExists = this.checkLockFile('menu');
|
||||
const msgLockExists = this.checkLockFile('msg');
|
||||
const dictLockExists = this.checkDictLockFile();
|
||||
|
||||
if (!menuLockExists || !msgLockExists) {
|
||||
if (!menuLockExists || !msgLockExists || !dictLockExists) {
|
||||
const tasks = [];
|
||||
if (!msgLockExists) {
|
||||
tasks.push(this.genBaseMsg());
|
||||
@ -155,14 +210,145 @@ export class BaseTranslateService {
|
||||
if (!menuLockExists) {
|
||||
tasks.push(this.genBaseMenu());
|
||||
}
|
||||
if (!dictLockExists) {
|
||||
tasks.push(this.genBaseDict());
|
||||
}
|
||||
await Promise.all(tasks);
|
||||
this.logger.info('All translations completed successfully');
|
||||
// 更新翻译映射
|
||||
await this.loadTranslations();
|
||||
await this.loadDictTranslations();
|
||||
} else {
|
||||
this.logger.info('Translation lock files exist, skipping translation');
|
||||
// 直接加载翻译文件到内存
|
||||
await this.loadTranslations();
|
||||
await this.loadDictTranslations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查字典锁文件
|
||||
*/
|
||||
private checkDictLockFile(): boolean {
|
||||
const lockFile = path.join(this.basePath, 'dict', '.lock');
|
||||
return fs.existsSync(lockFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建字典锁文件
|
||||
*/
|
||||
private createDictLockFile(): void {
|
||||
const lockFile = path.join(this.basePath, 'dict', '.lock');
|
||||
fs.writeFileSync(lockFile, new Date().toISOString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成基础字典
|
||||
*/
|
||||
async genBaseDict() {
|
||||
try {
|
||||
// 检查是否存在锁文件
|
||||
if (this.checkDictLockFile()) {
|
||||
this.logger.info('Dictionary lock file exists, skipping translation');
|
||||
return;
|
||||
}
|
||||
|
||||
const infos = await this.dictInfoEntity.find();
|
||||
const types = await this.dictTypeEntity.find();
|
||||
|
||||
// 确保目录存在
|
||||
const infoDir = path.join(this.basePath, 'dict', 'info');
|
||||
const typeDir = path.join(this.basePath, 'dict', 'type');
|
||||
fs.mkdirSync(infoDir, { recursive: true });
|
||||
fs.mkdirSync(typeDir, { recursive: true });
|
||||
|
||||
// 生成中文基础文件
|
||||
const infoContent = {};
|
||||
const typeContent = {};
|
||||
|
||||
for (const info of infos) {
|
||||
infoContent[info.name] = info.name;
|
||||
}
|
||||
for (const type of types) {
|
||||
typeContent[type.name] = type.name;
|
||||
}
|
||||
|
||||
const infoFile = path.join(infoDir, 'zh-cn.json');
|
||||
const typeFile = path.join(typeDir, 'zh-cn.json');
|
||||
|
||||
const infoText = JSON.stringify(infoContent, null, 2);
|
||||
const typeText = JSON.stringify(typeContent, null, 2);
|
||||
|
||||
fs.writeFileSync(infoFile, infoText);
|
||||
fs.writeFileSync(typeFile, typeText);
|
||||
|
||||
this.logger.info('Base dictionary files generated successfully');
|
||||
|
||||
// 翻译其他语言
|
||||
if (this.config?.enable && this.config.languages) {
|
||||
const translatePromises = [];
|
||||
|
||||
for (const language of this.config.languages) {
|
||||
if (language !== 'zh-cn') {
|
||||
// 翻译 info 字典
|
||||
translatePromises.push(
|
||||
this.invokeTranslate(infoText, language, infoDir, 'dict')
|
||||
);
|
||||
|
||||
// 翻译 type 字典
|
||||
translatePromises.push(
|
||||
this.invokeTranslate(typeText, language, typeDir, 'dict')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(translatePromises);
|
||||
this.logger.info('Dictionary translations completed successfully');
|
||||
}
|
||||
|
||||
// 创建锁文件
|
||||
this.createDictLockFile();
|
||||
|
||||
// 更新翻译映射
|
||||
await this.loadDictTranslations();
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to generate dictionary:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新字典翻译映射
|
||||
* @param language 语言
|
||||
*/
|
||||
async updateDictTranslationMap(language: string) {
|
||||
const infoFile = path.join(
|
||||
this.basePath,
|
||||
'dict',
|
||||
'info',
|
||||
`${language}.json`
|
||||
);
|
||||
const typeFile = path.join(
|
||||
this.basePath,
|
||||
'dict',
|
||||
'type',
|
||||
`${language}.json`
|
||||
);
|
||||
|
||||
if (fs.existsSync(infoFile)) {
|
||||
const content = fs.readFileSync(infoFile, 'utf-8');
|
||||
const translations = JSON.parse(content);
|
||||
for (const [key, value] of Object.entries(translations)) {
|
||||
this.dictMap[`${language}:dict:info:${key}`] = value as string;
|
||||
}
|
||||
}
|
||||
|
||||
if (fs.existsSync(typeFile)) {
|
||||
const content = fs.readFileSync(typeFile, 'utf-8');
|
||||
const translations = JSON.parse(content);
|
||||
for (const [key, value] of Object.entries(translations)) {
|
||||
this.dictMap[`${language}:dict:type:${key}`] = value as string;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -277,7 +463,7 @@ export class BaseTranslateService {
|
||||
text: string,
|
||||
language: string,
|
||||
dirPath: string,
|
||||
type: 'menu' | 'msg' = 'msg'
|
||||
type: 'menu' | 'msg' | 'dict' = 'msg'
|
||||
) {
|
||||
this.logger.info(`${type} ${language} translate start`);
|
||||
const response = await axios.post(I18N.DEFAULT_SERVICE_URL, {
|
||||
|
||||
@ -2,6 +2,7 @@ import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { DemoGoodsEntity } from '../../entity/goods';
|
||||
import { Get, Inject } from '@midwayjs/core';
|
||||
import { DemoGoodsService } from '../../service/goods';
|
||||
import { UserInfoEntity } from '../../../user/entity/info';
|
||||
|
||||
/**
|
||||
* 商品模块-商品信息
|
||||
@ -9,6 +10,19 @@ import { DemoGoodsService } from '../../service/goods';
|
||||
@CoolController({
|
||||
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||
entity: DemoGoodsEntity,
|
||||
pageQueryOp: {
|
||||
keyWordLikeFields: ['a.description'],
|
||||
fieldEq: ['a.status'],
|
||||
fieldLike: ['a.title'],
|
||||
select: ['a.*', 'b.nickName as userName'],
|
||||
join: [
|
||||
{
|
||||
entity: UserInfoEntity,
|
||||
alias: 'b',
|
||||
condition: 'a.id = b.id',
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
export class AdminDemoGoodsController extends BaseController {
|
||||
@Inject()
|
||||
|
||||
@ -12,6 +12,9 @@ import { Repository } from 'typeorm';
|
||||
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||
entity: DemoGoodsEntity,
|
||||
service: DemoGoodsService,
|
||||
pageQueryOp: {
|
||||
fieldLike: ['title'],
|
||||
},
|
||||
})
|
||||
export class OpenDemoGoodsController extends BaseController {
|
||||
@InjectEntityModel(DemoGoodsEntity)
|
||||
|
||||
@ -24,6 +24,12 @@ export class DemoGoodsEntity extends BaseEntity {
|
||||
@Column({ comment: '主图', nullable: true })
|
||||
mainImage: string;
|
||||
|
||||
@Column({ comment: '分类', dict: 'goodsType' })
|
||||
type: number;
|
||||
|
||||
@Column({ comment: '状态', dict: ['禁用', '启用'], default: 1 })
|
||||
status: number;
|
||||
|
||||
@Column({ comment: '示例图', nullable: true, type: 'json' })
|
||||
exampleImages: string[];
|
||||
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { BaseEntity } from '../../base/entity/base';
|
||||
import { Column, Entity, DataSource, Index } from 'typeorm';
|
||||
|
||||
console.log(DataSource);
|
||||
import { Column, Entity, Index } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 插件信息
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { CoolController, BaseController } from '@cool-midway/core';
|
||||
import { UserInfoEntity } from '../../entity/info';
|
||||
import { DemoGoodsEntity } from '../../../demo/entity/goods';
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
@ -9,7 +10,16 @@ import { UserInfoEntity } from '../../entity/info';
|
||||
entity: UserInfoEntity,
|
||||
pageQueryOp: {
|
||||
fieldEq: ['status', 'gender', 'loginType'],
|
||||
fieldLike: ['b.title'],
|
||||
keyWordLikeFields: ['nickName', 'phone'],
|
||||
select: ['a.*', 'b.title as goodsName'],
|
||||
join: [
|
||||
{
|
||||
entity: DemoGoodsEntity,
|
||||
alias: 'b',
|
||||
condition: 'a.id = b.id',
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
export class AdminUserInfoController extends BaseController {}
|
||||
|
||||
@ -20,15 +20,18 @@ export class UserInfoEntity extends BaseEntity {
|
||||
@Column({ comment: '手机号', nullable: true })
|
||||
phone: string;
|
||||
|
||||
@Column({ comment: '性别 0-未知 1-男 2-女', default: 0 })
|
||||
@Column({ comment: '性别', dict: ['未知', '男', '女'], default: 0 })
|
||||
gender: number;
|
||||
|
||||
@Column({ comment: '状态 0-禁用 1-正常 2-已注销', default: 1 })
|
||||
@Column({ comment: '状态', dict: ['禁用', '正常', '已注销'], default: 1 })
|
||||
status: number;
|
||||
|
||||
@Column({ comment: '登录方式 0-小程序 1-公众号 2-H5', default: 0 })
|
||||
@Column({ comment: '登录方式', dict: ['小程序', '公众号', 'H5'], default: 0 })
|
||||
loginType: number;
|
||||
|
||||
@Column({ comment: '来源', dict: 'sourceType', default: 0 })
|
||||
source: number;
|
||||
|
||||
@Column({ comment: '密码', nullable: true })
|
||||
password: string;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user