diff --git a/i18n-meta/en-US.json b/i18n-meta/en-US.json new file mode 100644 index 0000000..b996d66 --- /dev/null +++ b/i18n-meta/en-US.json @@ -0,0 +1,170 @@ +{ + "8854798582008352047": { + "id": "8854798582008352047", + "text": "输出格式", + "meaning": "", + "description": "", + "messageParts": [ + "输出格式" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Output Format" + }, + "9148710629420152102": { + "id": "9148710629420152102", + "text": "待翻译代码文件夹", + "meaning": "", + "description": "", + "messageParts": [ + "待翻译代码文件夹" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Code folder to be translated" + }, + "8228150899955189359": { + "id": "8228150899955189359", + "text": "元数据输出文件夹", + "meaning": "", + "description": "", + "messageParts": [ + "元数据输出文件夹" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Metadata output folder" + }, + "5764505695883366666": { + "id": "5764505695883366666", + "text": "正则匹配", + "meaning": "", + "description": "", + "messageParts": [ + "正则匹配" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "pattern" + }, + "172425973619832421": { + "id": "172425973619832421", + "text": "元数据名", + "meaning": "", + "description": "", + "messageParts": [ + "元数据名" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "metadata name" + }, + "6644092824683945049": { + "id": "6644092824683945049", + "text": "更新翻译元数据(会更新输出文件夹内的所有文件)", + "meaning": "", + "description": "", + "messageParts": [ + "更新翻译元数据(会更新输出文件夹内的所有文件)" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Update translation metadata (will update all files in the output folder)" + }, + "4602536547892723040": { + "id": "4602536547892723040", + "text": "提取代码中的 $localize 标签模板函数内容;使用 --update 可以直接更新文件夹内的翻译元数据,可以创建一个空翻译文件再执行更新", + "meaning": "", + "description": "", + "messageParts": [ + "提取代码中的 $localize 标签模板函数内容;使用 --update 可以直接更新文件夹内的翻译元数据,可以创建一个空翻译文件再执行更新" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Extract the content of the $localize tag template function from the code; Use --update to directly update the translation metadata in the folder, and create an empty translation file before executing the update" + }, + "1359707629255117030": { + "id": "1359707629255117030", + "text": "元数据文件夹", + "meaning": "", + "description": "", + "messageParts": [ + "元数据文件夹" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Metadata folder" + }, + "7325030709800272957": { + "id": "7325030709800272957", + "text": "输出 key-value 格式;用于直接引用", + "meaning": "", + "description": "", + "messageParts": [ + "输出 key-value 格式;用于直接引用" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Output key-value format; Used for direct reference" + }, + "4550868467630390053": { + "id": "4550868467630390053", + "text": "翻译元数据转换为代码可以引用的 key-value 格式", + "meaning": "", + "description": "", + "messageParts": [ + "翻译元数据转换为代码可以引用的 key-value 格式" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Translate metadata into key-value format that can be referenced by code" + }, + "7019652923141591278": { + "id": "7019652923141591278", + "text": "导出文件夹", + "meaning": "", + "description": "", + "messageParts": [ + "导出文件夹" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Export folder" + }, + "7673149086666070464": { + "id": "7673149086666070464", + "text": "翻译文件夹列表", + "meaning": "", + "description": "", + "messageParts": [ + "翻译文件夹列表" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Translation folder list" + }, + "3463923311488963679": { + "id": "3463923311488963679", + "text": "语言映射;第一个语言为输出名比如: en,en-us;cn,zh-cn 输出 en.json cn.json", + "meaning": "", + "description": "", + "messageParts": [ + "语言映射;第一个语言为输出名比如: en,en-us;cn,zh-cn 输出 en.json cn.json" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Language mapping; The first language is the output name, for example: en,en-us;cn,zh-cn output en.json cn.json" + }, + "4382030543399306865": { + "id": "4382030543399306865", + "text": "用于合并多个包的翻译文件/元数据", + "meaning": "", + "description": "", + "messageParts": [ + "用于合并多个包的翻译文件/元数据" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "Translation files/metadata for merging multiple packages" + } +} \ No newline at end of file diff --git a/i18n-meta/zh-Hans.json b/i18n-meta/zh-Hans.json new file mode 100644 index 0000000..2ad6d5f --- /dev/null +++ b/i18n-meta/zh-Hans.json @@ -0,0 +1,170 @@ +{ + "8854798582008352047": { + "id": "8854798582008352047", + "text": "输出格式", + "meaning": "", + "description": "", + "messageParts": [ + "输出格式" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "输出格式" + }, + "9148710629420152102": { + "id": "9148710629420152102", + "text": "待翻译代码文件夹", + "meaning": "", + "description": "", + "messageParts": [ + "待翻译代码文件夹" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "待翻译代码文件夹" + }, + "8228150899955189359": { + "id": "8228150899955189359", + "text": "元数据输出文件夹", + "meaning": "", + "description": "", + "messageParts": [ + "元数据输出文件夹" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "元数据输出文件夹" + }, + "5764505695883366666": { + "id": "5764505695883366666", + "text": "正则匹配", + "meaning": "", + "description": "", + "messageParts": [ + "正则匹配" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "正则匹配" + }, + "172425973619832421": { + "id": "172425973619832421", + "text": "元数据名", + "meaning": "", + "description": "", + "messageParts": [ + "元数据名" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "元数据名" + }, + "6644092824683945049": { + "id": "6644092824683945049", + "text": "更新翻译元数据(会更新输出文件夹内的所有文件)", + "meaning": "", + "description": "", + "messageParts": [ + "更新翻译元数据(会更新输出文件夹内的所有文件)" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "更新翻译元数据(会更新输出文件夹内的所有文件)" + }, + "4602536547892723040": { + "id": "4602536547892723040", + "text": "提取代码中的 $localize 标签模板函数内容;使用 --update 可以直接更新文件夹内的翻译元数据,可以创建一个空翻译文件再执行更新", + "meaning": "", + "description": "", + "messageParts": [ + "提取代码中的 $localize 标签模板函数内容;使用 --update 可以直接更新文件夹内的翻译元数据,可以创建一个空翻译文件再执行更新" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "提取代码中的 $localize 标签模板函数内容;使用 --update 可以直接更新文件夹内的翻译元数据,可以创建一个空翻译文件再执行更新" + }, + "1359707629255117030": { + "id": "1359707629255117030", + "text": "元数据文件夹", + "meaning": "", + "description": "", + "messageParts": [ + "元数据文件夹" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "元数据文件夹" + }, + "7325030709800272957": { + "id": "7325030709800272957", + "text": "输出 key-value 格式;用于直接引用", + "meaning": "", + "description": "", + "messageParts": [ + "输出 key-value 格式;用于直接引用" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "输出 key-value 格式;用于直接引用" + }, + "4550868467630390053": { + "id": "4550868467630390053", + "text": "翻译元数据转换为代码可以引用的 key-value 格式", + "meaning": "", + "description": "", + "messageParts": [ + "翻译元数据转换为代码可以引用的 key-value 格式" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "翻译元数据转换为代码可以引用的 key-value 格式" + }, + "7019652923141591278": { + "id": "7019652923141591278", + "text": "导出文件夹", + "meaning": "", + "description": "", + "messageParts": [ + "导出文件夹" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "导出文件夹" + }, + "7673149086666070464": { + "id": "7673149086666070464", + "text": "翻译文件夹列表", + "meaning": "", + "description": "", + "messageParts": [ + "翻译文件夹列表" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "翻译文件夹列表" + }, + "3463923311488963679": { + "id": "3463923311488963679", + "text": "语言映射;第一个语言为输出名比如: en,en-us;cn,zh-cn 输出 en.json cn.json", + "meaning": "", + "description": "", + "messageParts": [ + "语言映射;第一个语言为输出名比如: en,en-us;cn,zh-cn 输出 en.json cn.json" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "语言映射;第一个语言为输出名比如: en,en-us;cn,zh-cn 输出 en.json cn.json" + }, + "4382030543399306865": { + "id": "4382030543399306865", + "text": "用于合并多个包的翻译文件/元数据", + "meaning": "", + "description": "", + "messageParts": [ + "用于合并多个包的翻译文件/元数据" + ], + "placeholderNames": [], + "associatedMessageIds": {}, + "target": "用于合并多个包的翻译文件/元数据" + } +} \ No newline at end of file diff --git a/package.json b/package.json index 3bce2af..0ed4d33 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,10 @@ "scripts": { "sync:localize": "code-recycle ./script/sync-localize.ts --cwd ./src ", "test": "rimraf ./test/fixture-output && node --import tsx --inspect ./node_modules/.bin/mocha \"test/**/*.ts\"", - "build": "rimraf ./dist && tsx ./script/build.cli.ts && tsc -p ./tsconfig.build-import.json && tsx ./script/build.import.ts && cpx \"./*.md\" ./dist && cpx ./src/package.json ./dist", - "release-publish": "npm run build && npm --registry=http://192.168.31.88:5555 publish ./dist" + "build": "rimraf ./dist && tsx ./script/build.cli.ts && tsc -p ./tsconfig.build-import.json && tsx ./script/build.import.ts && cpx \"./*.md\" ./dist && cpx ./src/package.json ./dist && npm run i18n:convert", + "release-publish": "npm run build && npm --registry=http://192.168.31.88:5555 publish ./dist", + "i18n:init": "tsx ./src/bin/index.ts ./src ./i18n-meta --update --name zh-Hans", + "i18n:convert": "tsx ./src/bin/index.ts convert ./i18n-meta ./dist/bin/i18n" }, "bin": { "i18n": "./lib/bin/index.js", diff --git a/src/bin/index.ts b/src/bin/index.ts index d0f7324..176cf9b 100644 --- a/src/bin/index.ts +++ b/src/bin/index.ts @@ -4,35 +4,41 @@ import { extract, DefaultOptions } from '../command/extract'; import { convert } from '../command/convert'; import { merge } from '../command/merge'; import { resolve } from 'path'; -let format = new Option('-f,--format [string]', 'output format').choices(['json', 'yaml']).default(DefaultOptions.format); +import { $localize } from '../index'; +import { loadI18n } from '../load.node'; +loadI18n() +let format = new Option('-f, --format [string]', $localize`输出格式`).choices(['json', 'yaml']).default(DefaultOptions.format); program - .argument('', 'input dir') - .argument('[output]', 'output dir', process.cwd()) + .argument('', $localize`待翻译代码文件夹`) + .argument('[output]', $localize`元数据输出文件夹`, process.cwd()) .enablePositionalOptions() - .option('-p,--pattern [string]', 'pattern', DefaultOptions.pattern) - .option('-n,--name [string]', 'name', DefaultOptions.name) - .option('--update [string]', 'update language', DefaultOptions.update) + .option('-p, --pattern [string]', $localize`正则匹配`, DefaultOptions.pattern) + .option('-n, --name [string]', $localize`元数据名`, DefaultOptions.name) + .option('--update [string]', $localize`更新翻译元数据(会更新输出文件夹内的所有文件)`, DefaultOptions.update) .addOption(format) .action(async (input, output, options) => { await extract(resolve(process.cwd(), input), resolve(process.cwd(), output), process.cwd(), options); - }); + }) + .description($localize`提取代码中的 $localize 标签模板函数内容;使用 --update 可以直接更新文件夹内的翻译元数据,可以创建一个空翻译文件再执行更新`); program .command('convert') - .argument('', 'input dir') - .argument('[output]', 'output dir') + .argument('', $localize`元数据文件夹`) + .argument('[output]', $localize`输出 key-value 格式;用于直接引用`) .addOption(format) .action(async (dir: string, output: string, { format }) => { await convert(dir, format, output); - }); + }) + .description($localize`翻译元数据转换为代码可以引用的 key-value 格式`); program .command('merge') - .argument('', 'output path') - .argument('', 'filePath list') + .argument('', $localize`导出文件夹`) + .argument('', $localize`翻译文件夹列表`) .addOption(format) - .option('-m,--map [string]', 'language map;output first language as name.eg: en,en-us;cn,zh-cn output en.json cn.json') + .option('-m, --map [string]', $localize`语言映射;第一个语言为输出名比如: en,en-us;cn,zh-cn 输出 en.json cn.json`) .action(async (output: string, dir: string[], { format, map }) => { await merge(dir, format, output, map); - }); + }) + .description($localize`用于合并多个包的翻译文件/元数据`); program.parse(process.argv); diff --git a/src/command/extract.ts b/src/command/extract.ts index 5a064da..0a88d1c 100644 --- a/src/command/extract.ts +++ b/src/command/extract.ts @@ -26,7 +26,7 @@ export async function extract( options: { name: string; pattern: string; dryRun?: boolean; format: FileFormat; update: boolean } ) { let result = await codeRecycleByNode(path, root, { config: { dryRun: options.dryRun } }); - const createFileName = `${options.name}.json`; + const createFileName = `${options.name}.${options.format}`; let obj = {} as Record; return result(async (util, rule, host, injector) => { @@ -99,7 +99,7 @@ export async function extract( }, { type: 'create', - path: join(output, `${options.name}.${options.format}`), + path: join(output, createFileName), content: async (context) => { context = context.getContext('root.match'); for (const childContext of context.children) { @@ -116,7 +116,7 @@ export async function extract( delete (result as any).substitutions; delete result.location; delete result.legacyIds; - (result as any).target = ''; + (result as any).target = options.update ? result.text : ''; obj[result.id] = result; } } @@ -131,13 +131,14 @@ export async function extract( for (const item of fileList) { if (['.yaml', '.yml', '.json'].some((ext) => item.endsWith(ext))) { let filePath = path.join(outputDir, item); - let data = await parseFile(filePath); + let data = await parseFile(filePath).catch(() => ({} as Record)); let newData = {} as Record; for (const key in obj) { if (key in data) { newData[key] = data[key]; } else { newData[key] = obj[key]; + newData[key].target = ''; } } await completePromise(host.write(filePath, stringToFileBuffer(formatContent(newData, fileFormat(item))))); diff --git a/src/load.node.ts b/src/load.node.ts new file mode 100644 index 0000000..76b4a47 --- /dev/null +++ b/src/load.node.ts @@ -0,0 +1,34 @@ +import path from 'path'; +import fs from 'fs'; +import { loadTranslations } from './index'; +export const LanguageMap: Record = { + zh_cn: 'zh-Hans', + cn: 'zh-Hans', + en: 'en-US', + en_us: 'en-US', +}; + +export function loadI18n() { + let lang = process.env['CR_LANG']?.toLowerCase(); + if (!lang) { + if (process.env['LANGUAGE']) { + lang = process.env['LANGUAGE'].split(':')[0].toLowerCase(); + } else if (process.env['LANG']) { + lang = process.env['LANG'].split('.')[0].toLowerCase(); + } + } + let cache; + try { + const filePath = path.join(__dirname, `./i18n/${LanguageMap[lang!] || lang || 'zh-Hans'}.json`); + + if (!fs.existsSync(filePath)) { + cache = require('./i18n/zh-Hans.json'); + } else { + cache = require(filePath); + } + loadTranslations(cache); + } catch (error) { + console.warn(error); + loadTranslations({}); + } +} diff --git a/src/package.json b/src/package.json index caf42c4..d2e442f 100644 --- a/src/package.json +++ b/src/package.json @@ -1,6 +1,6 @@ { "name": "@cyia/localize", - "version": "1.2.0", + "version": "1.2.1", "description": "Angular 本地化独立版本;Angular localize standalone version", "bin": { "i18n": "./bin/index.js",