/** * 多国语言管理 * * node i18n.mjs init [默认语言代号] * node i18n.mjs build [语言代号] */ import fs from 'node:fs'; import { readdir, readFile, writeFile } from 'node:fs/promises'; import path from 'node:path'; import common from './common.mjs'; class I18N { //构造函数,设置默认配置 constructor(defaultLang, templateDir, langDir) { this.defaultLang = typeof(defaultLang) != 'undefined' && defaultLang ? defaultLang : 'en'; this.templateDir = typeof(templateDir) != 'undefined' && templateDir ? templateDir : './public/template/'; this.langDir = typeof(langDir) != 'undefined' && langDir ? langDir : './i18n/'; } //从模板文件中解析语言占位变量,并生成语言包文件 async init(lang) { const _self = this; try { const files = await readdir(_self.templateDir); let parseLangRes = null; for (const file of files) { parseLangRes = await _self.parseLangFromTemplate(_self.templateDir + file); if (parseLangRes) { console.log('Template file [%s] parse lang config done', file); } } } catch (err) { console.error('Read dir in function init failed', err); return false; } return true; } //根据语言包文件以及模板文件,生成对应语言的html文件 build(lang) { const _self = this; } //判断语言代码格式是否符合国际标准 isIosLangCode(lang) { return /^[a-z]{2}(?:\-[a-z]{2})$/i.test(lang); } //更新语言包文件内容,合并新的数据到已有内容中 async updateLangFile(langFile, langJson) { const _self = this; let updated = false; try { let json = await readFile(langFile, { encoding: 'utf8'}); if (json) { let data = JSON.parse(json); for (const key in langJson) { data[key] = langJson[key]; } updated = await writeFile(langFile, JSON.stringify(data, null, 4)); }else { updated = await writeFile(langFile, JSON.stringify(langJson, null, 4)); } } catch (err) { console.error('updateLangFile failed', err); } return updated; } //解析单个模板文件,并生成语言包文件 async parseLangFromTemplate(templateFilepath) { const _self = this; let langJson = {}, total = 0; try { const html_template = await readFile(templateFilepath, { encoding: 'utf8' }); const regHtmlLang = /[\s\S]*[\s\S]*/i; let htmlLang = html_template.replace(regHtmlLang, "$1"); if (htmlLang == html_template || _self.isIosLangCode(htmlLang) == false) { htmlLang = _self.defaultLang; }else { htmlLang = htmlLang.toLowerCase(); } const regLang = /\{([^\}\r\n:;]+)\}/ig; const matches = html_template.matchAll(regLang); for (const match of matches) { langJson[match[1]] = match[1]; total ++; } //更新语言包文件 if (total > 0) { let langFile = _self.langDir + `${htmlLang}.json`; const saved = await _self.updateLangFile(langFile, langJson); if (!saved) { return false; } } } catch (err) { console.error('parseLangFromTemplate failed', err); return false; } return langJson; } } export default I18N;