Есть ли способ автоматизировать создание.файлы 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 МОЖЕТ ЭТО СДЕЛАТЬ:
- хрюкать / глотать будет постоянно посмотреть все соответствующие файлы JSON;
- когда изменение обнаружено в наблюдаемом файле, a пользовательский скрипт запущен;
- пользовательский скрипт читать в изменен файл и получить новый ключ(Ы) и значение(ы); пользовательский скрипт будет написать для всех других соответствующих файлов 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) с любыми внесенными изменениями и обновите весь список файлов локали по мере необходимости.
- создайте необходимый список файлов локали, если его нет, затем инициализируйте его данными локали по умолчанию
- добавить новые ключи по умолчанию локаль
- удалить отсутствующие ключи на основе локали по умолчанию
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];
}
это гарантирует, что даже если манифест для локали не содержит перевода, мы все еще заполняем его английской версией США.