Я хотел бы воспользоваться новыми возможностями 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.