有没有办法自动创建用于语言翻译的 .json 文件?



我有这样的文件,其中包含转换键和值:

locale-en.json
{
"CHANGE_PASSWORD": "Change Password",
"CONFIRM_PASSWORD":  "Confirm Password",
"NEW_PASSWORD": "New Password"
}
locale-jp.json
{
"CHANGE_PASSWORD": "パスワードを変更します",
"CONFIRM_PASSWORD":  "パスワードを認証します",
"NEW_PASSWORD": "新しいパスワード"
}

例如,当我向包含英语翻译的 JSON 文件添加新的转换密钥时,我必须记住将该密钥和关联的翻译添加到所有其他 JSON 文件中。所有 JSON 文件也会单独编辑。这个过程很费力,而且容易出错。

有没有人找到一种方法来减少错误并自动化该过程。

理想情况下,我希望能够从 Windows PowerShell 运行一个脚本,如果将其他键添加到 locale-en.json 中,该脚本会将文件更改为此脚本:

locale-en.json
{
"CHANGE_PASSWORD": "Change Password",
"CONFIRM_PASSWORD":  "Confirm Password",
"NEW_PASSWORD": "New Password",
"NEW_KEY": "New Key"
}
locale-jp.json
{
"CHANGE_PASSWORD": "パスワードを変更します",
"CONFIRM_PASSWORD":  "パスワードを認証します",
"NEW_PASSWORD": "新しいパスワード",
>>>"NEW_KEY": "New Key"
}

你可以在powershell中写这样的东西:

$masterFile = "locale-en.json"
function Get-LocaleMap($file){
$map = @{}
$localeJson = ConvertFrom-Json (gc $file -Raw)
$localeJson | gm -MemberType NoteProperty | % {
$map.Add($_.Name, ($localeJson | select -ExpandProperty $_.Name))
}
return $map
}
$masterLocale = Get-LocaleMap $masterFile
ls | ? { $_.Name -like "locale-*.json" -and $_.Name -ne $masterFile } | % {
$locale = Get-LocaleMap $_.FullName
$masterLocale.GetEnumerator() | % {
if(!$locale.ContainsKey($_.Key)){
$locale.Add($_.Key, $_.Value)
}
}
ConvertTo-Json $locale | Out-File -FilePath $_.FullName -Force -Encoding utf8
}

它从您的英语 json 文件创建了一个字典。然后,它会查找所有其他语言环境文件,并检查它们中存在但缺少的键。然后,它添加缺少的键和值,并以 Unicode 保存区域设置文件。

让我告诉你如何使用老式的Windows脚本做同样的事情,因为你似乎更喜欢JavaScript:

var masterFile = "locale-en.json"
var fso = new ActiveXObject("Scripting.FileSystemObject");
var scriptPath = fso.GetParentFolderName(WScript.ScriptFullName);
var charSet = 'utf-8';
var f = fso.GetFolder(scriptPath);
var fc = new Enumerator(f.files);
function getLocaleMap(fileName){
var path = scriptPath + '\' + fileName;
var stream = new ActiveXObject("ADODB.Stream"); // you cannot use fso for utf-8
try{
stream.CharSet = charSet;
stream.Open();
stream.LoadFromFile(path);
var text = stream.ReadText();
var json = {};
eval('json = ' + text); // JSON.parse is not available in all versions
return json;
}
finally{
stream.Close();
}
}
function saveAsUtf8(fileName, text){
var path = scriptPath + '\' + fileName;
var stream = new ActiveXObject("ADODB.Stream"); 
try{
stream.CharSet = charSet;
stream.Open();
stream.Position = 0;
stream.WriteText(text);
stream.SaveToFile(path, 2); // overwrite
}
finally{
stream.Close();
}
}
var locales = [];
var masterMap = getLocaleMap(masterFile);
for (; !fc.atEnd(); fc.moveNext())
{
var file = fc.item();
var extension = file.Name.split('.').pop();
if(extension != "json" || file.Name == masterFile){
continue;
}
var map = getLocaleMap(file.Name);
var newLocaleText = '{rn';
var i = 0;
for(var name in masterMap){
var value = '';
if(map[name]){
value = map[name];
}
else{
value = masterMap[name];
}
if(i > 0){
newLocaleText += ",rn";
}
newLocaleText += "t'" + name + "': '" + value + "'";
i++;
}
newLocaleText += 'rn}'
saveAsUtf8(file.Name, newLocaleText);
}

你可以像这样从命令行运行javascript:

Cscript.exe "C:yourscript.js"

我希望它有所帮助。

有没有办法自动创建用于语言翻译的 .json 文件?

是的,执行自动任务正是像Grunt和Gulp这样的自动化工具所要做的事情。

正如你所说,手动做事既费力又容易出错,所以 Grunt/Gulp 是要走的路。

通过简单的Grunt/Gulp配置,可以同时监视所有相关的.json文件:添加到其中任何一个文件的任何密钥都将被立即检测到,并命令执行您选择的自定义脚本。

咕噜

咕噜/咕噜咕噜如何做到:

  1. Grunt/Gulp 会不断监视所有相关的 JSON 文件;
  2. 在监视文件中检测到更改时,将运行自定义脚本;
  3. 自定义脚本将读取更改的文件并检索新的键和值;
  4. 然后,自定义脚本将写入所有其他相关的 JSON 文件。

配置格伦特

要自动检测文件更改并执行myCustomScript,只需像这样使用 grunt-contrib-watch:

watch: {
scripts: {
files: ['**/*.locale.json'],
tasks: ['myCustomScript'],
},
}

自定义脚本,用于将新密钥添加到相关的 .JSON 文件:

grunt.event.on('watch', function(action, filepath) {
// filepath is the path to the file where change is detected
grunt.config.set('filepath', grunt.config.escape(filepath));
});
var myCustomScript=function(changedFile,keyFile){
var project = grunt.file.readJSON(changedFile);
//will store the file where changes were detected as a json object
var keys=grunt.file.readJSON(keyFile);
//will store keyFile as a json object
//walk changedFile keys, and check is keys are in keyFile
for (var key in project) {
if (project.hasOwnProperty(key)) {
if(!keys.hasOwnProperty(key)){
//a new key was detected
newKeyArray.push(key);
}
}
}
//should update all the other relevant JSON files with `grunt.file.write`, and add all the keys in newKeyArray:
var filesToChangeArray=grunt.file.match('**/*.locale.json');
//returns an array that contains all filepaths where change is desired
filesToChangeArray.forEach(function(path){
//walk newKeyArray to set addedContent string
newKeyArray.forEach(function(key){
addedContent+='"'+key+'":"to be set",';
//this will write all the new keys, with a value of "to be set", to the addedContent string
}
grunt.file.write(path,addedContent);
});
}

理想情况下,我希望能够从Windows PowerShell运行脚本。

尽管Grunt/Gulp通常用于执行用javaScript/nodejs编写的自定义文件,但它们能够很好地命令执行用其他语言编写的脚本。

要执行PowerShell脚本,您可以使用名为grunt-shell的Grunt插件,如下所示:

grunt.initConfig({
shell: {
ps: {
options: {
stdout: true
},
command: 'powershell myScript.ps1'
}
}
});

如这篇SO帖子中所述。

因此,如果PowerShell是你的东西,你可以两全其美

  • 使用咕噜声/咕噜声手表轻松检测;
  • 检测到更改时执行 PowerShell 脚本。

但是,您可能可以轻松地仅将Grunt/Gulp用于此目的:由于Grunt/Gulp已经在后台进行检测,您需要做的就是让它运行一个自定义脚本来读取您的新密钥(grunt.file.readJSON)并将它们(grunt.file.write)复制到相关文件中。

通过命令行使用 javascript 解决方案和 nodejs 自动化了该过程。

$ 节点区域设置更新程序.js

这将监视您的默认区域设置 (locale-en.json) 以及所做的任何修订,并根据需要更新整个区域设置文件列表。

  1. 创建必要的区域设置文件列表(如果不存在),然后使用默认区域设置数据对其进行初始化
  2. 根据默认区域设置添加新密钥
  3. 根据默认区域设置删除缺少的键

localeUpdater.js

var fs = require("fs");
var localeFileDefault = "locale-en.json";
var localeFileList = ["locale-jp.json", "locale-ph.json"];
fs.watchFile(localeFileDefault, function() {
var localeDefault = readFile(localeFileDefault);
var localeCurrent = null;
var fileNameCurrent = null;
for (var i in localeFileList) {
fileNameCurrent = localeFileList[i];
console.log("Adding new keys from default locale to file " + fileNameCurrent);
localeCurrent = readFile(fileNameCurrent);
for (var key in localeDefault) {
if (!localeCurrent[key]) {
console.log(key + " key added.");
localeCurrent[key] = localeDefault[key];
}
}
console.log("Removing keys not on default locale to file " + fileNameCurrent);
for (var key in localeCurrent) {
if (!localeDefault[key]) {
console.log(key + " key removed.");
delete localeCurrent[key];
}
}
writeFile(fileNameCurrent, JSON.stringify(localeCurrent));
console.log("File " + fileNameCurrent + " updated.");
}
});
function readFile(fileName) {
var result = null;
if (fs.existsSync(fileName)) {
result = fs.readFileSync(fileName, "utf8");
result = result ? JSON.parse(result) : {};
} else {
writeFile(fileName, "{}");
result = {};
}
return result;
}
function writeFile(fileName, content) {
fs.writeFileSync(fileName, content, "utf8");
}

您应该采取多种保护措施。

首先,您的翻译功能应该有一些保护措施。像这样:

function gettext(text) {
if (manifest[text]) {
return text;
}
return text;
}

我不确定您如何注册新字符串,但是我们将代码库用于gettext('...')之类的内容,然后以这种方式编译翻译列表。我们每天几次将其推送给第三方翻译公司,该公司会注意到新的字符串。它们填充新事物,我们拉回内容。"拉取"涉及对不同语言文件的编译。翻译文件编译始终回退到英语。换句话说,我们从第三方下载文件并执行以下操作:

_.map(strings, function(string) {
return localeManifest[locale][text] || localeManifest['en_US'][text];
}

这可确保即使区域设置的清单不包含翻译,我们仍会使用美国英语版本填充它。

最新更新