Utilidad FrontEnd para la personalización de textos por idioma y estilos CSS.
La lógica se basa en el patrón Observer (implementación signals) para automatizar los cambios de idioma y estilos en tiempo de ejecución. El proyecto está construido mediante Webpack he incorpora los scripts necesarios para su desarrollo:
npm run build
- Genera una versión minificada para producción.npm run dev
- Genera una versión no minificada para desarrollo y lanza un watcher para recompilar a cada modificación de archivos.npm run demo
- Lanza un servidor para ver una demostración de la utilidad, accediendo a http://localhost:8080/demo.npm run test
- Ejecuta los test del proyecto.npm run test:watch
- Ejecuta los test del proyecto y lanza un watcher para recompilar a cada modificación de archivos.
Para usar esta utilidad, la aplicación debe cumplir con unas convenciones.
-
Los textos a actualizar en el cambio de idioma deberán estar contenidos dentro de elementos HTML con el atributo
data-translate
. Este atributo tendrá como valor la clave que se corresponde con el texto que se mostrará a partir de un JSON:<span data-translate="saludo"></span>
-
La estructura del JSON de textos tendrá dos niveles: idioma y textos:
var strings = { 'es': {'saludo': 'Hola'}, 'en': {'saludo': 'Hello'} };
-
En enlace de la hoja de estilos debe tener el id
skin
:<link id="skin" rel="stylesheet" href="css/male.min.css">
-
Las hojas de estilo deberán estar en el mismo directorio y tener el mismo sufijo, ya sea
.css
o.min.css
Una vez añadida la librería a una aplicación, debe inicializarse mediante dos parámetros:
Customizer.init(stringsProvider, config)
-
stringsProvider: Objeto javascript que debe implementar el método
getString(key)
. De lo contrario se lanzará un TypeError. Una implementación básica usaría un JSON estático como datasource:var strings = { 'es': {'saludo': 'Hola'}, 'en': {'saludo': 'Hello'} }; var stringsProvider = (function () { return { getString: function (lang, key) { return strings[lang][key]; } }; })();
En un caso más avanzado se podría usar un servicio de textos cacheando las respuestas:
const stringsProvider = (function () { const textService = 'http://server/rest/texts-service/'; const strings = {}; const promises = {}; return { getString: function (lang, key) { // Si ya está cacheado el idioma devolvemos el string. if (strings[lang]) { return strings[lang][key]; } // Si no hay una petición asíncrona iniciada la creamos, // cacheando el idioma solicitado. if(!promises[lang]) { promises[lang] = fetch(textService + lang) .then((resp) => resp.json()) .then((json) => strings[lang] = json.response.data); } // Devolvemos la promesa, resuelta o en curso, // retornando el string solicitado una vez esté resulta. return promises[lang] // Finalmente devolvemos el string. .then(() => strings[lang][key]); } }; })();
En este ejemplo se emplea la API Fetch, pero aplicaría el mísmo uso a cualquier petición asíncrona que devuelva una Promise, también
JQuery.ajax
. -
config: Objeto JSON de configuración con los elementos que se deseen sincronizar y sus valores iniciales:
var config = { 'language': 'es_ES', 'skin': 'main' };
El valor por defecto de
language
es es_ES, y el deskin
styles.En cualquier caso, para sincronizar los cambios de estos atributos, se deberán incluir en el objeto de configuración inicial.
La utilidad Customizer expone una serie de métodos para facilitar la customización de textos y estilos en tiempo real, ocultando la lógica implicada y simplificando el desarrollo.
init(stringsProvider, config)
- Inicializa la sincronicación de textos y estilos de la aplicación con cambios en la configuración de lenguaje y los estilos respectivamente.changeLanguage(lang)
- Cambia el lenguaje de la aplicación en la configuración y actualiza automáticamente los textos vinculados. El valor del parámetrolang
debe ser uno de los identificadores de idioma definidos en elstringsProvider
.changeSkin(skin)
- Cambia los estilos de la aplicación actualizando el enlace del archivo CSS con el nuevo valor. El parámetroskin
debe corresponderse con el nombre de la hoja de estilos sin ruta ni sufijo. Por ejemplo, si el estilo inicial está en http://server/css/style.min.css, un cambio a unskin
llamado style-new debería tener la ruta http://server/css/style-new.min.css.
En la propia utilidad se incluye una demo responsive mostrando el funcionamiento de la utilidad, sincronizando un texto con el cambio de idioma y facilitando el cambio del aspecto visual general.
> git clone <este repositorio>
> cd <directorio clonado>
> npm install
> npm run demo
- Abrir en un navegador la URL
http://localhost:8080/demo
(El puerto puede variar de manera incremental si 8080 ya está en uso).
Quedan pendientes varias mejoras de esta herramienta:
- Binding automático de nuevos elementos creados programáticamente y gestión también de elementos eliminados. La solución de momento es llamar de nuevo a
Customizer.init()
después de haber modificado el DOM, pero debería ser una solución transitoria. - Encapsular al funcionamiento asíncrono ocultando la complejidad y facilitando su uso con servicios REST de textos.