26

Estamos construyendo una aplicación, la primera que usamos Rails 3, y tenemos que crear I18n desde el principio. Siendo perfeccionistas, queremos que la tipografía real se use en nuestros puntos de vista: guiones, comillas rizadas, elipses y otros.Evitando que las entidades de caracteres HTML en los archivos locales se contaminen con la protección Rails3 xss

Esto significa en nuestros locales/archivos xx.yml tenemos dos opciones:

  1. utilidad real caracteres UTF-8 en línea. Debería funcionar, pero es difícil de escribir, y me asusta debido a la cantidad de software que todavía hace cosas malas a unicode.
  2. usar HTML carácter entidades (& # 8217; & # 8212; etc.). Más fácil de escribir, y probablemente más compatible con el software de comportamiento incorrecto .

prefiero tomar la segunda opción, sin embargo, la auto-escapar en Rails 3 hace esta problemática, ya que los símbolos de unión en el YAML obtener automáticamente convertidos en entidades de caracteres sí mismos, lo que resulta en 'visible' & 8217; s en el navegador.

Obviamente, esto se puede evitar mediante el uso de raw en cadenas, es decir:

raw t('views.signup.organisation_details') 

Pero no estamos contentos de ir por el camino de nivel mundial raw -ing cada vez que t algo ya que nos deja abierta a hacer un error y producir un agujero XSS.

Podríamos seleccionar raw cadenas que sabemos que contienen entidades de caracteres, pero esto sería difícil de escalar, y simplemente se siente mal, además, una cadena que contiene una entidad en un idioma no puede en otro.

¿Alguna sugerencia sobre una forma astuta de rails-y para arreglar esto? ¿O estamos condenados a la tipografía basura, hoyos xss, horas de esfuerzo perdido o todo?

+2

que es una buena pregunta. esperando una buena respuesta. –

Respuesta

32

Hay una ticket in lighthouse para este problema, y ​​la resolución es añadir _html a la tecla i18n en el archivo locales/xx.yml y utilizar los alias de t para denotar una cadena html_safe. Por ejemplo:

en: 
    hello: "This is a string with an accent: ó" 

se convierte en:

en: 
    hello_html: "This is a string with an accent: ó" 

y crearía el siguiente resultado:

Ésta es una cadena con un acento: & oacute;

Esto le evitaría tener que escribir raw t('views.signup.organisation_details') y resultaría en una salida más limpia de: t('views.signup.organisation_details_html'). Y si bien el intercambio de raw para _html no parece la mejor operación, sí deja en claro que está produciendo lo que se supone que es una cadena html_safe.


He probado el código sugerido en el billete faro. Lo que encontré fue que tenía que usar específicamente el alias t. Si utilizó I18n.t o I18n.translate la traducción no trató a _html como html_safe:

I18n.t('hello_html') 
I18n.translate('hello_html') 
# Produces => "This is a string with an accent: ó" 

t('hello_html')  
# Produces => "This is a string with an accent: ó" 

no creo que este es el comportamiento previsto por el RoR TranslationHelper documentation.

8

Bien. Ayer marqué esta pregunta debido al ángulo i18n, pero no respondí porque soy una persona de Python que nunca usó Rails. Todavía no voy a contestar, pero dado que no están siendo arrollados por Railsianos útiles que podrían indicarle una buena manera de evitar las entrañas de Rails, esta es mi perspectiva, no obstante.

En primer lugar, creo que es gran que está pensando en el problema desde el principio. Eso es bastante raro. En segundo lugar, estoy completamente de acuerdo en que el uso de cadenas sin formato o la selección selectiva de cadenas con entidades para dar un tratamiento especial suena como un hack frágil, feo y propenso a errores.

Ahora si entiendo Rails correctamente (Leo this i18n guide), los archivos YAML contienen la cadena localizada para cada idioma. En este caso, recomiendo usar caracteres regulares en ellos (en UTF-8). De lo contrario, manteniendo las localizaciones, o incluso leyendo a través de un archivo de traducción, ¡piense en idiomas en scripts no latinos! - Va a ser un infierno.

Sí, significa que tiene que descubrir los métodos de entrada, pero la solución es limpia y directa.

+0

sí, simplemente coloque los caracteres codificados en UTF-8 completos en el archivo. Es lo que los chicos de Java han estado haciendo desde los dinosaurios: busca en todos sus archivos de idiomas y verás las codificaciones nativas. –

+0

+1, estoy completamente de acuerdo. –

+1

En retrospectiva, creo que esta es quizás la mejor solución. No sé por qué era tan reacio a eso hace 3 años. –

0

¿Conoce el método html_safe que se puede usar en ayudantes? No estoy seguro si entiendo totalmente el problema aquí, ya que nunca he trabajado con I18n, pero sería posible usar un helper personalizado que determine si los caracteres no deberían escaparse y devolver "string" .html_safe, y si debería escaparse, devolver "cadena".

O, posiblemente, anulan el ayudante "t" y añadir sus condiciones lógicas que escapan + .html_safe

+0

No sé lo suficiente sobre el problema yo mismo (y el 'Camino de Rails') para saber si este es un buen plan u otro camino a la ruina, pero gracias por la idea ... Podría probarlo y hacerle saber cómo va. –

0

Creo que no es una buena idea utilizar el uso "en bruto", podría intentar con una cuerda yml como esto

en: 
    hello: 
    This generates a text paragraph for HTML. " " à @ ' All this text, which you can find in 
    these lines, is being concatenated together to one single text node, and then put 
    into the body of the <p> ... </p> tag. ↂↀऊᎣᏍᏮ⁜℺℻⊛⍟⎬⎨⏏♞♝⚫⚬✱✰✭❺❻➣➱➲⬡⬕ 

HTML

This generates a text paragraph for HTML. &quot; &quot; à @ ' All this text, which you can find in these lines, is being concatenated together to one single text node, and then put into the body of the &lt;p&gt; ... &lt;/p&gt; tag. ↂↀऊᎣᏍᏮ⁜℺℻⊛⍟⎬⎨⏏♞♝⚫⚬✱✰✭❺❻➣➱➲⬡⬕ 

vista del navegador

This generates a text paragraph for HTML. " " à @ ' All this text, which you can find in these lines, is being concatenated together to one single text node, and then put into the body of the <p> ... </p> tag. ↂↀऊᎣᏍᏮ⁜℺℻⊛⍟⎬⎨⏏♞♝⚫⚬✱✰✭❺❻➣➱➲⬡⬕ 
1

Si no quiere exponerse a la posibilidad de un error simplemente agregando .html_safe (a través de alias_cadena_de_metodo o w/e) a todo, la mejor solución es simplemente usarla siempre que sea necesario.

En nuestro sitio usamos el lenguaje de marcado para obtener el resultado HTML de los archivos locales i18n, ya que quien los traduce no son desarrolladores, solo traductores.

Si solo en algunos lugares necesita su HTML para ser realmente HTML, úselo.html_safe

t('views.signup.organisation_details').html_safe 

El lenguaje simple de marcas que tenemos funciona bastante bien para nosotros, pero que es muy específica para cada caso :)

Cuestiones relacionadas