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

Добавление ссылок url_for() в Jinja шаблоны Flask многоязычного веб-сайта

На мультиязычном веб-сайте с мультиязычными пробками мы больше не можем использовать <a href="{{ url_for('pages.about') }}">{{ _('About') }}</a>.

15 сентября 2019
post main image
unsplash.com/@andrewtneel
Прежде чем читать дальше, вы можете прочитать мои предыдущие сообщения о многоязычии и языковой падеже, см. ссылки ниже. Когда я дал себе задание разработать и внедрить мультиязычный веб-сайт, SQLAlchemy я знал, что это может быть трудно. На самом деле, я не тратил время на разработку всего заранее, я просто много читал о мультиязыке в Интернете и доверял своему опыту при написании кода, который можно было бы расширить без особых усилий. Тем не менее, иногда вы можете быть настолько вовлечены в работу с кодом, что забываете простые вещи.

Проблема: url_for() в Jinja шаблонах

На страницах blueprint view.py я определил конечные точки для контакта, об условиях использования и политике конфиденциальности:
@pages_blueprint.route('/contact')
def contact():
    return page_view('contact')


@pages_blueprint.route('/about')
def about():
    return page_view('about')

@pages_blueprint.route('/terms-of-use')
def terms_of_use():
    return page_view('terms-of-use')


@pages_blueprint.route('/privacy-policy')
def privacy_policy():
    return page_view('privacy-policy')

Я удалил эти строки, поэтому единственной оставшейся конечной точкой для страниц будет функция page_view:

@pages_blueprint.route('/<slug>', methods=['GET', 'POST'])
def page_view(slug):
    ...

Потом страницы перестали работать... конечно. В некоторых местах в шаблонах я все еще использовал url_for() для генерации ссылки на страницу. Например, параметр "Подробнее" по-прежнему указывался как "Read More":

<a href="{{ url_for('pages.about') }}">{{ _('Read more') }}</a>

А на странице Регистрация была ссылка:

* {{ _('See our') }} <a href="{{ url_for('pages.privacy_policy') }}" class="link">{{ _('privacy policy') }}</a> {{ _('how we process and protect your personal data.') }}

Оба потерпели неудачу со знаменитостями:

werkzeug.routing.BuildError: Could not build url for endpoint ...

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

Решение: вложенный диктат для каждого выбранного языка

Как я уже говорил в предыдущих статьях, у нас есть две таблицы:

Содержание
Перевод содержания

ContentItem содержит "общее" имя. Например, страница About имеет общее название 'About', а записи ContentItemTranslation содержат заголовок переведенной страницы, для голландского языка это 'Over ons', а производный слизняк - over-ons', для того чтобы обеспечить функцию url_for() необходимыми данными, нам нужно создать словарь со следующей структурой:

{
    'About': { 'title': title, 'slug': slug },
    'Privacy policy': { 'title': title, 'slug': slug },
    ... 
}

Затем нам нужен контекстный процессор для ввода словаря в шаблон, здесь в качестве имени словаря я использую app_template_slug. В Jinja шаблоне мы можем использовать это следующим образом:

* {{ _('See our') }} <a href="{{ url_for('pages.page_view', slug=app_template_slug['Privacy policy']['slug']) }}" class="link">{{ app_template_slug['Privacy policy']['title'] }}</a> {{ _('how we process and protect your personal data.') }}

Мы используем "общее" имя, чтобы получить правильное название и слизняк, поэтому здесь нет зависимости от языка. Как и в случае с другими функциями, я создал объект, который заботится о генерации вложенного словаря в функции create_app.

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

Multilanguage fallback revisited and a page footer with multilanguage links
/en/blog/multilanguage-fallback-revisited-and-a-page-footer-with-multilanguage-links

Refining multilanguage: adding language fallback as an option
/en/blog/refining-multilanguage-adding-language-fallback-as-an-option

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

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

Комментарии

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

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