Browse Source

add npm command for i18n

master
filesite 6 days ago
parent
commit
c616d471c5
  1. 4
      i18n.mjs
  2. 6
      i18n/README.md
  3. 4
      package.json
  4. 6
      public/en-us/index.html
  5. 3
      public/globe.svg
  6. 6
      public/template/index.html
  7. 6
      public/zh/index.html
  8. 49
      test/i18n.test.mjs

4
i18n.mjs

@ -21,7 +21,7 @@ class I18N {
} }
//从模板文件中解析语言占位变量,并生成语言包文件 //从模板文件中解析语言占位变量,并生成语言包文件
async init(lang) { async init() {
const _self = this; const _self = this;
try { try {
@ -45,7 +45,7 @@ class I18N {
async build(lang) { async build(lang) {
const _self = this; const _self = this;
const langFiles = await _self.getLangFiles(); const langFiles = await _self.getLangFiles(lang);
console.log('Lang json files', langFiles); console.log('Lang json files', langFiles);
if (langFiles && langFiles.length > 0) { if (langFiles && langFiles.length > 0) {

6
i18n/README.md

@ -33,10 +33,10 @@
``` ```
node i18n.mjs init [默认语言代号] npm run i18n_init
``` ```
如果不传参数“默认语言代号”,默认从模板文件的<html lang="{语言代码}">标签中解析,如果解析失败,则默认为英文en; 默认从模板文件的<html lang="{语言代码}">标签中解析,如果解析失败,则默认为英文en;
从template/里的模板文件中解析出语言模版代码,并保存到i18n/{默认语言代码}.json文件中。 从template/里的模板文件中解析出语言模版代码,并保存到i18n/{默认语言代码}.json文件中。
@ -44,7 +44,7 @@ node i18n.mjs init [默认语言代号]
### 使用语言包生成html文件 ### 使用语言包生成html文件
``` ```
node i18n.mjs build [语言代号] npm run i18n_build [语言代号]
``` ```
如果不传参数“语言代号”,则生成i18n/目录下的所有已配置语言对应的html文件。 如果不传参数“语言代号”,则生成i18n/目录下的所有已配置语言对应的html文件。

4
package.json

@ -18,6 +18,8 @@
}, },
"scripts": { "scripts": {
"start": "node index.mjs", "start": "node index.mjs",
"test": "node test/heroUnion.test.mjs" "test": "node test/heroUnion.test.mjs",
"i18n_init": "node test/i18n.test.mjs init",
"i18n_build": "node test/i18n.test.mjs build"
} }
} }

6
public/en-us/index.html

@ -26,6 +26,7 @@
.mt-2{margin-top:2em} .mt-2{margin-top:2em}
.mt-4{margin-top:4em} .mt-4{margin-top:4em}
.mx-d2{margin-left:.5em;margin-right:.2em} .mx-d2{margin-left:.5em;margin-right:.2em}
.icon{vertical-align:middle}
.stats{background-color:#EEE;padding:10px 10px 4px 10px} .stats{background-color:#EEE;padding:10px 10px 4px 10px}
.col{display:inline-block;padding:13px 4px;width:20%;background:#444;color:#FFF;margin-right:4px;margin-bottom:6px;text-align:center} .col{display:inline-block;padding:13px 4px;width:20%;background:#444;color:#FFF;margin-right:4px;margin-bottom:6px;text-align:center}
@ -52,7 +53,10 @@
<hr class="mt-d5"> <hr class="mt-d5">
<div class="text-right mt-d5 langswitcher"> <div class="text-right mt-d5 langswitcher">
<button data-status="closed">English</button> <button data-status="closed">
<img src="/globe.svg" alt="Globe language switcher" class="icon">
English
</button>
<ul class="dropmenu"> <ul class="dropmenu">
<li><a href="/">English</a></li> <li><a href="/">English</a></li>
<li><a href="/zh/">简体中文</a></li> <li><a href="/zh/">简体中文</a></li>

3
public/globe.svg

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-globe" viewBox="0 0 16 16">
<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8m7.5-6.923c-.67.204-1.335.82-1.887 1.855A8 8 0 0 0 5.145 4H7.5zM4.09 4a9.3 9.3 0 0 1 .64-1.539 7 7 0 0 1 .597-.933A7.03 7.03 0 0 0 2.255 4zm-.582 3.5c.03-.877.138-1.718.312-2.5H1.674a7 7 0 0 0-.656 2.5zM4.847 5a12.5 12.5 0 0 0-.338 2.5H7.5V5zM8.5 5v2.5h2.99a12.5 12.5 0 0 0-.337-2.5zM4.51 8.5a12.5 12.5 0 0 0 .337 2.5H7.5V8.5zm3.99 0V11h2.653c.187-.765.306-1.608.338-2.5zM5.145 12q.208.58.468 1.068c.552 1.035 1.218 1.65 1.887 1.855V12zm.182 2.472a7 7 0 0 1-.597-.933A9.3 9.3 0 0 1 4.09 12H2.255a7 7 0 0 0 3.072 2.472M3.82 11a13.7 13.7 0 0 1-.312-2.5h-2.49c.062.89.291 1.733.656 2.5zm6.853 3.472A7 7 0 0 0 13.745 12H11.91a9.3 9.3 0 0 1-.64 1.539 7 7 0 0 1-.597.933M8.5 12v2.923c.67-.204 1.335-.82 1.887-1.855q.26-.487.468-1.068zm3.68-1h2.146c.365-.767.594-1.61.656-2.5h-2.49a13.7 13.7 0 0 1-.312 2.5m2.802-3.5a7 7 0 0 0-.656-2.5H12.18c.174.782.282 1.623.312 2.5zM11.27 2.461c.247.464.462.98.64 1.539h1.835a7 7 0 0 0-3.072-2.472c.218.284.418.598.597.933M10.855 4a8 8 0 0 0-.468-1.068C9.835 1.897 9.17 1.282 8.5 1.077V4z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

6
public/template/index.html

@ -26,6 +26,7 @@
.mt-2{margin-top:2em} .mt-2{margin-top:2em}
.mt-4{margin-top:4em} .mt-4{margin-top:4em}
.mx-d2{margin-left:.5em;margin-right:.2em} .mx-d2{margin-left:.5em;margin-right:.2em}
.icon{vertical-align:middle}
.stats{background-color:#EEE;padding:10px 10px 4px 10px} .stats{background-color:#EEE;padding:10px 10px 4px 10px}
.col{display:inline-block;padding:13px 4px;width:20%;background:#444;color:#FFF;margin-right:4px;margin-bottom:6px;text-align:center} .col{display:inline-block;padding:13px 4px;width:20%;background:#444;color:#FFF;margin-right:4px;margin-bottom:6px;text-align:center}
@ -52,7 +53,10 @@
<hr class="mt-d5"> <hr class="mt-d5">
<div class="text-right mt-d5 langswitcher"> <div class="text-right mt-d5 langswitcher">
<button data-status="closed">{Current Lang}</button> <button data-status="closed">
<img src="/globe.svg" alt="Globe language switcher" class="icon">
{Current Lang}
</button>
<ul class="dropmenu"> <ul class="dropmenu">
<li><a href="/">English</a></li> <li><a href="/">English</a></li>
<li><a href="/zh/">简体中文</a></li> <li><a href="/zh/">简体中文</a></li>

6
public/zh/index.html

@ -26,6 +26,7 @@
.mt-2{margin-top:2em} .mt-2{margin-top:2em}
.mt-4{margin-top:4em} .mt-4{margin-top:4em}
.mx-d2{margin-left:.5em;margin-right:.2em} .mx-d2{margin-left:.5em;margin-right:.2em}
.icon{vertical-align:middle}
.stats{background-color:#EEE;padding:10px 10px 4px 10px} .stats{background-color:#EEE;padding:10px 10px 4px 10px}
.col{display:inline-block;padding:13px 4px;width:20%;background:#444;color:#FFF;margin-right:4px;margin-bottom:6px;text-align:center} .col{display:inline-block;padding:13px 4px;width:20%;background:#444;color:#FFF;margin-right:4px;margin-bottom:6px;text-align:center}
@ -52,7 +53,10 @@
<hr class="mt-d5"> <hr class="mt-d5">
<div class="text-right mt-d5 langswitcher"> <div class="text-right mt-d5 langswitcher">
<button data-status="closed">简体中文</button> <button data-status="closed">
<img src="/globe.svg" alt="Globe language switcher" class="icon">
简体中文
</button>
<ul class="dropmenu"> <ul class="dropmenu">
<li><a href="/">English</a></li> <li><a href="/">English</a></li>
<li><a href="/zh/">简体中文</a></li> <li><a href="/zh/">简体中文</a></li>

49
test/i18n.test.mjs

@ -10,26 +10,23 @@ import common from '../common.mjs';
import I18N from '../i18n.mjs'; import I18N from '../i18n.mjs';
/* let initTest = async function(t) {
//根据模板文件生成默认语言包
test('Init test', async (t) => {
const i18n = new I18N(); const i18n = new I18N();
const res = await i18n.init(); const res = await i18n.init();
assert.ok(res); assert.ok(res);
}); };
*/
//根据语言包生成对应语言的html let buildTest = async function(t) {
test('Build test', async (t) => {
const i18n = new I18N(); const i18n = new I18N();
const res = await i18n.build();
let lang = process.argv[3];
const res = await i18n.build(lang);
assert.ok(res); assert.ok(res);
}); };
/* let getLangKeys = async function(t) {
test('Lang file content get test', async (t) => {
const i18n = new I18N(); const i18n = new I18N();
let langFiles = await i18n.getLangFiles('en-us'); let langFiles = await i18n.getLangFiles('en-us');
const langJson = await readFile(i18n.langDir + langFiles[0], { encoding: 'utf8' }); const langJson = await readFile(i18n.langDir + langFiles[0], { encoding: 'utf8' });
@ -41,5 +38,31 @@ test('Lang file content get test', async (t) => {
} }
assert.ok(langJson); assert.ok(langJson);
}); };
*/
let command = process.argv[2];
if (!command) {
console.error('Test command usage: node test/i18n.test.mjs "command"');
console.error('Test commands: init, build, langKeys');
}else {
switch (command) {
case 'init':
//根据模板文件生成默认语言包
test('Init test', initTest);
break;
case 'build':
//根据语言包生成对应语言的html
test('Build test', buildTest);
break;
case 'langKeys':
test('Lang file content get test', getLangKeys);
break;
default:
console.error('Test command usage: node test/i18n.test.mjs "command"');
console.error('Test commands: init, build, langKeys');
}
}

Loading…
Cancel
Save