javascript - ng2 - ¿Hay alguna manera de automatizar la creación de archivos.json utilizados para la traducción de idiomas?
internationalization angular 4 (4)
¿Hay alguna manera de automatizar la creación de archivos .json utilizados para la traducción de idiomas?
SÍ , la ejecución de tareas automáticas es exactamente para lo que se diseñaron las herramientas de automatización como Grunt y Gulp .
Como dijiste, hacer las cosas manualmente es laborioso y propenso a errores, por lo que Grunt / Gulp es el camino a seguir.
Con una configuración simple de Grunt / Gulp, todos los archivos .json relevantes se pueden ver simultáneamente : cualquier clave agregada a cualquiera de ellos se detectará instantáneamente, y ordena la ejecución del script personalizado de su elección.
CÓMO GRUNT / GULP PUEDE HACERLO:
- Grunt / Gulp vigilará constantemente todos los archivos JSON relevantes;
- Cuando se detecta un cambio en un archivo visto, se ejecuta un script personalizado ;
- El script personalizado leerá el archivo modificado y recuperará la (s) clave (s) y el (los) valor (es) nuevo (s);
- La secuencia de comandos personalizada se escribirá en todos los demás archivos JSON relevantes.
Grado de configuración
Para detectar cambios en los archivos automáticamente y ejecutar myCustomScript
, simplemente use grunt-contrib-watch así:
watch: {
scripts: {
files: [''**/*.locale.json''],
tasks: [''myCustomScript''],
},
}
ESCRIBA PERSONALIZADO PARA AGREGAR LA NUEVA (S) CLAVE (S) A LOS ARCHIVOS .JSON RELEVANTES
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, me gustaría poder ejecutar un script desde Windows PowerShell
Aunque Grunt / Gulp se usa a menudo para ejecutar archivos personalizados escritos en javaScript / nodejs, pueden ordenar la ejecución de scripts escritos en otros idiomas.
Para ejecutar un script de PowerShell, puedes usar un complemento Grunt llamado grunt-shell , como:
grunt.initConfig({
shell: {
ps: {
options: {
stdout: true
},
command: ''powershell myScript.ps1''
}
}
});
como se detalla en esta publicación SO .
Entonces, si PowerShell es lo tuyo, podrías tener lo mejor de ambos mundos :
- Fácil detección con reloj Grunt / Gulp;
- Ejecución del script PowerShell cuando se detecta un cambio.
Sin embargo, puede usar Grunt / Gulp tan fácilmente para esto: como Grunt / Gulp ya se está ocupando de la detección en segundo plano, todo lo que necesita hacer es ejecutar un script personalizado que lea sus nuevas claves (
grunt.file.readJSON
) y los copia (grunt.file.write
) en los archivos relevantes.
Tengo archivos como este que tienen claves y valores de traducción:
locale-en.json
{
"CHANGE_PASSWORD": "Change Password",
"CONFIRM_PASSWORD": "Confirm Password",
"NEW_PASSWORD": "New Password"
}
locale-jp.json
{
"CHANGE_PASSWORD": "パスワードを変更します",
"CONFIRM_PASSWORD": "パスワードを認証します",
"NEW_PASSWORD": "新しいパスワード"
}
Cuando agrego una nueva clave de traducción al archivo JSON que contiene las traducciones al inglés, por ejemplo, debo recordar agregar esa clave y la traducción asociada a todos los demás archivos JSON. Todos los archivos JSON también se editan por separado. El proceso es laborioso y propenso a errores.
¿Alguien ha encontrado una manera de reducir los errores y automatizar el proceso?
Idealmente, me gustaría poder ejecutar un script de Windows PowerShell que cambiaría los archivos a esto si se agregara una clave adicional a 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"
}
Automatizó el proceso utilizando una solución javascript con nodejs a través de la línea de comandos.
$ node localeUpdater.js
Esto observará su configuración regional predeterminada (locale-en.json) con las revisiones realizadas y actualizará toda la lista de archivos de configuración regional según sea necesario.
- cree la lista de archivos de configuración regional necesaria, si no está presente, inicialice con los datos de configuración regional predeterminados
- agregar nuevas claves basadas en la configuración regional predeterminada
- eliminar las claves faltantes según la configuración regional predeterminada
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");
}
Hay múltiples medidas de seguridad que debe poner en su lugar.
En primer lugar, su función de traducción debe tener algunas garantías. Algo como:
function gettext(text) {
if (manifest[text]) {
return text;
}
return text;
}
No estoy seguro de cómo registrar nuevas cadenas, pero regexamos nuestra base de código para cosas como gettext(''...'')
y luego compilamos una lista de traducciones de esa manera. Un par de veces al día enviamos eso a una empresa de traducción de terceros, que nota nuevas cadenas. Ellos pueblan cosas nuevas y nosotros retiramos el contenido. El "pull" implica una compilación a los diferentes archivos de idioma. La compilación del archivo de traducción siempre vuelve al inglés. En otras palabras, descargamos un archivo de la tercera parte y hacemos algo como:
_.map(strings, function(string) {
return localeManifest[locale][text] || localeManifest[''en_US''][text];
}
Esto garantiza que incluso si el manifiesto de la configuración regional no contiene la traducción, aún así lo rellenamos con la versión estadounidense en inglés.
Podrías escribir algo como esto en 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
}
Se creó un diccionario de su archivo json Inglés. Luego busca todos los demás archivos de configuración regional y los busca para las claves que están presentes en el archivo en inglés pero que faltan. Luego agrega las claves y los valores que faltan y guarda los archivos de configuración regional en Unicode.
Déjame mostrarte cómo puedes hacer lo mismo con Windows Scripting de la vieja escuela, ya que parece que prefieres 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);
}
Puede ejecutar el javascript desde la línea de comandos de esta manera:
Cscript.exe "C:/yourscript.js"
Espero que ayude.