Есть ли способ, которым я могу автоматизировать создание.файлы 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"
}
590   4  

4 ответов:

В 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. Затем он ищет все остальные файлы локали и проверяет их на наличие ключей, которые присутствуют в английском файле, но отсутствуют в нем. Затем он добавляет недостающие ключи и значения и сохраняет файлы локали в Юникоде.

Позвольте мне показать вам, как вы можете сделать то же самое со скриптами старой школы 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 = '{\r\n';
    var i = 0;

    for(var name in masterMap){
        var value = '';

        if(map[name]){
            value = map[name];
        }
        else{
            value = masterMap[name];
        }

        if(i > 0){
            newLocaleText += ",\r\n";
        }

        newLocaleText += "\t'" + name + "': '" + value + "'";
        i++;
    }

    newLocaleText += '\r\n}'

    saveAsUtf8(file.Name, newLocaleText);
}

Вы можете запустить javascript из командной строки примерно так:

Cscript.exe "C:\yourscript.js"

Я надеюсь, что это помогает.

Есть ли способ, которым я могу автоматизировать создание .файлы json, используемые для языковых переводов?

Да , выполнение автоматических задач-это именно то, что инструменты автоматизации, такие как Grunt и Gulp, предназначены для выполнения.

Как вы сказали, делать все вручную-это трудоемко и подвержено ошибкам, поэтому ворчание/глотание-это путь.

С простой конфигурацией Grunt/Gulp, все соответствующие.файлы json можно просматривать одновременно: любой ключ добавленный к любому из них будет мгновенно обнаружен, и заказывайте выполнение пользовательского скрипта по вашему выбору.


КАК GRUNT / GULP МОЖЕТ ЭТО СДЕЛАТЬ:

  1. Grunt/Gulp будет постоянно смотреть все соответствующие файлы JSON;
  2. при обнаружении изменения в наблюдаемом файле запускается пользовательский скрипт ;
  3. пользовательский скрипт будет читать измененный файл и извлекать новый ключ(Ы) и значение (ы);
  4. пользовательский сценарий будет тогда запишите во все другие соответствующие файлы JSON.

НАСТРОЙКА GRUNT

Чтобы автоматически обнаружить изменения файла и выполнить 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 под названием grunt-shell , например:

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

Как подробно описано в этом посте SO .

Итак, если PowerShell-это ваша вещь, вы можете иметь лучшее из обоих миров :

  • простое обнаружение с помощью часов Grunt/Gulp;
  • выполнение сценария PowerShell при изменении обнаруженный.

Однако вы можете с легкостью использовать Grunt/Gulp только для этого: поскольку Grunt/Gulp уже заботится об обнаружении в фоновом режиме, все, что вам нужно сделать, это запустить пользовательский скрипт, который читает ваши новые ключи (grunt.file.readJSON) и копирует их (grunt.file.write) в соответствующие файлы.

Автоматизировал процесс, используя решение javascript с nodejs через командную строку.

$ node localeUpdater.js

Это будет смотреть вашу локаль по умолчанию (locale-en.json) с любыми внесенными изменениями и обновите весь список файлов локали по мере необходимости.

  1. создайте необходимый список файлов локали, если он отсутствует, а затем инициализируйте его данными локали по умолчанию
  2. добавление новых ключей на основе языка по умолчанию
  3. удалить отсутствующие ключи по умолчанию locale

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];
}

Это гарантирует, что даже если манифест для локали не содержит перевода, мы все равно заполняем его английской американской версией.

Comments

    Ничего не найдено.