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

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. Затем он ищет все другие файлы локали и проверяет их на наличие ключей, которые присутствуют в английском файле, но отсутствуют в них. Затем он добавляет недостающие ключи и значения и сохраняет файлы в кодировке 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 = '{\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, все соответствующие .формат JSON файлы можно смотреть одновременно: любой ключ, добавленный к любому из них, будет мгновенно обнаружен и закажите выполнение пользовательского скрипта по вашему выбору.


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

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

НАСТРОЙКА GRUNT

для автоматического обнаружения изменений файлов и выполнения myCustomScript, просто использовать grunt-contrib-смотреть вот так:

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.initConfig({
shell: {
    ps: {
        options: {
            stdout: true
        },
        command: 'powershell myScript.ps1'
    }
}
});

as вся в должности.

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

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

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


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

$ node localeUpdater.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;
}

Я не уверен, как вы регистрируете новые строки, но мы regex нашу базу кода для таких вещей, как gettext('...') и затем мы составляем список переводов таким образом. Пару раз в день мы толкаем это в стороннюю переводческую компанию, которая замечает новые строки. Они заполняют новые вещи, а мы возвращаем контент. Тяга" включает компиляцию файлов на разных языках. Компиляция файла перевода всегда возвращается на английский язык. Другими словами, мы загружаем файл с 3-й стороны и делаем что-то вроде:

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

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