Project Server / Online: interfaz de usuario multiidioma mediante Javascript

En mi última colaboración con la revista CompartiMOSS abordé el tema del multiidioma en Project Server / Online. Resumiendo brevemente: las tablas relacionadas con Project no toleran por el momento varios idiomas como sí lo hace Sharepoint.Esto obliga a multiplicar todas las estructuras de Project (campos, vistas, tipos de proyectos, páginas…) por tantos idiomas como se necesiten. Si sólo estamos hablando de dos idiomas quizás podría ser abarcable pero si se trata de tres o cuatro idiomas, tanto la puesta en producción como el mantenimiento del sistema es un auténtico suplicio.

Mientras escribía el artículo se me ocurrió un workaround (“ñapa” en español de España) que podría ayudarnos a plantear esta solución de una manera mucho más sencilla y mantenible: usar una (o varias) listas de Sharepoint para mantener las traducciones de los textos de la interfaz de usuario y javascript para sobreescribir la misma. Y, aunque me pareció algo disparatado, la complejidad actual para mantener un sistema multidioma me llevó a realizar al menos una prueba de concepto y ver qué tal se comportaba el sistema.

Estructuras a traducir de la interfaz de usuario

Lo primero es ver cómo se puede sobreescribir la interfaz de usuario, ver cómo identificar las estructuras que se desean modificar mediante javascript. Y existen tres estructuras principales: las páginas de proyectos (PDP’s), la navegación y los desplegables con los nombres de las vistas que se vayan creando en nuestro PWA.

Páginas de Proyecto (PDP’s)

Para ver qué estructuras se generan nada mejor que el explorador DOM del navegador. Simplemente hay que posicionarse en la etiqueta correspondiente a los campos personalizados de empresa que se muestran en las páginas de proyecto y vemos que todos están dentro de un tag <h3> con la clase “ms-accentText”. Con esto ya tenemos suficiente para poder acceder a este elemento con jquery y sobreescribir su contenido.En la imagen puede apreciarse que se utilizó Internet Explorer 11 para obtener esta información, pero el resultado es el mismo con Firefox y con Chrome (vamos bien, en caso contrario nos tendríamos que hacer versiones diferentes del código según el navegador).

Multiidioma_PDP_HTML

Navegación

Podemos utilizar la misma técnica para detectar las estructuras correspondientes a la navegación lateral si utilizamos la proporcionada por Project Server. Si se utiliza la de Sharepoint, es probable que con las capacidades del mismo sea suficiente para traducir la interfaz, aunque podemos encontrar dificultades a la hora de securizar los enlaces a partir de la seguridad basada en Project. Se debe valorar para cada caso que conviene más.

No obstante, manteniendo la misma técnica utilizada para las PDP’s vemos que los elementos están contenidos dentro de etiquetas <span> con la clase “menu-item-text”:

Multiidioma_Navigation_HTML

Desplegables con las vistas

Otros elementos cuyo texto no se traduce en Project son las vistas: si queremos que el nombre de una misma vista se muestre en varios idiomas debemos replicar las vistas para cada una de las instancias de PWA correspondientes a cada uno de ellos.

Continuando con la solución planteada vemos que los desplegable generan estructuras dentro de etiquetas <span> con la clase “ms-cui-ctl-mediumlabel”:

Multiidioma_DropdownVistas_HTML

Lista con las traducciones

Para poder traducir los diferentes textos nada mejor que una o varias listas de Sharepoint. Si hay poco texto a traducir con una puede ser suficiente. Sin embargo,en caso de estructuras muy complejas, quizás es conveniente utilizar una lista de Sharepoint para cada uno de los grupos estructurales comentados anteriormente. De esta forma, se aligerarían las consultas para obtener las traducciones y se reduciría el tiempo de carga de la página.

En nuestro ejemplo, la estructura es muy sencilla, ya que estamos dando por hecho que se traduce todo al español. En caso de varios idiomas sería necesaria una columna adicional para informar el idioma al que traducir en cada caso (es-ES, en-US, etc…). Para la prueba de concepto simplemente tenemos dos columnas:

  • Source: se debe indicar el nombre del campo en el idioma original (inglés normalmente)
  • Translation: se usará para indicar la traducción correspondiente.

Multiidioma_ListaTraducciones

Traducir una PDP

No se va a realizar la traducción de todas las estructuras comentadas ya que la mecánica es la misma para todas, así que vamos a ver como sobreescribir los textos de una página, que tal vez sea el elemento más llamativo.

Lo primero es añadir un webpart de tipo “Script Editor” en cada una de las páginas a traducir. O en la master, aunque esta opción no es recomendable para Project Online:

Multiidioma_PDP_Webpart

A continuación, hay que añadir el código javascript necesario para leer de la lista “Translations” los elementos necesarios y sobreescribir el contenido de las etiquetas html correspondientes.

Lo primero es añadir un enlace a la librería jquery que se vaya a utilizar. En el ejempo está alojada en el cdn de asp de Microsoft aunque lo correcto sería tenerla alojada en una librería de Sharepoint:

Multiidioma_PDP_Script1

A continuación se genera una función que se llama cuando la página esté cargada y que, sencillamente, carga en una variable la url de la instancia de pwa (podría inferirse mediante javascript en realidad) y, en otra variable, el nombre de la lista con las traducciones. También se obtiene el idioma actual de ejecución para poder filtrar la lista con este en una segunda versión del código. Por el momento, se da por sentado que se traduce al español. Finalmente se llama a la función getListItem pasándole las variables ya inicializadas como parámetros:

(function() {
var url = https://MyPWAInstanceURL;
var listName = “Tranlations”;
var lang = navigator.languages ?
navigator.languages[0] : (navigator.language || navigator.userLanguage);
console.log(“lang” + lang);
getListItem(url, listName);
})();

Esta función realiza una llamada asíncrona mediante el api REST a la lista “Translations”
para obtener sus elementos y los almacena en la variable global myData en caso
de éxito. En caso de error simplemente se muestra por consola, aunque en un proyecto
real habría que llamar a una función que tratara esto. Por último, se utiliza una
promesa para llamar a la función OverWriteTranslations, que será la que sobreescriba
la interfaz de usuario:

function getListItem(url, listname) {
// Getting our list items
$.ajax({
url: url + “/_api/web/lists/getbytitle(‘” + listname + “‘)/items”,
method: “GET”,
headers: { “Accept”: “application/json; odata=verbose” },
success: function (data) {
// Returning the results
myData = data.d.results;
},
error: function (data) {
console.log(“ko”);
}
}).then(function(){ // use a promise library to make sure we synchronize off the jsonp
OverWriteTranslations(myData);
});
}

Finalmente, la función OverWriteTranslations obtiene las etiquetas HTML que utilizan la clase “ms-accentText” (y que identifica los campos a traducir como se vió anteriormente) y las va recorriendo, sustituyendo su contenido por la correspondiente traducción:

function OverWriteTranslations(results)
{
var labels = document.getElementsByClassName(“ms-accentText”);
for(var i=0;i<labels.length;i++)
{
var label = labels[i];
for(j=0;j<results.length;j++)
{
label.innerHTML = label.innerHTML.replace(results[j].Title, results[j].Translation);
}
}
}

El resultado final es el siguiente:

Multiidioma_PDP_Traducida

Conclusiones

Como se ha comentado al inicio de esta entrada, la solución que se plantea es un workaround, algo que puede valorarse si existe una necesidad de negocio imperiosa de utilizar varios idiomas en Project Server / Online. El código es claramente mejorable como ya se ha ido apuntando a medida que se comentaba. Incluso, en ocasiones, se carga primero el contenido en el idioma original y rápidamente se sobreescribe, lo que es percibido por el usuario y produce un efecto un tanto extraño: sería recomendable cachear los resultados obtenidos para evitar todo esto. Sin embargo, sirve como ejemplo de que es posible realizar lo que se plantea con un resultado aceptable.

No obstante,se corren varios riesgos a la hora de su mantenimiento, especialmente si estamos trabajando con Project Online, como el cambio de renderizado por parte de Microsoft, tanto a nivel de las clases utilizadas para identificar las estructuras como que no se comporte igual en todos los navegadores.

Probablemente sería mucho peor mantener multitud de idiomas en Project Online, pero al menos se tendría el control de los cambios a realizar (una nueva vista, un nuevo campo…) en las diferentes instancias de PWA.

 

Anuncios