【问题标题】:How to use Pyramid i18n outside of views and templates?如何在视图和模板之外使用 Pyramid i18n?
【发布时间】:2012-04-29 15:57:07
【问题描述】:

Pyramid documentation 向我们展示了如何使用 i18n 内部视图(和 templates as well)。但是如何在我们无法访问当前request 的视图和模板之外使用它(例如,在formsmodels 中)?

@Michael 说将request 传递给模型和表单。但这样做对吗?我的意思是如果表单字段在__init__() 方法调用之前定义,模型也是如此。他们从视图中看不到任何参数...

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

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

【问题讨论】:

    标签: python pyramid python-babel


    【解决方案1】:

    我的解决方案是在需要使用 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,然后使用该工厂创建一个表单。通过这样做,表单中的所有消息都被替换为当前的语言环境。

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

    【讨论】:

      【解决方案2】:

      【讨论】:

      • get_localizer() 需要参数request,所以这意味着我只能在视图函数(或类)中使用它。但是如何在视图之外使用它呢?
      • 好吧,您可以通过将request 传递到您的表单/模型中来访问它,或者使用get_current_request(),或者您可以制作自己的本地化程序,正如该链接通过make_localizer 所说的那样。 request 决定了本地化程序应该使用什么语言环境,如果你想保持这种行为,那么显然你需要一个request
      • 似乎您刚刚将问题从“如何在视图/模板之外进行翻译”更改为“如何进行翻译”。我觉得我在答案和 cmets 中回答了您关于 Pyramid 如何做到这一点的原始问题。要了解 Pyramid 如何进行翻译,您应该阅读我链接的整个页面,因为它似乎涵盖了大部分“实践”。
      【解决方案3】:

      实际上我也遇到了同样的问题。我最终做的是查看默认的语言环境协商器是如何工作的——它在给定的请求对象上查找 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 真的很糟糕,而且很痛苦,因为我们需要用他们的母语向用户发送电子邮件,然后尝试恢复语言……此外,翻译请求之外的任何内容都是不可能的一个 pylons 程序,作为翻译器或注册表不存在。

      【讨论】:

        【解决方案4】:

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

        在制作本地化程序时,您可以传递您想要的语言(无论您是从 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 _
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多