template loop for es6 concatenate javascript localization ecmascript-6 gettext template-strings

loop - template string javascript html



¿Puedes "simplificar" las cadenas de plantillas de ES6 a las cadenas normales? (2)

Gran pregunta Hay cuatro soluciones que vienen a la mente:

1. Fuerza bruta

Un reemplazo de fuerza bruta de palos con comillas antes de escanear cadenas traducibles, como sugirió, no es una idea horrible, siempre y cuando comprenda los riesgos. Por ejemplo, considere:

"hello, this word is in `backticks`"

Otro caso extremo es

`${`I am nested`}`

Este enfoque también romperá cadenas de plantillas de varias líneas.

2. Reparar xgettext

Por supuesto, la solución "correcta" es escribir una bifurcación de xgettext que trate con cadenas de plantillas. Entonces podrías escribir

const something = _(`Look, I am a ${adjective} string`);

Desafortunadamente, esto podría ser más difícil de lo que parece. Existe una gran cantidad de lógica integrada dentro de xgettext relacionada con las cadenas. Si tuviera que emprender este proyecto, muchos lo agradecerían.

3. Usando un analizador

La alternativa más sólida es usar un analizador de JavaScript como Esprima. Estos analizadores exponen la capacidad de recoger tokens (como cadenas de plantillas). Como puede ver en http://esprima.org/demo/parse.html , el tipo de token relevante que debe buscar es TemplateLiteral .

4. Hacks no recomendables

Otra (¿mala?) Idea es escribir cadenas de plantillas como cadenas regulares para comenzar, luego tratarlas como cadenas de plantillas en tiempo de ejecución. Definimos una función eval_template :

const template = _("Look, I am a ${adjective} string"); const something = eval_template(template, {adjective});

eval_template convierte una cadena en una plantilla evaluada. Cualquier variable en el ámbito local utilizada en la cadena de plantilla debe proporcionarse a eval_template como parte del objeto pasado en el segundo parámetro (porque las funciones creadas con Function están en el alcance global y no pueden acceder a las variables locales, por lo que debemos pasarlas ) Se implementa de la siguiente manera:

function eval_template_(s, params) { var keys = Object.keys(params); var vals = keys.map(key => params[key]); var f = Function(...keys, "return `" + s + "`"); return f(...vals); }

De acuerdo, esto es un poco incómodo. La única ventaja de este enfoque es que no requiere reescritura previa al escaneo.

Punto menor, pero si la cadena de la plantilla original es multilínea, no puede reescribirla directamente como una cadena regular. En ese caso, puede dejarlo como una cadena de plantilla con la parte posterior marcada, pero escapa del $ as /$ , y todo estará bien:

En xgettext : a menos que quieras reescribir xgettext , usar un analizador sintáctico o participar en otro hackeo, haz el reemplazo de fuerza bruta.

Tengo que evitar la limitación de gettext para reconocer las cadenas de plantillas de ES6, y pensé en obtener el "valor no interpolado" de las cadenas de plantillas como un paso de compilación, para tener solo cadenas "normales" en el código.

Básicamente lo que me gustaría lograr es transformar esto

const adjective = ''wonderful'' const something = `Look, I am a ${adjective} string` console.log(something) > "Look, I am a wonderful string"

dentro de esto

const adjective = ''wonderful'' const something = ''Look, I am a ${adjective} string'' console.log(something) > "Look, I am a ${adjective} string"

Una forma brutal de lograr esto es usar sed , pero ciertamente no es el más elegante (y probablemente también propenso a errores)

sed "s//`/''/g" FILENAME

¿Alguna idea mejor y más limpia viene a la mente?


Actualmente, estoy trabajando en una solución de localización que se basa en literales de plantilla es6. Puede consultarlo aquí - https://c-3po.js.org . Este proyecto tiene una funcionalidad de extracción (basada en el plugin babel). Y también puedes usarlo para construir js localizados. Así es como se ve:

t`Hello ${name}`