Как выбрать язык из файлов cookie / заголовков / сеанса в webapp2?

Я бы хотел воспользоваться преимуществами новых возможностей webapp2 для локализации, которые также имеют форматирование времени и валюты, зависящее от локали.

В Django есть хорошая функция get_language_from_request которые я использовал до того, как полностью перешел на webapp2, и теперь я использую i18n из webapp2, и я могу переключаться между локализациями, которые я пишу с помощью 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 доступен, но я не знаю, сколько делает i18n из webapp2, например, нужно ли мне позаботиться об откате для таких языков, как pt-br, должен вернуться к pt, если его нет. mo локализация для pt-br и аналогичные для других диалектов.

На самом деле настройку языка я могу сделать с помощью

i18n.get_i18n (). Set_locale (language)

Я прошу вашей помощи сделать приоритетными различные способы получения языка пользователя, и я также хотел бы знать свои идеи, как продолжить реализацию. Или вы думаете, что я могу просто использовать переменную сеанса и не так тщательно подходить к «полному» решению, поскольку я все равно в основном исправляю язык для географического использования, где мои единственные фактически используемые переводы сейчас - это бразильский португальский и английский, но я хочу он хорошо подготовлен к переключению на испанский и русский, а также на другие языки, поэтому я хотел бы иметь возможность переключиться на язык пользователя и, по крайней мере, сохранить его в сеансе webapp2 и знать, что вы думаете об использовании также cookie и заголовка, чтобы получить пользователя язык.

Исходный код, который я использовал для si от django, выглядит так, и я больше не могу его использовать, потому что он привязан к файлам 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

Согласно моим ожиданиям, я могу взять некоторую функцию непосредственно из django, если я решу использовать заголовки http, но я не понимаю, что они делают, поэтому, возможно, вы можете объяснить это код для меня из 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

Спасибо

Обновление

Я обнаружил, что не могу использовать сеансы в функции инициализации обработчика запросов, возможно, это потому, что объект сеанса еще не создан. Поэтому я поместил код для получения языка из сеанса в функцию рендеринга BaseHandler, и, похоже, он работает. Также было бы неплохо рассмотреть заголовки или значение cookie.

6
задан Niklas Rosencrantz 15 December 2011 в 07:47
поделиться