如何在视图和模板之外使用Pyramid i18n?

时间:2012-04-29 15:57:08

标签: python pyramid babel

Pyramid documentation告诉我们如何在视图中使用i18n(和templates as well)。但是如何在我们无权访问当前request的视图和模板之外使用它(例如,在formsmodels中)?

@Michael说要将request传递给模特和表格。但这是对的吗?我的意思是如果表单字段在__init__()方法调用之前定义,则与模型相同。他们没有从视图中看到任何参数...

在Pylons中,我们可以简单地使用get_lang()set_lang()并在父控制器中定义首选语言,然后在我们想要的任何地方使用ugettext()ungettext(),而无需调用它request直接在每个可能的时间(在视图中)。

如何在金字塔中做到这一点?请注意,必须根据用户的设置(会话,cookie,数据库等)设置语言。

4 个答案:

答案 0 :(得分:3)

我的解决方案是在需要localizer作为参数时创建表单类。例如

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

当您需要使用表格

@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)

如您所见,我们在视图中获取了本地化程序,并将其传递给FormFactory,然后使用该工厂创建表单。通过这样做,表单中的所有消息都被当前的语言环境替换。

同样,你可以对模型做同样的事情。

答案 1 :(得分:2)

答案 2 :(得分:1)

其实我遇到了同样的问题。我最终做的是查看默认语言环境协商器如何工作 - 它在给定的请求对象上查找 LOCALE 属性。所以只需使用虚拟对象来创建定位器。如果需要,您也可以缓存此值

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

    return get_localizer(request)

或者,加入irc频道#pyramid @ freenode并在那里充分纠缠那些人将get_localizer的功能分成2个单独的文档函数(get_localizer和get_localizer_for_locale_name)供我们欣赏;)

另外,请注意Pyramid TranslationStrings是懒惰的,因此您可以根据需要进行翻译,例如。

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})
旁白:pylons'i18n是我多年来打开的最糟糕的蠕虫。因为我们需要用他们的母语向用户发送电子邮件然后尝试恢复语言,所以set_lang,get_lang hack真的非常糟糕,而且很痛苦...而且,在请求之外翻译任何内容都是不可能的。当时不存在作为翻译或注册表的挂架程序。

答案 3 :(得分:0)

您可以制作本地化程序,然后相应地翻译模板。

制作本地化程序时,您可以传递所需的语言(无论您是从db还是其他语言)。希望它可以提供帮助。

为了清楚起见,我将其设置为下面的“fr”

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)

<强> 修改 您也可以将此逻辑放入一个小函数

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 _