如何从webapp2中的cookies/headers/session决定语言?

2023-11-23

我想利用 webapp2 的新本地化功能,该功能还具有特定于区域设置的时间和货币格式。

Django 有一个很好的函数,名为 get_language_from_request,我在完全迁移到 webapp2 之前就使用了该函数,现在我使用 webapp2 中的 i18n,并且我可以在使用 gettext 编写的本地化之间进行切换,并编译为我的应用程序可以使用的名为 messages.mo 的文件读取并显示。然后,我确定了以下获取用户语言的方法并确定了优先级: 1. HTTP GET 例如。 hl=pt-br 巴西葡萄牙语 2. HTTP SESSION变量我称之为i18n_language 3. Cookie 我应该设置和获取,但我不知道具体如何 4. 我可以获得 HTTP 标头,但在这里我也不太清楚,我正在寻找 djnango 如何通过方便的方式做到这一点get_language_from_request我曾经使用过,现在我已经停止导入 django,并且我仍然希望在我现在基于 webapp2 的代码中使用此功能。

def get_language_from_request(self, request):
    """
    Analyzes the request to find what language the user wants the system to
    show. If the user requests a sublanguage where we have a main language, we send
    out the main language.
    """
    if self.request.get('hl'):
      self.session['i18n_language'] = self.request.get('hl')
      return self.request.get('hl')

    if self.session:
      lang_code = self.session.get('i18n_language', None)
      if lang_code:
        logging.info('language found in session')
        return lang_code

    lang_code = Cookies(self).get(LANGUAGE_COOKIE_NAME)
    if lang_code:
        logging.info('language found in cookies')
        return lang_code

    accept = os.environ.get('HTTP_ACCEPT_LANGUAGE', '')
    for accept_lang, unused in self.parse_accept_lang_header(accept):
      logging.info('accept_lang:'+accept_lang)
      lang_code = accept_lang

    return lang_code

我看到 django 代码可用,但我不知道 webapp2 中的 i18n 做了多少,例如,如果没有 .mo 本地化,我是否必须处理诸如 pt-br 之类的语言的回退,应该回退到 pt pt-br 和其他方言类似。

实际上设置我可以使用的语言

i18n.get_i18n().set_locale(language)

我请求您帮助确定获取用户语言的不同方式的优先级,我也想知道您对如何继续实施的想法。或者您认为我可以只使用会话变量而不是彻底了解“完整”解决方案,因为无论如何我主要修复地理用途的语言,其中我现在唯一实际使用的翻译是巴西葡萄牙语和英语,但我想要它已经做好了切换到西班牙语、俄语和其他语言的准备,因此我希望能够切换到用户语言并至少将其保存到 webapp2 会话中,并了解您对使用 cookie 和 header 来获取用户的想法语言。

我曾经从 django 获得 si 的原始代码看起来像这样,我不能再使用它了,因为它被锁定到 django.mo 文件并且特定于 django

def get_language_from_request(request):
    """
    Analyzes the request to find what language the user wants the system to
    show. Only languages listed in settings.LANGUAGES are taken into account.
    If the user requests a sublanguage where we have a main language, we send
    out the main language.
    """
    global _accepted
    from django.conf import settings
    globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
    supported = dict(settings.LANGUAGES)

    if hasattr(request, 'session'):
        lang_code = request.session.get('django_language', None)
        if lang_code in supported and lang_code is not None and check_for_language(lang_code):
            return lang_code

    lang_code = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME)

    if lang_code and lang_code not in supported:
        lang_code = lang_code.split('-')[0] # e.g. if fr-ca is not supported fallback to fr

    if lang_code and lang_code in supported and check_for_language(lang_code):
        return lang_code

    accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
    for accept_lang, unused in parse_accept_lang_header(accept):
        if accept_lang == '*':
            break

        # We have a very restricted form for our language files (no encoding
        # specifier, since they all must be UTF-8 and only one possible
        # language each time. So we avoid the overhead of gettext.find() and
        # work out the MO file manually.

        # 'normalized' is the root name of the locale in POSIX format (which is
        # the format used for the directories holding the MO files).
        normalized = locale.locale_alias.get(to_locale(accept_lang, True))
        if not normalized:
            continue
        # Remove the default encoding from locale_alias.
        normalized = normalized.split('.')[0]

        if normalized in _accepted:
            # We've seen this locale before and have an MO file for it, so no
            # need to check again.
            return _accepted[normalized]

        for lang, dirname in ((accept_lang, normalized),
                (accept_lang.split('-')[0], normalized.split('_')[0])):
            if lang.lower() not in supported:
                continue
            langfile = os.path.join(globalpath, dirname, 'LC_MESSAGES',
                    'django.mo')
            if os.path.exists(langfile):
                _accepted[normalized] = lang
                return lang

    return settings.LANGUAGE_CODE

对每个请求都这样做可以吗?我想我还应该将标题设置为语言self.response.headers['Content-Language'] = language

根据我的期望,如果我选择使用 http 标头,我可以直接从 django 获取一些函数,但我不明白它的作用,所以也许你可以从 django 为我解释这段代码:

def parse_accept_lang_header(lang_string):
    """
    Parses the lang_string, which is the body of an HTTP Accept-Language
    header, and returns a list of (lang, q-value), ordered by 'q' values.

    Any format errors in lang_string results in an empty list being returned.
    """
    result = []
    pieces = accept_language_re.split(lang_string)
    if pieces[-1]:
        return []
    for i in range(0, len(pieces) - 1, 3):
        first, lang, priority = pieces[i : i + 3]
        if first:
            return []
        priority = priority and float(priority) or 1.0
        result.append((lang, priority))
    result.sort(lambda x, y: -cmp(x[1], y[1]))
    return result

谢谢

Update

我发现我无法在请求处理程序的初始化函数中使用会话,也许是因为会话对象尚未创建。因此,我将用于从会话获取语言的代码放在 BaseHandler 渲染函数中,它似乎可以工作。考虑标头或 cookie 值也很好。


这就是我所做的 - 我有一个基本请求处理程序,我的所有请求处理程序都继承自它,然后在这里我有一个包含可用语言的常量,并且我覆盖初始化方法设置每个请求的语言:

import webapp2
from webapp2_extras import i18n

AVAILABLE_LOCALES = ['en_GB', 'es_ES']

class BaseHandler(webapp2.RequestHandler):
    def __init__(self, request, response):
        """ Override the initialiser in order to set the language.
        """
        self.initialize(request, response)

        # first, try and set locale from cookie
        locale = request.cookies.get('locale')
        if locale in AVAILABLE_LOCALES:
            i18n.get_i18n().set_locale(locale)
        else:
            # if that failed, try and set locale from accept language header
            header = request.headers.get('Accept-Language', '')  # e.g. en-gb,en;q=0.8,es-es;q=0.5,eu;q=0.3
            locales = [locale.split(';')[0] for locale in header.split(',')]
            for locale in locales:
                if locale in AVAILABLE_LOCALES:
                    i18n.get_i18n().set_locale(locale)
                    break
            else:
                # if still no locale set, use the first available one
                i18n.get_i18n().set_locale(AVAILABLE_LOCALES[0])

首先,我检查 cookie,然后检查标头,最后如果未找到有效语言,则默认使用第一种可用语言。

为了设置 cookie,我有一个单独的控制器,如下所示:

import base

class Index(base.BaseHandler):
    """ Set the language cookie (if locale is valid), then redirect back to referrer
    """
    def get(self, locale):
        if locale in self.available_locales:
            self.response.set_cookie('locale', locale, max_age = 15724800)  # 26 weeks' worth of seconds

        # redirect to referrer or root
        url = self.request.headers.get('Referer', '/')
        self.redirect(url)

因此,像 www.example.com/locale/en_GB 这样的 URL 会将语言环境更改为 en_GB,设置 cookie 并返回引荐来源网址(这样做的优点是能够在任何页面上切换语言,并使其保持在同一页面上)页)。

此方法不考虑标头中区域设置的部分匹配,例如“en”而不是“en_GB”,但看到我在应用程序中启用的语言列表是固定的(并且区域设置更改 URL 很难 -编码在页脚中),我不太担心。

HTH

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从webapp2中的cookies/headers/session决定语言? 的相关文章

随机推荐

  • 如何使用express-validator在单独的文件中实现验证

    我正在尝试使用express validator 来验证req body 然后再发送post 请求以将数据插入postgres 我有一个路由文件 控制器文件 我想在名为 validate js 的文件中进行验证 同时 我已经安装了expre
  • Date.tomorrow 引用从现在开始的两天

    我看到一些非常奇怪的东西 h3 h3 结果是 2013 年 10 月 9 日星期三 这是正确的 然而 结果是 2013 年 10 月 11 日星期五 h3 h3 它完全跳过星期四 实际上是明天 有任何想法吗 方法tomorrow不在 Rub
  • 当未指定区域时,ASP.NET MVC 2 RC 2 返回特定于区域的控制器

    我有一个基本的 MVC 2 RC2 站点 其中包含一个基础级控制器 Home 以及一个区域 Admin 和一个控制器 Abstract 当我打电话时http 网站 摘要 即使我没有在 URL 中指定区域 管理区域中的抽象控制器也会被调用 更
  • 以编程方式设置 EditText 数字

    我本质上是试图以编程方式设置 EditText 的数字值 到目前为止我有 weightInput setInputType InputType TYPE CLASS PHONE weightInput setKeyListener Digi
  • 错误:@vitejs/plugin-vue 要求 vue (>=3.2.13) 或 @vue/compiler-sfc 存在于依赖关系树中

    我正在使用带有模块 federation 和 vue3 的 berry 版本的纱线 当我运行这些命令来创建项目的基础时 mkdir vue error yarn set version stable yarn plugin import w
  • CreateProcess:在 C++/Windows 中将子标准输出重定向到父标准输出

    根据 MSDN 这将子 stdout 重定向到父 stdout 但事实并非如此 有什么问题吗 PROCESS INFORMATION pi STARTUPINFOA si ZeroMemory si sizeof si si cb size
  • Symfony 查询错误:预期文字,得到 '"'

    我有以下查询 query em gt createQueryBuilder gt select u id u username u username canonical u email u email canonical u last lo
  • 我可以在 ngIf 语句中使用过滤器吗

    有没有办法在 ng if 语句中使用过滤器 例如 div span Hello span div 注意 翻译过滤器返回一个字符串 我知道如何在控制器内执行此操作 但我想在 HTML 上使用 是的 这有效 这是一个笨蛋 http plnkr
  • android sqlite 删除查询不起作用

    以下 sqlite 查询不会删除以零开头的 ID Android Sqlite 表结构 String CREATE TABLE BUS CREATE TABLE TABLE BUS KEY TID INTEGER PRIMARY KEY A
  • 修复损坏的 SVN 存储库

    我在 Mac OS X Lion 10 7 2 11C74 上使用 svnX 0 9 13 并且我认为似乎有一个损坏的 SVN 存储库 我在该网站上搜索了类似的问题并得到了found a couple 但没有人描述当你无法完成任务时如何恢复
  • PHP 中如何实现分页? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 PHP 中通常如何实现分页结果 我想要一个包含 10 个结果的结果页面 在导航中向前翻页将显示下一组和上一组 有没有一种常见的方法 有人对入门有简单的建议吗 您需要对 PHP 有一定
  • 如何用前 n 个级别(通过某些指标)以及 [其他] 替换因子级别?

    对于在图表中着色的级别数超过合理数量的因素 我想用 其他 替换不在 前 10 个 中的任何级别 替代问题 如何将因子水平减少到 rcolorbrewer 可以绘制为单独颜色的数量 例如 如果我想从棒球数据中绘制每十年的本垒打数量 requi
  • PyQt QWidget 窗口显示后立即关闭?

    我意识到这个问题之前已经被问过好几次了 尽管它们似乎都不适用于我的情况 我已经安装了 PyQt 并且只是尝试打开一个窗口 如下所示 import sys from PyQt4 import QtGui as qt segmentation
  • 一直异步问题

    我有一个异步 asp net 控制器 该控制器调用异步方法 实际执行异步 IO 工作的方法在我的应用程序的深处 控制器和链中最后一个方法之间的一系列方法都用 async 修饰符标记 这是我如何设置代码的示例 public async Tas
  • 编辑(更新、删除)空手道中的标题之一

    我有这个标题 它位于 js文件 我正在使用读取此标头 configure headers read classpath services Headers distheader js 问题 1 如何使用场景数据在运行时编辑此文件中的标头之一
  • Mongodb C# 驱动程序和 ISODate

    我通过了以下测试 namespace MongoDateTest TestFixture public class DateTesting public class TestEntity public string Id get set p
  • 我想用 javascript 将链接延迟 500 秒

    我一直在浏览 Stackoverflow 的问题 试图获得有关简单链接延迟的帮助 我想把它放在 div 周围 但我无法弄清楚我找到的示例 到目前为止 我知道我需要停止 href 的本机功能 但我不知道该怎么做 该代码对我来说仍然很陌生 帮助
  • 从另一个类调用表单类中的函数,C# .NET

    有人可以通过一些代码让我知道如何从另一个类调用位于 Form 类中的函数吗 一些代码会有很大帮助 thanks 编辑 这是我当前的代码 public partial class frmMain Form Class Instances Im
  • 关于默认的 C 结构体值,这段代码怎么样?

    我正在尝试创建具有默认值的结构 我不知道如何实现这一点 因为我看到的每个代码都是关于初始化的 我会以自然的方式进行 例如 struct stuff int stuff a 1 int stuff b 2 and so on 环顾四周 我发现
  • 如何从webapp2中的cookies/headers/session决定语言?

    我想利用 webapp2 的新本地化功能 该功能还具有特定于区域设置的时间和货币格式 Django 有一个很好的函数 名为 get language from request 我在完全迁移到 webapp2 之前就使用了该函数 现在我使用