2012-04-29 20 views
5

Pyramid documentation nos muestra cómo usar i18n dentro de las vistas (y templates as well). Pero, ¿cómo se puede utilizar uno fuera de las vistas y las plantillas en las que no tenemos acceso a la actual request (por ejemplo, en forms y models)?¿Cómo usar Pyramid i18n fuera de vistas y plantillas?

@Michael dice que pase request a modelos y formularios. Pero es correcto? Me refiero a si los campos de formulario definen antes de las llamadas al método __init__(), lo mismo con los modelos. Ellos no ven ningún parámetro de vistas ...

En los pilones podríamos simplemente utilizar get_lang() y set_lang() y definir el lenguaje preferible en controlador de matriz y luego usar ugettext() y ungettext() en cualquier lugar que queramos sin que calificó de request directamente cada tiempo posible (en puntos de vista).

¿Cómo hacer eso en Pyramid? Tenga en cuenta que el idioma debe configurarse a partir de la configuración del usuario (sesión, cookies, db, etc.).

Respuesta

3

Mi solución es crear la clase de formulario cuando se necesita con el localizador como parámetro. Por ejemplo

forms.py

class FormFactory(object): 

    def __init__(self, localizer): 
     self.localizer = localizer 
     _ = self.localizer 
     self.required_msg = _(u'This field is required.') 
     self.invalid_email_msg = _(u'Invalid email address.') 
     self.password_not_match_msg = _(u'Password must match') 

    def make_contact_form(self): 
     _ = self.localizer 
     class ContactForm(Form): 
      email = TextField(_(u'Email address'), [ 
       validators.Required(self.required_msg), 
       validators.Email(self.invalid_email_msg) 
      ]) 
      content = TextAreaField(_(u'Content'), [ 
       validators.Required(self.required_msg) 
      ]) 
     return ContactForm 

Cuando es necesario utilizar la forma

@view_config(route_name='front_pages.contact_us', 
      renderer='myweb:templates/front_pages/contact_us.genshi') 
def contact_us(request): 
    """Display contact us form or send mail 

    """ 
    _ = get_localizer(request) 

    factory = FormFactory(_) 
    ContactForm = factory.make_contact_form() 
    form = ContactForm(request.params) 
    return dict(form=form) 

Como se puede ver, se obtiene el localizador en la vista, y pasarlo a la FormFactory, luego crea una forma con esa fábrica. Al hacerlo, todos los mensajes en el formulario fueron reemplazados por el idioma local actual.

Del mismo modo, puede hacer lo mismo con el modelo.

2
+0

'get_localizer() 'require parametr' request', así que esto significa que puedo usarlo solo dentro de la función de vista (o clase). Pero, ¿cómo usarlo fuera de las vistas? –

+1

Bueno, usted accede a la 'solicitud' pasándola a sus formularios/modelos, o usa' get_current_request() 'o crea su propio localizador como dice ese enlace a través de' make_localizer'. La 'solicitud' determina qué localidad debe usar el localizador, y si desea mantener ese comportamiento, obviamente necesita una' solicitud'. –

+0

Parece que acaba de cambiar la pregunta de "cómo hacer la traducción fuera de vistas/plantillas" a "cómo hacer la traducción". Siento que respondí tu pregunta original en la respuesta y los comentarios con respecto a cómo Pyramid hace esto. Para saber cómo hace Pyramid la traducción, debe leer toda la página que he vinculado, porque realmente parece abarcar la mayor parte de esta "práctica". –

1

en realidad tenía este mismo problema. Lo que terminé haciendo fue ver cómo funciona el negociador de locale predeterminado: busca una propiedad LOCALE en el objeto de solicitud dado. Así que solo usa un maniquí para crear el localizador. Es posible almacenar en caché este valor también, si quieres

def my_get_localizer(locale=None): 
    request = Request({}) 
    request._LOCALE_ = locale 

    return get_localizer(request) 

Alternativamente, se unen al canal de IRC#pyramid @ freenode y molestar a los chicos lo suficiente allí para dividir la funcionalidad de get_localizer en 2 funciones separadas documentados (get_localizer y get_localizer_for_locale_name) para nosotros para disfrutar;)

Además, tenga en cuenta que Pyramid TranslationStrings son flojos, por lo que puede traducirlos tan tarde como desee, por ejemplo

class MyModel(Base): 
    description = TranslationString("My model number ${number}") 

... 

def view(request): 
    m = MyModel() 
    localizer = get_localizer(request) 
    description = localizer.translate(m.description, mapping={'number': 1}) 

Sidenote: pilones 'i18n era la peor lata de gusanos que había abierto en mucho tiempo. El hack set_lang, get_lang fue realmente horrible, y el dolor en el culo ya que necesitábamos enviar correos electrónicos a los usuarios en sus idiomas nativos y luego tratar de restaurar el idioma ... también, era IMPOSIBLE traducir cualquier cosa fuera de una solicitud en un programa de pilones, como traductor o el registro no existía entonces.

0

Puede hacer un localizador y luego traducir una plantilla en consecuencia.

Al hacer el localizador, puede pasar el idioma que desee (ya sea que lo tenga de db u otro). Espero que pueda ayudar.

En aras de la claridad, voy a configurarlo como 'fr' a continuación

from pyramid.i18n import make_localizer, TranslationStringFactory 
from mako.template import Template 
from mako.lookup import TemplateLookup 
import os 

absolute_path = os.path.dirname(os.path.realpath(__file__)) 
tsf = TranslationStringFactory('your_domain') 
mako_lookup = TemplateLookup(directories=['/']) 
template = Template(filename=template_path, lookup=mako_lookup) 

localizer = make_localizer("fr", [absolute_path + '/../locale/']) 

def auto_translate(*args, **kwargs): 
    return localizer.translate(tsf(*args, **kwargs)) 

# Pass _ pointer (translate function) to the context 
_ = auto_translate 

context.update({ 
    "_": _ 
}) 

html = template.render(**context) 

EDITAR También se puede poner esta lógica en una pequeña función

def get_translator(lang): 
    """ 
    Useful when need to translate outside of queries (no pointer to request) 
    :param lang: 
    :return: 
    """ 
    localizer = make_localizer(lang, [absolute_path + '/../locale/']) 

    def auto_translate(*args, **kwargs): 
     return localizer.translate(tsf(*args, **kwargs)) 

    _ = auto_translate 

    return _ 
Cuestiones relacionadas