Knowing that: the " original " object has properties and that these properties have other properties themselves, and all final values are of type string
and without addressing validation issues (outside the scope of question) a viable method would be as follows.
-
iterate every object and its properties to call up all values ( string
)
-
Create a percentage index from the total values of the " original "
-
Iterate the total values of the " original " and clone objects to verify equality and based on this (or lack thereof) used to mount the percentage of total completed and remaining (to be completed)
The following approach fulfills the issue.
Example:
// objeto original
var i18n1 = {
// índice único
title: "Titulo qualquer",
// índice com sub-índices
words: {
logout: "Encerrar sessão",
open: "abrir",
close: "fechar"
},
// índice com sub-índices e itens
combo: {
btn_top: "De volta ao topo",
err_conn: {
dberr: "Erro ao conectar a base de dados",
reqerr: "Erro ao requisitar recurso"
}
}
}
// objeto original
var i18n2 = {
// índice único
title: "Titulo qualquer modificado",
// índice com sub-índices
words: {
logout: "Encerrar sessão",
open: "abrir janela",
close: "fechar"
},
// índice com sub-índices e itens
combo: {
btn_top: "De volta ao topo",
err_conn: {
dberr: "Erro ao conectar a base de dados",
reqerr: "Reco reco"
}
}
}
// função para percorrer o object
var get_values = function(obj){
var strings = [];
// initialize loops
for (k in obj) {
// values from first level
if ( typeof obj[k] === 'string' ) {
strings.push(obj[k])
}
// first level keys search
if ( typeof obj[k] === 'object' ) {
for (k1 in obj[k] ) {
// values from second level
if ( typeof obj[k][k1] === 'string' ) {
strings.push(obj[k][k1])
}
// second level keys search
if ( typeof obj[k][k1] === 'object' ) {
for (k2 in obj[k][k1]) {
// values from third level
if ( typeof obj[k][k1][k2] === 'string' ) {
strings.push(obj[k][k1][k2])
}
// third level keys search
if ( typeof obj[k][k1][k2] === 'object' ) {
for (k3 in obj[k][k1][k2]) {
// values from fourt level
if ( typeof obj[k][k1][k2][k3] === 'string' ) {
strings.push(obj[k][k1][k2][k3])
}
/*
if ( typeof obj[k][k1][k2][k3] === 'object' ) {
console.info(obj[k][k1][k2][k3])
}
*/
}
}
}
}
}
}
}
return strings;
};
// função para comparar
var compare = function(obj1, obj2){
var indx1 = get_values(obj1),
indx2 = get_values(obj2),
len = indx1.length;
var percentage = (100/indx1.length),
yes = 0, // traduzidas
not = 0; // faltando
// loop
for (;len--;) {
if ( indx1[len] !== indx2[len] ) {
yes++
} else {
not++
}
}
var done = ( (percentage * yes) === 100.00 || (percentage * yes) === 0.00) ? (percentage * yes).toFixed(0) : (percentage * yes).toFixed(2);
var need = ( (percentage * not) === 100.00 || (percentage * not) === 0.00) ? (percentage * not).toFixed(0) : (percentage * not).toFixed(2);
return {
done: done +'%',
need: need +'%'
}
};
// buscar resultado
var res = compare(i18n1, i18n2);
// printar
console.log('tradução concluída: ' + res.done);
// output: tradução concluída: 42.86%
console.log('faltando traduzir: ' + res.need);
// output: faltando traduzir: 57.14%
However I'm not sure if the amount of loops using for
is the best way or if there is a less "costly" method so I leave the question open for corrections, suggestions or a response more qualified person to come.
Thanks for any help.