17

simplemente me di cuenta de que la forma rieles recomienda ajustar la configuración regional en su controlador¿Por qué la configuración regional en Rails actúa como global (cuando se usa Thin)?

before_filter :set_locale 

def set_locale 
    I18n.locale = params[:locale] || I18n.default_locale 
end 

establece la configuración regional a nivel mundial. El código anterior funciona, pero me pregunto si default_locale es realmente predeterminado si tiene que escribirlo explícitamente.

lo que cabe esperar es tener un local por la petición (como el que tenemos sesión por petición) y hacer algo como:

def set_locale 
    locale = params[:locale] if params[:locale] 
end 

Y habiendo I18n.default_locale utiliza por defecto de otra manera. Esto coincidiría con la configuración regional idealmente opcional en la ruta:

# config/routes.rb 
scope "(:locale)", :locale => /en|nl/ do 
    resources :books 
end 

Por ahora, si por alguna razón me salto configuración local en algún tipo de acción que utiliza la configuración regional establecida en la solicitud anterior, que podría ser de otro usuario!

¿Y no existe una posible condición de carrera ya que una solicitud puede cambiar global I18n.locale mientras que otra solicitud (habiendo establecido otra configuración regional antes) está en el medio de la representación?


UPDATE: Algunos detalles que he encontrado por ahora, desde el documentstion I18n:

Establece la localización actual pseudo-a nivel mundial, es decir, en el hash Thread.current def locale = (locale)

Ahora quiero entender si cada solicitud es un hilo separado.


ACTUALIZACIÓN 2: Véase mi respuesta para la explicación.

Respuesta

12

Así que ahora la respuesta final. TL; DR La configuración regional actúa como global solo cuando utiliza servidores web con hilos, como Thin y Puma.

Como he mencionado, I18n.locale=

Establece la localización actual pseudo-a nivel mundial, es decir, en la rosca.hash actual

Se supone que es por solicitud, y funciona de esta manera en Webrick y Unicorn.

Pero si utiliza un servidor web con hilos como Thin o Puma, parece que el hilo dura más, y el valor se conserva para solicitudes futuras, hasta que se modifique explícitamente. Donde aprendí es a partir de la nueva joya de Steve Klabnik request_store:

Si necesitas estado global, probablemente ha llegado a Thread.current.

<...>

Así que la gente está utilizando esos lujo roscado servidores web, como fino o Puma. Pero si usas Thread.current y usas uno de esos servidores, ten cuidado. Los valores pueden durar más de lo esperado, y esto puede causar errores.

+0

Estoy teniendo exactamente el mismo problema, ¡pero estoy usando Unicornio! Alguna idea de como resolver esto? gracias –

+0

Creo que cuando dices "I18n.set_locale", en realidad quieres decir "I18n.locale =" ¿no? http://www.rubydoc.info/github/svenfuchs/i18n/I18n/Config:locale= – lulalala

+0

Tiene razón, gracias por la corrección. – khustochka

2

El código recomendado de arriba no establece la configuración global a nivel mundial sino que lo establece por solicitud.

El código se suele colocar en BaseController por lo que antes de procesar cada página, se activa y configura. No hay condiciones de carrera ya que cada página activará este código y la configuración regional I18n se calculará allí. Puede expandir esto para, por ejemplo, buscar la configuración regional de los usuarios, que la configuración regional de la sesión, en vez de solicitar parámetros, que en inglés.

def set_locale 
    I18n.locale = @user.locale || session[:locale] || params[:locale] || :en 
end 

En otras palabras, si lo configura en una sola página digamos en el hogar de controlador alemán y llegó a controlador de panel de control verá idioma por defecto (Inglés). Dado que el cambio no es global. Es por eso que el código se coloca en el controlador base. Espero que tenga sentido.

+1

'I18n' es un módulo global, y' I18n.locale = 'cambia su estado. Acepto que la forma recomendada de establecer explícitamente la configuración regional para cada solicitud a través de 'before_filter' funciona como se espera en general. Todavía me pregunto si las solicitudes Rails se pueden ejecutar simultáneamente en diferentes subprocesos; si es así, veo que es posible que la solicitud 1 establezca 'I18n.locale', luego solicite 2 establezca' I18n.locale', luego request 1 comience a procesar usando la nueva configuración (incorrecta). Lo siento si su respuesta es incorrecta. – khustochka

Cuestiones relacionadas