angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Flask Многоязыковая обработка, переключение и исключение 404 Страница не найдена

В этой заметке мы обсуждаем несколько условий при обработке языка в url, используя язык по умолчанию и используя список доступных языков.

13 ноября 2019 Обновленный 15 ноября 2019
post main image
https://unsplash.com/@sadswim

Как реализовать многоязычие Flask объясняется в документах Flask , см. ссылки ниже. Но это только начало. Вам необходимо более глубокое понимание процесса обработки особых случаев, таких как возврат к языку по умолчанию, переключение языка и исключение 404 Страница не найдена.

Предположения

В оставшейся части этой статьи мы используем код языка 'lang_code', который доступен в URL, это первая часть URL, например:

https://www.example.com/en

https://www.example.com/en/login

Мы также используем Flask-Babel для переводов. Я использую blueprints и регистрирую их в create_app() следующим образом:

    # authentication (shared)
    from shared.blueprints.auth.views import auth_blueprint
    app.register_blueprint(auth_blueprint, url_prefix='/<lang_code>/auth')

    # pages (shared)
    from shared.blueprints.pages.views import pages_blueprint
    app.register_blueprint(pages_blueprint, url_prefix='/<lang_code>')

В качестве значения выбранного языка мы используем g.lang_code. Я использую переменную сессии не для запоминания языка, а полагаюсь на доступность языка в каждом запросе.

Flask Многоязычная обработка данных

Flask обрабатывает запрос на нескольких языках следующим образом:

Во-первых, вызывается url_value_preprocessor() для извлечения языка из примера url:

@pages_blueprint.url_value_preprocessor
def pull_lang_code(endpoint, values):
    # pop lang_code from url and set g.lang_code
    ...
    if 'lang_code' in values:
        g.lang_code = values.pop('lang_code')

Затем вызывается функция locale_selector() Babels для обеспечения перевода страницы, например:

@babel.localeselector
def get_locale():
    return g.get('lang_code')

Наконец url_defaults() вызывается перед тем, как страница будет собрана для замены <lang_code> на lang_code> в urls, например:

@pages_blueprint.url_defaults
def add_language_code(endpoint, values):
    # stuff g.lang_code in urls
    ...
    values.setdefault('lang_code', g.lang_code)

Это довольно просто, но, как вы видите, могут возникнуть условия, когда код языка изменяется, недоступен или даже недействителен. Самое главное - убедиться, что g.lang_code всегда установлен в допустимый язык перед вызовом localeselector() и url_defaults(). Ниже рассматривается ряд условий.

Flask Многоязычная обработка: переключение посетителя на другой язык

Для переключения на другой язык мы можем использовать GET для текущего запроса с дополнительным параметром lang_code:

<a href="{{ request.script_root  +  request.path }}?lc=en">English</a>
<a href="{{ request.script_root  +  request.path }}?lc=de">Deutsch</a>

Мы должны расширить функциональность url_value_preprocessor() для поддержки языкового переключателя. Упрощенно, этот дополнительный код выглядит так:

@pages_blueprint.url_value_preprocessor
def pull_lang_code(endpoint, values):
    ...
    request_lang_code = request.args.get('lc')
    if request_lang_code:
        g.lang_code = request_lang_code
    ...

Flask Многоязыковая обработка: отсутствует язык в url и языке по умолчанию

Это не может быть ошибкой, потому что вы можете захотеть, чтобы vistor напечатал ваш URL домена и был "перенаправлен" на страницы языка по умолчанию. Но это также может случиться, если посетитель набирает неправильный URL, (поисковый) бот набирает неправильный URL. Опять же мы можем справиться с этим в url_value_preprocessor(). В этом случае мы устанавливаем значение lang_code на lang_code языка по умолчанию:

@pages_blueprint.url_value_preprocessor
def pull_lang_code(endpoint, values):
    ...
    if g.get('lang_code') is  None:
        g.lang_code = default_lang_code

Flask Многоязыковая обработка: язык не поддерживается

Наше приложение поддерживает только ограниченное количество языков, например

    available_lang_codes = ['en', 'de']

Опять же мы можем обработать некорректный языковой регистр в url_value_preprocessor(). Если язык недействителен, мы устанавливаем для Lang_code значение lang_code языка по умолчанию:

@pages_blueprint.url_value_preprocessor
def pull_lang_code(endpoint, values):
    ...
    if 'lang_code' in values:
        lang_code = values.pop('lang_code')
        if lang_code not in available_lang_codes:
            g.lang_code = default_lang_code

Flask Многоязычная обработка: Страница Не найдена (404) Ошибка

Это вызвало у меня головные боли, потребовалось немного отладки, чтобы понять, что в этом случае поток отличается. Здесь происходит следующее: если ни один из blueprints не соответствует запросу url, вызов url_value_preprocessor() НИКОГДА не выполняется. Например, с blueprints , показанным ранее, это действительный url:

http://127.0.0.1:8000/en/auth/login

но этот урна дает 404 исключения:

http://127.0.0.1:8000/en/auth/login/something

Что здесь делать? Ответ заключается в обработке этого условия в Flask _@before_request. При нормальном потоке до запроса() вызывается после (!) url_value_preprocessor():

    @pages_blueprint.url_value_preprocessor
    def pull_lang_code(endpoint, values):
        ....

    @app.before_request
    def before_request():
        ....

В случае исключения 404 вызов функции url_value_preprocessor() НЕ выполняется, а выполняется до вызова функции_request():

    @app.before_request
    def before_request():
        ....

Обычно url_value_preprocessor() устанавливает g.lang_code в значение, языковой код. Но на 404 функция url_value_preprocessor() не вызывается и g.lang_code не задается. В функции before_request() мы проверяем значение g.lang_code. Если он не установлен, мы можем обработать запрос url самостоятельно. Если первая часть является правильным кодом языка, мы предполагаем, что это то, что нам нужно, и устанавливаем g.lang_code. В противном случае мы установим g.lang_code на язык по умолчанию. Затем, когда вызывается обработчик 404, страница может быть отображена на нужном языке.

Резюме

Я не использовал переменную сессии для хранения выбранного языка, а полагался на язык в url. Это прекрасно работает, если мы работаем со всеми типами условий, таких как отсутствие языка. Наиболее важным является установка языка в g перед выполнением любой другой обработки.

Ссылки / кредиты

Flask Series: Internationalization
https://damyanon.net/post/flask-series-internationalization/

Flask-Babel
https://pythonhosted.org/Flask-Babel/

Using URL Processors
https://flask.palletsprojects.com/en/1.1.x/patterns/urlprocessors/

Оставить комментарий

Комментируйте анонимно или войдите в систему, чтобы прокомментировать.

Комментарии

Оставьте ответ

Ответьте анонимно или войдите в систему, чтобы ответить.