From 17cad1b1ca5480ff565ef7275b6e391eb88c9a8a Mon Sep 17 00:00:00 2001 From: COOL Date: Mon, 10 Feb 2025 18:29:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=89=B9=E6=AE=8A=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/base/service/translate.ts | 104 +++++++++++++++++++++-- src/modules/demo/controller/open/i18n.ts | 18 ++++ src/modules/demo/service/i18n.ts | 29 +++++++ 3 files changed, 144 insertions(+), 7 deletions(-) create mode 100644 src/modules/demo/controller/open/i18n.ts create mode 100644 src/modules/demo/service/i18n.ts diff --git a/src/modules/base/service/translate.ts b/src/modules/base/service/translate.ts index bf67c65..1fd4886 100644 --- a/src/modules/base/service/translate.ts +++ b/src/modules/base/service/translate.ts @@ -55,13 +55,15 @@ export class BaseTranslateService { msgMap: Record = {}; + commMap: Record = {}; + // 添加字典映射 dictMap: Record = {}; /** * 检查是否存在锁文件 */ - private checkLockFile(type: 'menu' | 'msg'): boolean { + private checkLockFile(type: 'menu' | 'msg' | 'comm'): boolean { const lockFile = path.join(this.basePath, type, '.lock'); return fs.existsSync(lockFile); } @@ -69,7 +71,7 @@ export class BaseTranslateService { /** * 创建锁文件 */ - private createLockFile(type: 'menu' | 'msg'): void { + private createLockFile(type: 'menu' | 'msg' | 'comm'): void { const lockFile = path.join(this.basePath, type, '.lock'); fs.writeFileSync(lockFile, new Date().toISOString()); } @@ -89,13 +91,16 @@ export class BaseTranslateService { this.menuMap = {}; this.msgMap = {}; this.dictMap = {}; - + this.commMap = {}; // 加载菜单翻译 await this.loadTypeTranslations('menu', this.menuMap); // 加载消息翻译 await this.loadTypeTranslations('msg', this.msgMap); + // 加载通用消息翻译 + await this.loadTypeTranslations('comm', this.commMap); + // 加载字典翻译 await this.loadDictTranslations(); } @@ -106,7 +111,7 @@ export class BaseTranslateService { * @param map 映射对象 */ private async loadTypeTranslations( - type: 'menu' | 'msg', + type: 'menu' | 'msg' | 'comm', map: Record ) { const dirPath = path.join(this.basePath, type); @@ -178,7 +183,7 @@ export class BaseTranslateService { * @returns 翻译后的文本 */ translate( - type: 'menu' | 'msg' | 'dict:info' | 'dict:type', + type: 'menu' | 'msg' | 'dict:info' | 'dict:type' | 'comm', language: string, text: string ): string { @@ -202,9 +207,10 @@ export class BaseTranslateService { this.basePath = path.join(this.app.getBaseDir(), '..', 'src', 'locales'); const menuLockExists = this.checkLockFile('menu'); const msgLockExists = this.checkLockFile('msg'); + const commLockExists = this.checkLockFile('comm'); const dictLockExists = this.checkDictLockFile(); - if (!menuLockExists || !msgLockExists || !dictLockExists) { + if (!menuLockExists || !msgLockExists || !dictLockExists || !commLockExists) { const tasks = []; if (!msgLockExists) { tasks.push(this.genBaseMsg()); @@ -215,6 +221,9 @@ export class BaseTranslateService { if (!dictLockExists) { tasks.push(this.genBaseDict()); } + if (!commLockExists) { + tasks.push(this.genCommMsg()); + } // 启动旋转动画 const spinner = ['|', '/', '-', '\\']; let index = 0; @@ -464,6 +473,87 @@ export class BaseTranslateService { this.createLockFile('msg'); } + + /** + * 生成通用消息 + */ + async genCommMsg(){ + const file = path.join(this.basePath, 'comm', 'zh-cn.json'); + const scanPath = path.join(this.app.getBaseDir(), '..', 'src', 'modules'); + const messages = {}; + + // 递归扫描目录 + const scanDir = (dir: string) => { + const files = fs.readdirSync(dir); + for (const file of files) { + const fullPath = path.join(dir, file); + const stat = fs.statSync(fullPath); + + if (stat.isDirectory()) { + scanDir(fullPath); + } else if (file.endsWith('.ts')) { + const content = fs.readFileSync(fullPath, 'utf-8'); + const matches = content.match( + /this.translate.comm\((['"])(.*?)\1\)/g + ); + if (matches) { + matches.forEach(match => { + const message = match.match(/(['"])(.*?)\1/)[2]; + messages[message] = message; + }); + } + } + } + }; + + // 开始扫描 + scanDir(scanPath); + + // 确保目录存在 + const msgDir = path.dirname(file); + if (!fs.existsSync(msgDir)) { + fs.mkdirSync(msgDir, { recursive: true }); + } + + // 写入文件 + const text = JSON.stringify(messages, null, 2); + fs.writeFileSync(file, text); + this.logger.debug('base comm generate success'); + + const translatePromises = []; + for (const language of this.config.languages) { + if (language !== 'zh-cn') { + translatePromises.push( + this.invokeTranslate( + text, + language, + path.join(this.basePath, 'comm'), + 'comm' + ) + ); + } + } + await Promise.all(translatePromises); + this.createLockFile('comm'); + } + + /** + * 通用消息翻译 + * @param text 文本 + * @returns 翻译后的文本对象,包含各语言的翻译 + */ + comm(text: string) { + const translations = {}; + for (const lang of this.config.languages) { + const langFile = path.join(this.basePath, 'comm', `${lang}.json`); + if (fs.existsSync(langFile)) { + const content = JSON.parse(fs.readFileSync(langFile, 'utf-8')); + translations[lang] = content[text] || text; + } + } + return translations; + } + /** * 调用翻译 * @param text 文本 @@ -476,7 +566,7 @@ export class BaseTranslateService { text: string, language: string, dirPath: string, - type: 'menu' | 'msg' | 'dict' = 'msg' + type: 'menu' | 'msg' | 'dict' | 'comm' = 'msg' ) { this.logger.debug(`${type} ${language} translate start`); const response = await axios.post(I18N.DEFAULT_SERVICE_URL, { diff --git a/src/modules/demo/controller/open/i18n.ts b/src/modules/demo/controller/open/i18n.ts new file mode 100644 index 0000000..3dba19d --- /dev/null +++ b/src/modules/demo/controller/open/i18n.ts @@ -0,0 +1,18 @@ +import { CoolController, BaseController } from '@cool-midway/core'; +import { DemoI18nService } from '../../service/i18n'; + +/** + * 国际化 + */ +@CoolController({ + serviceApis: [{ + method: 'en', + summary: '翻译成英文', + }, + { + method: 'tw', + summary: '翻译成繁体', + }], + service: DemoI18nService, +}) +export class DemoI18nController extends BaseController {} diff --git a/src/modules/demo/service/i18n.ts b/src/modules/demo/service/i18n.ts new file mode 100644 index 0000000..933928a --- /dev/null +++ b/src/modules/demo/service/i18n.ts @@ -0,0 +1,29 @@ +import { Inject, Provide } from '@midwayjs/core'; +import { BaseTranslateService } from '../../base/service/translate'; + +/** + * 国际化服务 + */ +@Provide() +export class DemoI18nService { + @Inject() + translate: BaseTranslateService; + + /** + * 翻译成英文 + */ + async en() { + const value = this.translate.comm('一个很Cool的框架')['en']; + console.log(value); + return value + } + + /** + * 翻译成繁体 + */ + async tw() { + const value = this.translate.comm('一个很Cool的框架')['zh-tw']; + console.log(value); + return value + } +}