2015-05-08 11 views
18

Ho i file di questo tipo che hanno chiavi e valori traduzione:Esiste un modo per automatizzare la creazione di file .json utilizzati per le traduzioni della lingua?

locale-en.json 
{ 
    "CHANGE_PASSWORD": "Change Password", 
    "CONFIRM_PASSWORD": "Confirm Password", 
    "NEW_PASSWORD": "New Password" 
} 

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

Quando aggiungere una nuova chiave di traduzione al file JSON contenente le traduzioni per esempio in inglese, devo ricordare di aggiungere la chiave e il relativo traduzione in tutti gli altri file JSON. Tutti i file JSON sono anche modificati separatamente. Il processo è laborioso e soggetto a errori.

Qualcuno ha trovato un modo per ridurre gli errori e automatizzare il processo.

Idealmente mi piacerebbe essere in grado di eseguire uno script da Windows PowerShell che avrebbe cambiato i file in questo caso di un tasto aggiuntivo è stato aggiunto al 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" 
} 
+1

È possibile semplicemente creare un'attività di gulp, passare la chiave di traduzione e specificare in quali file si desidera aggiungere. –

+0

Inoltre, forse ci sono alcuni servizi online per i traduttori che consentono all'utente di tradurre le cose ed esportarle in diversi formati. – DWand

+0

Quale IDE stai usando? –

risposta

11

Si potrebbe scrivere qualcosa di simile in 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 
} 

ha creato un dizionario dal file JSON inglese. Quindi cerca tutti gli altri file locali e li controlla per le chiavi che sono presenti nel file inglese ma che mancano da esse. Quindi aggiunge le chiavi e i valori mancanti e salva i file delle impostazioni internazionali in Unicode.

Mi permetta di mostrare come si può fare lo stesso con la vecchia scuola di Windows Scripting dal momento che sembra preferire 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); 
} 

è possibile eseguire i javascript da linea di comando come questo:

Cscript.exe "C:\yourscript.js" 

Spero che aiuti.

7

C'è un come posso automatizzare la creazione di file .json usati per le traduzioni della lingua?

SI, l'esecuzione di attività automatiche è esattamente ciò che strumenti di automazione come Grunt e Gulp dove progettato per fare.

Come hai detto, fare le cose manualmente è laborioso e soggetto a errori, quindi Grunt/Gulp è la strada da percorrere.

Con un semplice Grunt/Gulp config, tutti i file .json rilevanti possono essere guardato contemporaneamente: un tasto qualsiasi aggiunto a qualsiasi di essi sarà rilevato istantaneamente, e ordinare l'esecuzione dello script personalizzato di vostra scelta.


COME GRUNT/GULP può farlo:

  1. Grunt/Gulp sarà costantemente orologio tutti i file JSON pertinenti;
  2. Quando viene rilevata una modifica in un file guardato, viene eseguito uno script personalizzato ;
  3. Lo script personalizzato sarà letto il file modificato e recupererà la nuova chiave (s) e valore (s);
  4. Lo script personalizzato sarà quindi scrivere in tutti gli altri file JSON pertinenti.

CONFIGURAZIONE GRUNT

Per rilevare automaticamente le modifiche di file ed eseguire myCustomScript, basta usare grunt-contrib-watch in questo modo:

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

CUSTOM script per aggiungere la nuova chiave (S) PER IL RILEVANTE.JSON FILES:

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

Idealmente mi piacerebbe essere in grado di eseguire uno script da Windows PowerShell

Anche se Grunt/Gulp vengono spesso utilizzati per eseguire i file personalizzati scritti in JavaScript/nodejs, sono in grado di ordinare l'esecuzione di script scritti in altre lingue.

per eseguire uno script PowerShell, è possibile utilizzare un plugin chiamato Grunt grunt-shell, in questo modo:

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

come detailed in this SO post.

Quindi, se PowerShell è la vostra passione, si potrebbe avere il meglio dei due mondi:

  • rilevamento facile con Grunt/Gulp guardare;
  • Esecuzione di script PowerShell quando viene rilevata una modifica.

Tuttavia, si potrebbe facilmente utilizzare Grunt/Gulp solo per questo: come Grunt/Gulp sta già prendendo cura della rilevazione in background, tutto quello che dovete fare è avere correre uno script personalizzato che legge le nuove chiavi (grunt.file.readJSON) e le copia (grunt.file.write) nei file pertinenti.

4

Automatizzato il processo utilizzando una soluzione javascript con nodejs tramite riga di comando.

localeUpdater.js $ nodo

Questa guarderanno proprio locale predefinito (locale-en.json) con revisioni effettuate e aggiornare l'elenco di file locale intero, se necessario.

  1. creare l'elenco di file locale necessario se non è presente quindi inizializzato con dati locali di default
  2. aggiungere nuove chiavi basate su impostazioni internazionali predefinite
  3. rimuovere le chiavi mancanti sulla base di impostazioni internazionali predefinite

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"); 
 
}

0

Ci sono più salvaguardie che dovresti mettere in atto.

Prima di tutto la funzione di traduzione dovrebbe avere alcune protezioni. Qualcosa di simile:

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

    return text; 
} 

io non sono sicuro di come si registra nuove stringhe, ma abbiamo Regex la nostra base di codice per cose come gettext('...') e poi compilare una lista di traduzioni in quel modo. Un paio di volte al giorno lo spingiamo a una società di traduzione di terze parti, che nota nuove stringhe. Popolano nuove cose e recuperiamo i contenuti. Il "pull" comporta una compilazione nei diversi file di lingua. La compilazione del file di traduzione ricade sempre in inglese. In altre parole si scarica un file dalla 3a parte e fare qualcosa di simile:

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

questo modo si garantisce che, anche se il manifesto per l'impostazione internazionale non contiene la traduzione eppure siamo ancora popolarlo con la versione inglese degli Stati Uniti.

Problemi correlati