【问题标题】:set language within a django view在 Django 视图中设置语言
【发布时间】:2011-01-21 03:53:31
【问题描述】:

背景: 当支付服务在后台回复支付结果时调用该视图 - 之后我需要以正确的语言发送电子邮件以确认支付等。我可以从支付服务器的请求中取回语言代码,并希望将其与 Django 的 i18n 系统一起使用来确定以哪种语言发送我的电子邮件。

所以我需要在视图中设置我的 django 应用程序的语言。然后一次性完成我的模板渲染和电子邮件。

设置request.session['django_language'] = lang 仅在我测试时影响下一个视图。

还有其他方法吗?

干杯,

男人

【问题讨论】:

    标签: django internationalization


    【解决方案1】:

    引用 Django 的 Locale Middleware (django.middleware.locale.LocaleMiddleware) 中的部分内容:

    from django.utils import translation
    
    class LocaleMiddleware(object):
        """
        This is a very simple middleware that parses a request
        and decides what translation object to install in the current
        thread context. This allows pages to be dynamically
        translated to the language the user desires (if the language
        is available, of course).
        """
    
        def process_request(self, request):
            language = translation.get_language_from_request(request)
            translation.activate(language)
            request.LANGUAGE_CODE = translation.get_language()
    

    translation.activate(language) 是重要的一点。

    【讨论】:

    • 很好的提示。帮助我解决了我遇到的一个完全不相关的问题(由于某些先前的测试使用了 django 的测试客户端,因此 doctest 失败了,这使系统具有意外的语言环境值。在 doctest 的开头添加 translation.deactivate_all() 解决了这个问题)
    • 如何使用它,在我的自定义视图中登录用户时设置语言?语言代码放在 UserProfile 表中。
    • 警告,我刚刚修复了当前开发中的一个错误,原因是 translation.activate :线程在请求​​之间重用并保持最后一种语言处于激活状态。这导致了一些奇怪的事情,比如 django admin 一直在切换语言。如果您手动触发 transaction.activate,请不要忘记在所有字符串都被渲染后使用 translation.deactivate(这是 LocaleMiddleware 在渲染后所做的)。
    • 一定要把LocaleMiddleware放在 SessionMiddleware之后,我们刚刚解决了一些问题。
    • @vincent 嗨,文森特,我们还需要这个吗?我将它与多个激活一起使用during password reset。
    【解决方案2】:

    一定要在process_response中也加上deactivate,否则不同线程会有问题。

    from django.utils import translation
    
    class LocaleMiddleware(object):
        """
        This is a very simple middleware that parses a request
        and decides what translation object to install in the current
        thread context. This allows pages to be dynamically
        translated to the language the user desires (if the language
        is available, of course).
        """
    
        def process_request(self, request):
            language = translation.get_language_from_request(request)
            translation.activate(language)
            request.LANGUAGE_CODE = translation.get_language()
    
        def process_response(self, request, response):
            translation.deactivate()
            return response
    

    【讨论】:

    • 当我在没有停用翻译的情况下使用中间件时遇到了奇怪的行为,我想知道为什么这会导致线程出现问题。无论如何,感谢您的重要提示。 +1
    【解决方案3】:

    您可以考虑将语言存储在用户模型中并使用此自定义中间件django-user-language-middleware。

    这可以通过查看 user.language 字段中选择的语言轻松翻译您的 Django 应用程序,您可以随时了解任何用户的语言偏好。

    用法:

    1. 向您的用户模型添加语言字段:

      class User(auth_base.AbstractBaseUser, auth.PermissionsMixin):
          # ...
          language = models.CharField(max_length=10,
                                      choices=settings.LANGUAGES,
                                      default=settings.LANGUAGE_CODE)
      
    2. 从 pip 安装中间件:

      pip install django-user-language-middleware

    3. 将其添加到设置中的中间件类列表以侦听请求:

      MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
          ...
          'user_language_middleware.UserLanguageMiddleware',
          ...
      ]
      

    我希望这可以帮助人们将来解决这个问题。

    【讨论】:

      【解决方案4】:

      如果只是想获取某种语言的翻译字符串,您可以像这样use override as a decorator:

      from django.utils import translation
      from django.utils.translation import ugettext as _
      
      with translation.override(language):
          welcome = _('welcome')
      

      【讨论】:

        【解决方案5】:

        有时您希望为给定视图强制使用某种语言,但让浏览器语言设置为其余视图选择语言。我还没有弄清楚如何更改视图代码中的语言,但您可以通过实现一个简单的中间件来做到这一点

        lang_based_on_url_middleware.py:

        from django.utils import translation
        
        # Dictionary of urls that should use special language regardless of language set in browser
        #   key = url
        #   val = language code
        special_cases = {
            '/this/is/some/url/' : 'dk',
            '/his/is/another/special/case' : 'de',
                         }
        
        class LangBasedOnUrlMiddleware(object):
            def process_request(self, request):
                if request.path_info in special_cases:
                    lang = special_cases[request.path_info]
                    translation.activate(lang)
                    request.LANGUAGE_CODE = lang
        

        在settings.py中:

        MIDDLEWARE_CLASSES = (
            ...
            'django.middleware.locale.LocaleMiddleware',
            'inner.lang_based_on_url_middleware.LangBasedOnUrlMiddleware', # remember that the order of LocaleMiddleware and LangBasedOnUrlMiddleware matters
            ...
        )
        

        不是一个优雅的解决方案,但它有效。

        【讨论】:

          【解决方案6】:

          如果您使用 django 1.10 或更高版本,自定义中间件有一个新语法:

          from django.utils import translation
          
          class LocaleMiddleware(object):
          
              def __init__(self, get_response):
                  self.get_response = get_response
          
              def __call__(self, request):
          
                  language_code = 'en' #TODO, your logic
          
                  translation.activate(language_code)
          
                  response = self.get_response(request)
          
                  translation.deactivate()
          
                  return response
          

          【讨论】:

            【解决方案7】:

            request.LANGUAGE_CODE 如果 LocaleMiddleware 已激活。

            【讨论】:

              【解决方案8】:

              对于基于类的视图,这应该可以工作:

              class YourView(SomeBuiltInView):
              def get(self, request, *args, **kwargs):
                  setattr(request, 'LANGUAGE_CODE', 'YOUR_LANGUAGE_CODE')
                  return super().get(self, request, *args, **kwargs)
              

              基本上你所做的只是让视图渲染器认为请求来自YOUR_LANGUAGE_CODE,而不是原来的真实。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2020-01-20
                • 2012-08-01
                • 2017-03-04
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多