3 horizontal lines, burger
3 horizontal lines, burger
3 horizontal lines, burger
3 horizontal lines, burger

3 horizontal lines, burger
Remove all
LOADING ...

Content



    How to localize a Django website. Namely python, and js scripts, and django templates

    Clock
    06.02.2025
    /
    Clock
    07.04.2026
    /
    Clock
    10 minutes
    An eye
    4726
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0

    Introduction. How it works

    In this article, I'll describe the process and possible areas of translation in Django. The process of translating HTML files and Python scripts is very different from, say, translating JS files.
    When localizing, you also need to understand how exactly you want to display a different language version. A good idea is to display this directly in the URL. There are several options:
    1. Create a separate website with a corresponding domain. Like example.de. This is too expensive and impractical.
    2. Add a subdomain. Like ru.example.com
    3. Add a directory. Like example.com/en/
    4. Or use the URL parameter example.com?loc=en
    Each of these options has its pros and cons. And I'm not the one in the right place to talk about them. Everything is described in detail here on Google's blog. I've only tried the directory option because... well, I have a single server and a limited budget. Therefore, in this article, you'll find this method of displaying translations. In any case, translating a Django website can be divided into four tasks: translating strings in Python code, translating Django models, translating strings in templates, and translating strings in JavaScript code.
    The process itself can be divided into the following stages:
    1. Marking all the strings to translate
    2. Collecting all the marked strings
    3. Filling up the translations strings
    4. Compilation of a special *.mo files
    These steps are not applicable to translating and localizing Django models. They have their own specific requirements.
    But before you start translating, you need to fine-tune your website. There's no other way.

    Basic setup

    First, let's enable the appropriate middleware. Its main role is to redirect to the appropriate localized pages and insert the translation strings needed for the site's current locale.
    In the settings.py file:
    MIDDLEWARE = [ ... 'django.middleware.locale.LocaleMiddleware', .... ]
    You also need to record the default language code, which is also the current language, and prepare a list of supported localizations (translations) for the site. Also, add the USE_I18N global variable. This last point is optional; it's enabled by default, but I just like to have everything explicitly configured.
    LANGUAGE_CODE = 'en' USE_I18N = True LANGUAGES = [ ('en', 'English'), ('ru', 'Russian'), ('de', 'German'), ('es', 'Spanish') ]
    The final step is specifying the localizable routes. In this case, it doesn't make sense to localize all the api or admin paths, and especially not the allauth paths. These are the ones that will remain untouched. In other words, we'll localize our frontend. These are the about, contacts, homepage, email confirmation, and password reset pages.
    Add the following lines to the urls.py file:
    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')), )
    By the way, the i18n_patterns function can only be used in the main urls.py file. That's it.
    Preliminary setup is complete.

    Website Localization Step by Step

    All subsequent subchapters will describe the website localization process, from collecting strings for translation to compiling them.

    Selecting Strings for Translation

    We need to specify what actually needs to be translated, and for each part of the website, be it a template, Python code, or JavaScript code, this will be different.

    Translations in Python Code

    To mark strings for translation, you need to import the following functions: gettext and gettext_lazy.
    from django.utils.translation import gettext as _ from django.utils.translation import gettext_lazy as __ ###
    Next, you simply need to wrap the string you need in gettext or gettext_lazy. Note that not every string can be wrapped in a gettext function. For example, variables or calculated values. For example:
    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))
    In this example, Django will only detect the first string, "Usual string." It will ignore all the others.
    I also imported the gettext_lazy function. What's special about it, and when should I use it? Generally speaking, the only difference between the two is that the latter takes a string from the *.po file only when that string is used on the server. At least that's what the official Django website says.
    This function (gettext_lazy) is worth using when translating Django models and their attributes, as well as descriptions for the admin panel. But in 90% of cases, gettext will suffice. Plus, as I noted earlier, making models international requires more than Django's built-in utilities.

    Translations in Templates

    To translate text in templates, you only need to know three tags:
    {% 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 %}
    At the beginning of your template, you'll need to load a special module, i18n. Every time you need to translate text in your template, load the module, even if this template inherits from another template that already has i18n loaded.
    After the i18n module has been loaded, you have two options:
    1. The first is to use single-line translation.
    2. The second is to use multi-line translation.
    The difference between them is that in the second case, everything between the tags will be translated, including other tags. Stay tuned.

    Translations in JS files

    Setting up JavaScript code translations is probably the most difficult and tedious part. Although at first glance, it seems like there's a tutorial and nothing out of the ordinary is required. But more on that later. Let me first show you how to set up JS translations via Django.
    The first thing you need to do is include the appropriate paths in urls.py. Moreover, I would like to point out that if you use the i18n_patterns function, you need to include the JavaScriptCatalog class there.
    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')), )
    The JavaScriptCatalog class will generate a mini-JS library for us with a catalog of translation strings. Yes, this will slow down page loading speed somewhat, so we'll need to remember to cache it in the future. Now let's include this script.
    <script src="/en/jsi18n/"></script>
    The translation backend is now configured. Now we need to mark the strings we want to translate. So, we only need the gettext() function, which is defined in the JS file we included earlier. For example, like this:
    email = 'some@mail.com' gettext(`Successfully send an email to ${email}`)
    This is how we mark strings for translation. We simply wrap them in the appropriate gettext function.

    Collecting Strings

    After setting up translations for templates, Python, and JavaScript, we need to collect all marked strings into *.po files. First, create a locale directory in each application that contains strings for translation. If all the necessary directories (locale) for translation have been created, run the following command:
    python .\manage.py makemessages -l ru
    If you marked lines in JS, you need to run another command to collect lines from JS files. In this command, we use the -d flag with the value djangojs.
    python .\manage.py makemessages -d djangojs -l ru -i node_modules/*
    Please also use the -i or --ignore flag. Look, I'm using Node.js and ReactJS. They're all in the node_modules directory, and there are actually more. If you don't use this flag, Django will reliably check every JS file in your project, and there will be tens of thousands of them.

    Translations, how to fill them in

    These two commands will result in the files django.po from the first command and djangojs.po from the second command. They will contain lines like this, for example:
    #: .\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" " "
    You'll need to fill in everything in the "" after the msgstr. Don't touch anything inside the msgid, that's the first thing. And second, when translating multi-line elements (those starting with "\n") after the msgid, the msgstr must also start with "\n."
    In any case, if there are any errors during compilation, they're very informative, and you won't have any problems fixing them yourself. Speaking of compilation,

    Compiling Translations

    The final step in translating is compiling them into *.mo files. To compile translations, regardless of whether they're templates, Python, or JS code, use the following command:
    python .\manage.py compilemessages
    Congratulations! We've finished translating our website, and it can now support many other languages, regardless of which strings are located or where. However, if you're not satisfied with the quality of your JS file translations, or if you're having trouble translating your React JS files—it simply can't find them—then continue reading the next chapter about translating JS strings using the i18next React module.

    Translating JS files using the i18next framework

    Unlike translating JS files using Django, setting up React for this is much more complicated. But it guarantees that all the necessary strings will be found. Let's install the necessary packages first:
    npm install i18next-http-backend i18next-browser-languagedetector react-i18next i18next-parser i18next --save
    Let's take a look at each package we installed:
    1. i18next - the core functionality for translations
    2. react-i18next - the link between React and i18next
    3. i18next-browser-languagedetector - allows you to detect the user's current browser language and change it
    4. i18next-http-backend - delivers translations to the end client
    5. i18next-parser - collects all the strings for translation
    Now all this needs to be configured. Let's start with the parser. Create a file called i18next-parser.config.js in the Frontend directory, which is where your node_modules directory is. Then paste the following content.
    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, }
    Compared to the original, I changed a lot.
    1. First, I changed the lexer, lexers:, for JS files.
    2. Second, I added locales, locales:, for English, Russian, German, Spanish, and French.
    3. Third, I changed the output path. I'm placing all translation files in the static directory. Why? When I host this site on the server, all static files will need to be served by that server. Accordingly, all these files will need to be moved to another location. And Django already has a built-in command for copying all static files to this location—collectstatic. That's right, including our localizations.
    4. Fourth, I set all separator values ​​to false. I did this because I don't use their translation functions, as demonstrated in their tutorial. I wrap strings and sentences in the appropriate translation function, rather than creating specific keys for each case.
    The next thing we need to do is create an i18n.js file next to index.js and insert the following content:
    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;
    In this file, we configure the i18n module. We define how we'll deliver static files to the end user (the Backend module) and how we'll detect the user's language (the LanguageDetector module). In the latter case, it's important to specify that 'path' comes first, as this is how we specify the language change.
    We import this component:
    import i18n from './i18n'; // Everything else
    Now, using one of the components as an example, I'll show you how to mark strings that need to be translated. First, import the translation function:
    import { useTranslation } from "react-i18next";
    Next, in the component function, we use the hook:
    export default function EmailVerify(){ const { t } = useTranslation(); ...
    And now, to wrap the necessary string for translation:
    <Typography>{t('To finish email verification click the button below')}</Typography> <Button onClick={()=>{onConfirmEmail(key, containerRef, t)}} variant='text'>{t('proceed')}</Button>
    As you may have noticed, I'm passing the t function further as an argument to the onConfirmEmail handler. I did this because translations are needed not only in React components but also in regular handlers and functions. I couldn't find another way to globally define a translation function, so in each function that needs translation, I define an additional parameter—the t translation handlers.
    Now, mark all your strings that need translation.
    Let's collect all the strings I've highlighted into translation files. This is why we installed the i18n-parser module. And to make future development of our website easier, we'll write a separate script for performing translations in package.json.
    { "name": "app", "version": "1.0.0", "main": "index.js", "scripts": { ... "trans": "i18next 'src/**/*.js'", ... }, ... }
    You only need to specify where and what to search using a special pattern. ** means search all folders and subfolders. *.js means search any files with the .js extension.
    Let's run the script, and it will find all the strings for translation and create all the previously specified localization files.
    You'll find all the translation files at static/locales/LOCALE/translation.json. Here's an example of a generated localization file for Russian:
    { "Saving preset": "Сохранение пресета", "Preset name": "Имя пресета", "At least 3 character long": "Не менее 3 символов в длину", "Save": "Сохранить", "Successfully parsed a data": "Успешно спарсил данные", "Cant parse data": "Не могу спарсить данные" }
    Next, let's look at the console output and what the page looks like when translated into German.
    Using one of my sites as an example.
    As you can see from the console, we made two XMLHttpRequest (or XHR) requests to get German and English localizations. Why two and not one? That's because we specified fallbackLng: 'en' in i18n.js. This means if German localization isn't available, we'll use the default locale.
    You can also see how the LanguageDetector module triggered and detected the user's language change. That's it, the translations of the JS code to React are complete.

    Epilogue

    In this article, we've covered all the possible cases where translations might be needed. Translations in templates or Python code aren't difficult.
    While setting up and creating translations for JS code is also easy, keep in mind that it works well with vanilla JS. Other translations can present some challenges. For example, proper translations of React code require installing additional packages.
    Finally, I'd like to add that translation isn't a simple matter and takes a long time. And I hope I was able to make your work with them at least a little easier.

    Do not forget to share, like and leave a comment :)

    Comments

    (0)

    captcha
    Send
    LOADING ...
    It's empty now. Be the first (o゚v゚)ノ

    Other

    Similar articles


    Simple and basic Django project. How to init and what to use

    Clock
    19.07.2024
    /
    Clock
    11.03.2026
    An eye
    487
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0
    How to create an empty or very simple Django project using a virtual environment and then run a test server as a result

    Interactive web development tutorial on website | Series SearchResultParser p. 3

    Clock
    29.08.2024
    /
    Clock
    11.03.2026
    An eye
    478
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0
    In this article you will understand how to add a web tutorial on a website for guests using React components. With the ability to define to which elements hints will …

    How to add translations(localisation) for your telegram bot in aiogram/python + i18n

    Clock
    14.01.2025
    /
    Clock
    11.03.2026
    An eye
    3800
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0
    In this article, I will show you how to make translations(localisation) for telegram bots made in aiogram/python. And I will do it using the Babel (+ i18n) package. You will …

    How to deploy a Django website on reg.ru

    Clock
    16.03.2025
    /
    Clock
    15.04.2026
    An eye
    2952
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    1
    How to deploy a django website on a reg.ru with database configuration, plus setup for a HTTPS redirects and configuration of a nginx, gunicorn and dns

    Used termins


    Related questions