3 горизонтальные линии, бургер
3 горизонтальные линии, бургер
3 горизонтальные линии, бургер
3 горизонтальные линии, бургер

3 горизонтальные линии, бургер
Удалить все
ЗАГРУЗКА ...

Содержание



    Как локализовать Django сайт. А именно python, и js скрипты, и django шаблоны

    Часы
    06.02.2025
    /
    Часы
    07.04.2026
    /
    Часы
    9 минут
    Глазик
    6778
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    Соединённые точки
    0

    Вступлени. Как это вообще работает

    В этой статье я опишу процесс и возможные области переводов на Django. Так процесс переводов HTML файлов и Python скриптов сильно отличается от того же перевода JS файлов.
    Так же при локализации надо понимать, как именно ты хочешь показать другую версию языка. И хорошей идеей будет отобразить это непосредственно в URL. Есть варианты:
    1. Создать отдельный сайт с соответствующим доменом. По типу example.de. Это слишком дорого и не практично.
    2. Добавить поддомен. По типу ru.example.com
    3. Добавить директорию. По типу example.com/en/
    4. Или использовать URL параметр example.com?loc=en
    У каждого из этих вариантов есть свои плюсы и минусы. И я не из тех, кто может говорить об этом. Всё довольно подробно описано здесь, в блоге гугла. Я опробовал только вариант с директориями, ибо ... ну, у меня один сервер и ограниченный бюджет. Поэтому в этой статье вы найдёте именно этот способ отображения переводов.
    В любом случае перевод сайта на django можно разделить на 4 условные задачи. Это перевод строк в python коде, перевод django-моделей, перевод строк в шаблонах и перевод строк в javascript коде.
    И сам процесс можно разделить на следующие этапы:
    1. Помечаем(выделяем) необходимые строки для перевода.
    2. Собираем все помеченные(выделенные) строки.
    3. Пишем переводы для них
    4. Компилируем специальный *.mo файл
    Данные этапы не применимы при переводе и локализации django-моделей. У них своя специфика.
    Но перед тем, как начать переводить необходимо донастроить свой сайт. Без этого никак.

    Базовая настройка

    В первую очередь подключим соответствующий мидлвари. Его основная роль это редиректы на соответствующие локализованные страницы и вставка тех строк перевода, которые нужны для текущей локали сайта.
    В файле settings.py:
    MIDDLEWARE = [ ... 'django.middleware.locale.LocaleMiddleware', .... ]
    Ещё нужно записать код языка по умолчанию, он же текущий, и подготовить список поддерживаемых локализаций(переводов) сайта. Так же добавь глобальную переменную USE_I18N. Последний пункт не обязателен, он включён по умолчанию, но я просто люблю чтобы всё было явно настроено.
    LANGUAGE_CODE = 'en' USE_I18N = True LANGUAGES = [ ('en', 'English'), ('ru', 'Russian'), ('de', 'German'), ('es', 'Spanish') ]
    Последним штрихом будет, указание локализуемых маршрутов. В данном случае, не имеет смысла локализовывать все api или admin пути, ну и уж тем более allauth пути. Это то, что останется не тронутым. То есть, будем локализовывать наш фронтенд. Это страницы about, contacts, главная и страницы подтверждения почты и сброса пароля.
    В файле Website/urls.py добавь следующие строчки:
    from django.urls import path, include from django.conf.urls.i18n import i18n_patterns urlpatterns += i18n_patterns( path('', include('Authentication.urls')), path('', include('Frontend.urls')), )
    Кстати, функцию i18n_patterns можно использовать только в главном urls.py. Такие дела.
    Предварительная настройка завершена.

    Локализация сайта по этапам

    Все дальнейшие подглавы будут описывать процесс локализации сайта. Начиная от сбора строчек для перевода заканчивая их компиляцией.

    Выделяем строчки для перевода

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

    Переводы в python коде

    Для того чтобы пометить строчки для перевода, необходимо импортировать следующие функции: gettext и gettext_lazy.
    from django.utils.translation import gettext as _ from django.utils.translation import gettext_lazy as __ ###
    Дальше, нужно просто обернуть нужную тебе строчку в gettext или gettext_lazy. Сразу замечу, не вокруг каждой строки возможно обернуть функцию gettext. Например, переменной или вычисляемым значениям. То есть, например:
    def translation_test(): str = _("Usual string") var_for_str1 = "Variable for str1" str1 = _(var_for_str1) list_for_str2 = ['Variable', 'for', 'str2'] str2 = _("-".join(list_for_str2))
    В данном примере, django сможет обнаружить только первую строку "Usual string". Все остальные он проигнорирует.
    Я так же сделал импорт такой функции как gettext_lazy. В чём его особенность и когда его применять? В общем и целом единственное отличие их друг от друга состоит в том, что второй берёт строку из *.po файла, только тогда, когда эта строка используется на сервере. Так по крайней мере написано на официальном сайте django.
    Эту функцию (gettext_lazy) стоит применять, при необходимости перевода django моделей и его аттрибутов, описаний для админки. Но в 90% случаев, gettext вам хватит. Плюс, как я заметил раньше, чтобы сделать модели интернациональными, потребуется нечто большее чем встроенные утилиты django.

    Переводы в шаблонах

    Для перевода текста в шаблонах тебе нужно знать только три тега:
    {% load i18n %} {% trans "YOUR TRANSLATION STRING" %} {% blocktrans %} Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis hendrerit arcu, vitae lacinia arcu. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. {% endblocktrans %}
    В начале шаблона тебе нужно будет загрузить специальный модуль, i18n. Каждый раз, когда тебе будет нужно перевести некий текст в шаблоне, загружай модуль. Даже если этот шаблон наследуется от другого шаблона, который уже загрузил i18n.
    После того как модуль i18n был загружен. У тебя есть два варианта:
    1. Первый это использовать однострочный перевод.
    2. Второй использовать многострочный перевод.
    Разница между ними такова, что во втором случае между тегами всё попадёт под перевод, в том числе и другие теги. Будь в курсе.

    Переводы в JS файлах

    Настройка переводов javascript кода, наверное, самое сложное и муторное. Хотя на первый взгляд, вроде и туториал есть и не требуется ничего экстра ординарного. Но об этом позже. Давай я сначала покажу как настроить переводы JS через django.
    Первое, что нужно сделать это подключить соответствующие пути в urls.py. Причём замечу, если ты пользуешься функцией i18n_patterns, то и подключать JavaScriptCatalog класс нужно там.
    from django.urls import path, include from django.conf.urls.i18n import i18n_patterns from django.views.i18n import JavaScriptCatalog urlpatterns += i18n_patterns( path("jsi18n/", JavaScriptCatalog.as_view(), name="javascript-catalog"), path('', include('Authentication.urls')), path('', include('Frontend.urls')), )
    Класс JavaScriptCatalog, будет генерировать для нас мини-js библиотеку с каталогом строчек перевода. Да, это поубавит несколько скорость загрузки страницы поэтому в будущем надо будет не забыть кешировать это. Теперь подключим этот скрипт.
    <script src="/ru/jsi18n/"></script>
    Настройка бэкенда для перевода готова. Теперь нужно пометить строки, которые мы хотим перевести. Итак, нам потребуется только функция gettext(), котора определена в подключённом ранее JS-файле. Например, вот так:
    email = 'some@mail.com' gettext(`Successfully send an email to ${email}`)
    Вот таким вот образом мы помечаем строки для перевода. То есть просто оборачиваем их в соответствующую функцию gettext.

    Собираем строки

    После настроек для переводов шаблонов, python и javascript, нужно собрать все отмеченные строки в файлы *.po. Предварительно создав директорию locale в каждом приложении в котором есть строки для перевода. Если все необходимые директории (locale) для переводов были созданы, нужно запустить следующую команду:
    python .\manage.py makemessages -l ru
    Если ты помечал строчки в JS, то необходимо запустить ещё одну команду для сбора строк и из JS файлов. В этой команде мы используем флаг -d со значением djangojs.
    python .\manage.py makemessages -d djangojs -l ru -i node_modules/*
    Пожалуйста, ещё используй флаг -i или --ignore. Смотри, я использую Node.js и ReactJS. Все они находятся в директории node_modules и не только они на самом деле. Если ты не поставишь данный флаг, django со всей ответственностью проверит каждый JS-файл в твоём проекте, а их будет десятки тысяч.

    Переводы, как их заполнять

    В результате этих двух команд мы получим файлы django.po - от первой команды и djangojs.po - в качестве результата второй команды. Там будут вот такие строки, например:
    #: .\Frontend\templates\Frontend\base.html:25 msgid "profile" msgstr "Profil" #: .\Frontend\templates\Frontend\base.html:39 msgid "TimTheWebmaster ➥" msgstr "TimTheWebmaster ➥" #: .\Frontend\templates\Frontend\base.html:42 msgid "" "\n" " Made by <div id=\"ref_to_place\" class=\"pl-1 pr-1\"></div> " "Copyright © 2024\n" " " msgstr "" "\n" " Erstellt von <div id=\"ref_to_place\" class=\"pl-1 pr-1\"></div> " "Copyright © 2024\n" " "
    Тебе нужно будет заполнить всё что в "" после msgstr. Ничего не трогай внутри msgid, это первое. И второе, при переводе многострочных элементов (это те которые начинаются с "\n") после msgid - msgstr так же должен начинаться с "\n".
    В любом случае, если и будут ошибки при компиляции, то они очень информативны и у тебя не будет проблем их решить самостоятельно. Кстати о компиляции.

    Компиляция переводов

    Последним этапом переводов является их компиляция в *.mo файлы. Чтобы скомпилировать переводы, вне зависимости от того переводы это шаблонов, python или js кода, используй следующую команду:
    python .\manage.py compilemessages
    Поздравляю! Мы закончили переводить наш сайт и теперь он может поддерживать множество других языков, вне зависимости, какие и где эти строчки находятся. Но если, качество переводов JS файлов тебя не устраивает, или ты столкнулся с проблемой переводов JS файлов на React, он просто их не находит, то продолжи читать следующую главу про переводы JS строк через i18next реакт модуль.

    Переводы в JS файлах, через i18next фреймворк

    В отличии перевода JS файлов через Django, настроить реакт для этого, гораздо сложнее. Но зато нахождение всех необходимых строчек гарантированно. Установим необходимы пакеты для начала:
    npm install i18next-http-backend i18next-browser-languagedetector react-i18next i18next-parser i18next --save
    Разберём каждый пакет, который установили:
    1. i18next - функциональное ядро для переводов
    2. react-i18next - связующее звено между React и i18next
    3. i18next-browser-languagedetector - позволяет определять текущий язык пользователя в браузере и его изменение
    4. i18next-http-backend - занимается тем, что доставляет переводы до конечного клиента
    5. i18next-parser - собирает все строчки для переводов
    Теперь всё это нужно будет настроить. Начнём с парсера, создай файл i18next-parser.config.js в Frontend директории, это там где у тебя node_modules директория. После вставь следующий контент.
    module.exports = { contextSeparator: '_', createOldCatalogs: false, defaultNamespace: 'translation', defaultValue: '', indentation: 2, keepRemoved: false, keySeparator: false, lexers: { hbs: ['HandlebarsLexer'], handlebars: ['HandlebarsLexer'], htm: ['HTMLLexer'], html: ['HTMLLexer'], mjs: ['JavascriptLexer'], js: ['JsxLexer'], // if you're writing jsx inside .js files, change this to JsxLexer ts: ['JavascriptLexer'], jsx: ['JsxLexer'], tsx: ['JsxLexer'], default: ['JavascriptLexer'], }, lineEnding: 'auto', locales: ['en', 'ru', 'de', 'es', 'fr'], namespaceSeparator: false, output: './static/locales/$LOCALE/$NAMESPACE.json', pluralSeparator: false, input: undefined, sort: false, verbose: false, failOnWarnings: false, failOnUpdate: false, customValueTemplate: null, resetDefaultValueLocale: null, i18nextOptions: null, yamlOptions: null, }
    Если сравнивать с оригиналом, я многое что поменял.
    1. Во-первых, поменял лексер, lexers: для JS файлов.
    2. Во-вторых добавил локали, locales:, для Английского, Русского, Белорусского, Немецкого, Испанского и Французского.
    3. В третьих, я изменил путь сохранения результатов, output. Я помещаю все файлы переводов в директорию static. Спрашивается, почему? Когда я размещу на сервере этот сайт, все статические файлы должны обслуживаться этим сервером. Соответственно, все эти файлы должны будут перемещены в другую локацию. И у джанго уже есть встроенная команда для копирования всех статических файлов в эту локацию - collectstatic. Правильно, в том числе и наши локализации.
    4. В четвёртых, я проставил все значения для сепараторов на false. Сделал я это потому, что не использую их функции переводов, как это демонстрируется в их туториале. Я оборачиваю строчки и предложения в соответствующую функцию для перевода, вместо того, чтобы придумывать некие особенные ключи для каждого случая.
    Следующее, что нам нужно сделать, это создать файл i18n.js рядом с index.js. И вставить следующий контент:
    import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import Backend from 'i18next-http-backend'; const HttpApi = new Backend(null, { loadPath: '/static/locales//.json', }); import LanguageDetector from 'i18next-browser-languagedetector'; const languageDetector = new LanguageDetector(null, { order: ['path', 'cookie', 'localStorage', 'sessionStorage', 'navigator', 'htmlTag', 'subdomain'], }); i18n .use(HttpApi) .use(languageDetector) .use(initReactI18next) .init({ debug: true, fallbackLng: 'en', }); export default i18n;
    В этом файле мы настраиваем модуль i18n. Определяем как мы будем доставлять до конечного пользователя статические файлы (Backend модуль) и как мы будем определять язык пользователя (LanguageDetector модуль). Во-втором случае важно указать, чтобы 'path' было первым, ведь именно так, мы указываем изменение языка.
    Делаем импорт данного компонента:
    import i18n from './i18n'; // Всё остальное
    Теперь на примере одного из компонентов, я покажу как пометить строчки, которые необходимо перевести. В первую очередь делаем импорт функции перевода:
    import { useTranslation } from "react-i18next";
    Дальше в функции-компонента, используем хук:
    export default function EmailVerify(){ const { t } = useTranslation(); ...
    И теперь, чтобы обернуть необходимую строку для перевода:
    <Typography>{t('To finish email verification click the button below')}</Typography> <Button onClick={()=>{onConfirmEmail(key, containerRef, t)}} variant='text'>{t('proceed')}</Button>
    Как ты мог заметить, я отправляю функцию t дальше, в качестве аргумента обработчика onConfirmEmail. Сделал я это потому, что переводы необходимы не только в реакт компонентах, но и в обычных обработчиках и функциях. Я не смог найти другой способ глобально определить функцию перевода, поэтому в каждой функции, которая нуждается в переводе я определяю дополнительный параметр - обработчики переводов t.
    А теперь пометь все свои строчки, которым требуется перевод.
    Соберём все выделенные мною строчки в файлы переводов. Для этого мы и устанавливали i18n-parser модуль. И чтобы и дальше нам было просто разрабатывать наш сайт, напишем отдельный скрипт для выполннения переводов в package.json.
    { "name": "app", "version": "1.0.0", "main": "index.js", "scripts": { ... "trans": "i18next 'src/**/*.js'", ... }, ... }
    Необходимо указать только, где и что искать используя специальный паттерн. ** - значит ищи во всех папках и подпапках. *.js - значит ищи любые файлы с расширением .js
    Запустим скрипт, и он найдёт нам и за нас все строчки для переводов и создаст все, ранее указанные, файлы локализации.
    Все файлы переводов ты найдёшь по пути static/locales/LOCALE/translation.json. И вот пример, сгенерированного файла локализации для русского языка:
    { "Saving preset": "Сохранение пресета", "Preset name": "Имя пресета", "At least 3 character long": "Не менее 3 символов в длину", "Save": "Сохранить", "Successfully parsed a data": "Успешно спарсил данные", "Cant parse data": "Не могу спарсить данные" }
    Дальше посмотрим на вывод в консоль и то как выглядит страница при переводе на немецкий язык.
    На примере одного из моих сайтов.
    Как видно из консоли мы сделали XMLHttpRequest (или XHR) запрос два раза, чтобы получить немецкую и английскую локализацию. Почему две, а не одну? Всё потому, что мы указали в i18n.js, fallbackLng: 'en' . То есть если не удастся получить немецкую локализацию, мы будем использовать локаль по умолчанию.
    Ещё видно, как модуль LanguageDetector сработал и заметил изменение языка пользователя. Всё, переводы JS кода на React завершены.

    Эпилог

    В этой статье мы с тобой разобрали, все возможные случаи, где нужно будет сделать перевод. Переводы в шаблонах или python коде не представляют сложность.
    Хотя настройка и создание переводов для JS кода, тоже легко, только нужно учитывать, что он хорошо работает с ванильным JS. Со всем остальным могут возникнуть некоторые трудности. Так для нормальных переводов React кода, потребуется устанавливать дополнительные пакеты.
    Ну и в заключении хочу добавить, что перевод дело не простое и долгое. И надеюсь я смог хоть немного облегчить тебе работу с ними.

    Не забудь поделиться, лайкнуть и оставить комментарий)

    Комментарии

    (0)

    captcha
    Отправить
    ЗАГРУЗКА ...
    Сейчас тут пусто. Буть первым (o゚v゚)ノ

    Другое

    Похожие статьи


    Пустой(Стартовый) проект на Django. Как сделать и что для этого нужно

    Часы
    19.07.2024
    /
    Часы
    11.03.2026
    Глазик
    564
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    О создании пустого или стартового django проекта, используя виртуальное окружение и с последующим запуском тестового сервера.

    Интерактивный туториал для сайта | Серия SearchResultParser ч. 3

    Часы
    29.08.2024
    /
    Часы
    11.03.2026
    Глазик
    733
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    В этой статье ты узнаешь как добавить туториал для новоприбывших пользователей используя React, с возможностью указывать к каким элементам относятся подсказки и количество этих подсказок, последовательно

    Как добавить переводы (выбор языка) для твоего телеграм бота telegram/aiogram/python

    Часы
    14.01.2025
    /
    Часы
    11.03.2026
    Глазик
    1921
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    В этой статье я покажу, как сделать так, чтобы английский бот писал на русском, то есть сделаю бота многоязычными на aiogram. И сделаю я это при помощи пакета Babel + …

    Как загрузить django сайт на хостинг от reg.ru

    Часы
    16.03.2025
    /
    Часы
    15.04.2026
    Глазик
    6873
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    2
    Соединённые точки
    0
    Как запустить django сайт на reg.ru с настройкай базы данных. Настроим переадресацию на HTTPS, на nginx, gunicorn, и работа с DNS

    Использованные термины


    Релевантные вопросы