2
0

i18n.rst 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. ====================
  2. Internationalisation
  3. ====================
  4. .. contents::
  5. :local:
  6. :depth: 3
  7. .. _multi_language_content:
  8. Multi-language content
  9. ======================
  10. .. versionadded:: 2.11
  11. Overview
  12. --------
  13. Out of the box, Wagtail assumes all content will be authored in a single language.
  14. This document describes how to configure Wagtail for authoring content in
  15. multiple languages.
  16. .. note::
  17. Wagtail provides the infrastructure for creating and serving content in multiple languages,
  18. but does not itself provide an admin interface for managing translations of the same content
  19. across different languages. For this, the `wagtail-localize <https://github.com/wagtail/wagtail-localize>`_
  20. app must be installed separately.
  21. This document only covers the internationalisation of content managed by Wagtail.
  22. For information on how to translate static content in template files, JavaScript
  23. code, etc, refer to the `Django internationalisation docs <https://docs.djangoproject.com/en/3.1/topics/i18n/translation/>`_.
  24. Or, if you are building a headless site, refer to the docs of the frontend framework you are using.
  25. Wagtail's approach to multi-lingual content
  26. -------------------------------------------
  27. This section provides an explanation of Wagtail's internationalisation approach.
  28. If you're in a hurry, you can skip to `Configuration`_.
  29. In summary:
  30. - Wagtail stores content in a separate page tree for each locale
  31. - It has a built-in ``Locale`` model and all pages are linked to a ``Locale`` with the ``locale`` foreign key field
  32. - It records which pages are translations of each other using a shared UUID stored in the ``translation_key`` field
  33. - It automatically routes requests through translations of the site's homepage
  34. - It uses Django's ``i18n_patterns`` and ``LocaleMiddleware`` for language detection
  35. Page structure
  36. ^^^^^^^^^^^^^^
  37. Wagtail stores content in a separate page tree for each locale.
  38. For example, if you have two sites in two locales, then you will see four
  39. homepages at the top level of the page hierarchy in the explorer.
  40. This approach has some advantages for the editor experience as well:
  41. - There is no default language for editing, so content can be authored in any
  42. language and then translated to any other.
  43. - Translations of a page are separate pages so they can be published at
  44. different times.
  45. - Editors can be given permission to edit content in one locale and not others.
  46. How locales and translations are recorded in the database
  47. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  48. All pages (and any snippets that have translation enabled) have a ``locale`` and
  49. ``translation_key`` field:
  50. - ``locale`` is a foreign key to the ``Locale`` model
  51. - ``translation_key`` is a UUID that's used to find translations of a piece of content.
  52. Translations of the same page/snippet share the same value in this field
  53. These two fields have a 'unique together' constraint so you can't have more than
  54. one translation in the same locale.
  55. Translated homepages
  56. ^^^^^^^^^^^^^^^^^^^^
  57. When you set up a site in Wagtail, you select the site's homepage in the 'root page'
  58. field and all requests to that site's root URL will be routed to that page.
  59. Multi-lingual sites have a separate homepage for each locale that exist as siblings
  60. in the page tree. Wagtail finds the other homepages by looking for translations of
  61. the site's 'root page'.
  62. This means that to make a site available in another locale, you just need to
  63. translate and publish its homepage in that new locale.
  64. If Wagtail can't find a homepage that matches the user's language, it will fall back
  65. to the page that is selected as the 'root page' on the site record, so you can use
  66. this field to specify the default language of your site.
  67. Language detection and routing
  68. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  69. For detecting the user's language and adding a prefix to the URLs
  70. (``/en/``, ``/fr-fr/``, for example), Wagtail is designed to work with Django's
  71. builtin internationalisation utilities such as ``i18n_patterns`` and
  72. `LocaleMiddleware`. This means that Wagtail should work seamlessly with any
  73. other internationalised Django applications on your site.
  74. Locales
  75. ~~~~~~~
  76. The locales that are enabled on a site are recorded in the ``Locale`` model in
  77. ``wagtailcore``. This model has just two fields: ID and ``language_code`` which
  78. stores the `BCP-47 language tag <https://en.wikipedia.org/wiki/IETF_language_tag>`_
  79. that represents this locale.
  80. The locale records can be set up with an :ref:`optional management UI <enabling_locale_management>` or created
  81. in the shell. The possible values of the ``language_code`` field are controlled
  82. by the ``WAGTAIL_CONTENT_LANGUAGES`` setting.
  83. .. note:: Read this if you've changed ``LANGUAGE_CODE`` before enabling internationalisation
  84. On initial migration, Wagtail creates a ``Locale`` record for the language that
  85. was set in the ``LANGUAGE_CODE`` setting at the time the migration was run. All
  86. pages will be assigned to this ``Locale`` when Wagtail's internationalisation is disabled.
  87. If you have changed the ``LANGUAGE_CODE`` setting since updating to Wagtail 2.11,
  88. you will need to manually update the record in the ``Locale`` model too before
  89. enabling internationalisation, as your existing content will be assigned to the old code.
  90. Configuration
  91. -------------
  92. In this section, we will go through the minimum configuration required to enable
  93. content to be authored in multiple languages.
  94. .. contents::
  95. :local:
  96. :depth: 1
  97. .. _enabling_internationalisation:
  98. Enabling internationalisation
  99. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  100. To enable internationalisation in both Django and Wagtail, set the following
  101. settings to ``True``:
  102. .. code-block:: python
  103. # my_project/settings.py
  104. USE_I18N = True
  105. WAGTAIL_I18N_ENABLED = True
  106. In addition, you might also want to enable Django's localisation support. This
  107. will make dates and numbers display in the user's local format:
  108. .. code-block:: python
  109. # my_project/settings.py
  110. USE_L10N = True
  111. Configuring available languages
  112. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  113. Next we need to configure the available languages. There are two settings
  114. for this that are each used for different purposes:
  115. - ``LANGUAGES`` - This sets which languages are available on the frontend of the site.
  116. - ``WAGTAIL_CONTENT_LANGUAGES`` - This sets which the languages Wagtail content
  117. can be authored in.
  118. You can set both of these settings to the exact same value. For example, to
  119. enable English, French, and Spanish:
  120. .. code-block:: python
  121. # my_project/settings.py
  122. WAGTAIL_CONTENT_LANGUAGES = LANGUAGES = [
  123. ('en', "English"),
  124. ('fr', "French"),
  125. ('es', "Spanish"),
  126. ]
  127. .. note::
  128. Whenever ``WAGTAIL_CONTENT_LANGUAGES`` is changed, the ``Locale`` model needs
  129. to be updated as well to match.
  130. This can either be done with a data migration or with the optional locale
  131. management UI described in the next section.
  132. You can also set these to different values. You might want to do this if you
  133. want to have some programmatic localisation (like date formatting or currency,
  134. for example) but use the same Wagtail content in multiple regions:
  135. .. code-block:: python
  136. # my_project/settings.py
  137. LANGUAGES = [
  138. ('en-GB', "English (Great Britain)"),
  139. ('en-US', "English (United States)"),
  140. ('en-CA', "English (Canada)"),
  141. ('fr-FR', "French (France)"),
  142. ('fr-CA', "French (Canada)"),
  143. ]
  144. WAGTAIL_CONTENT_LANGUAGES = [
  145. ('en-GB', "English"),
  146. ('fr-FR', "French"),
  147. ]
  148. When configured like this, the site will be available in all the different
  149. locales in the first list, but there will only be two language trees in
  150. Wagtail.
  151. All the ``en-`` locales will use the "English" language tree, and the ``fr-``
  152. locales will use the "French" language tree. The differences between each locale
  153. in a language would be programmatic. For example: which date/number format to
  154. use, and what currency to display prices in.
  155. .. _enabling_locale_management:
  156. Enabling the locale management UI (optional)
  157. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  158. An optional locale management app exists to allow a Wagtail administrator to
  159. set up the locales from the Wagtail admin interface.
  160. To enable it, add ``wagtail.locales`` into ``INSTALLED_APPS``:
  161. .. code-block:: python
  162. # my_project/settings.py
  163. INSTALLED_APPS = [
  164. # ...
  165. 'wagtail.locales',
  166. # ...
  167. ]
  168. Adding a language prefix to URLs
  169. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  170. To allow all of the page trees to be served at the same domain, we need
  171. to add a URL prefix for each language.
  172. To implement this, we can use Django's built-in
  173. `i18n_patterns <https://docs.djangoproject.com/en/3.1/topics/i18n/translation/#language-prefix-in-url-patterns>`_
  174. function, which adds a language prefix to all of the URL patterns passed into it.
  175. This activates the language code specified in the URL and Wagtail takes this into
  176. account when it decides how to route the request.
  177. In your project's ``urls.py`` add Wagtail's core URLs (and any other URLs you
  178. want to be translated) into an ``i18n_patterns`` block:
  179. .. code-block:: python
  180. # /my_project/urls.py
  181. ...
  182. from django.conf.urls.i18n import i18n_patterns
  183. # Non-translatable URLs
  184. # Note: if you are using the Wagtail API or sitemaps,
  185. # these should not be added to `i18n_patterns` either
  186. urlpatterns = [
  187. path('django-admin/', admin.site.urls),
  188. path('admin/', include(wagtailadmin_urls)),
  189. path('documents/', include(wagtaildocs_urls)),
  190. ]
  191. # Translatable URLs
  192. # These will be available under a language code prefix. For example /en/search/
  193. urlpatterns += i18n_patterns(
  194. path('search/', search_views.search, name='search'),
  195. path("", include(wagtail_urls)),
  196. )
  197. User language auto-detection
  198. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  199. After wrapping your URL patterns with ``i18n_patterns``, your site will now
  200. respond on URL prefixes. But now it won't respond on the root path.
  201. To fix this, we need to detect the user's browser language and redirect them
  202. to the best language prefix. The recommended approach to do this is with
  203. Django's ``LocaleMiddleware``:
  204. .. code-block:: python
  205. # my_project/settings.py
  206. MIDDLEWARE = [
  207. # ...
  208. 'django.middleware.locale.LocaleMiddleware',
  209. # ...
  210. ]
  211. Custom routing/language detection
  212. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  213. You don't strictly have to use ``i18n_patterns`` or ``LocaleMiddleware`` for
  214. this and you can write your own logic if you need to.
  215. All Wagtail needs is the language to be activated (using Django's
  216. ``django.utils.translation.activate`` function) before the
  217. ``wagtail.core.views.serve`` view is called.
  218. Recipes for internationalised sites
  219. -----------------------------------
  220. Language/region selector
  221. ^^^^^^^^^^^^^^^^^^^^^^^^
  222. Perhaps the most important bit of internationalisation-related UI you can add
  223. to your site is a selector to allow users to switch between different
  224. languages.
  225. If you're not convinced that you need this, have a look at https://www.w3.org/International/questions/qa-site-conneg#yyyshortcomings for some rationale.
  226. Basic example
  227. ~~~~~~~~~~~~~
  228. Here is a basic example of how to add links between translations of a page.
  229. This example, however, will only include languages defined in
  230. ``WAGTAIL_CONTENT_LANGUAGES`` and not any extra languages that might be defined
  231. in ``LANGUAGES``. For more information on what both of these settings mean, see
  232. `Configuring available languages`_.
  233. If both settings are set to the same value, this example should work well for you,
  234. otherwise skip to the next section that has a more complicated example which takes
  235. this into account.
  236. .. code-block:: html+Django
  237. {# make sure these are at the top of the file #}
  238. {% load i18n wagtailcore_tags %}
  239. {% if page %}
  240. {% for translation in page.get_translations.live %}
  241. {% get_language_info for translation.locale.language_code as lang %}
  242. <a href="{% pageurl translation %}" rel="alternate" hreflang="{{ language_code }}">
  243. {{ lang.name_local }}
  244. </a>
  245. {% endfor %}
  246. {% endif %}
  247. Let's break this down:
  248. .. code-block:: html+Django
  249. {% if page %}
  250. ...
  251. {% endif %}
  252. If this is part of a shared base template it may be used in situations where no page object is available, such as 404 error responses, so check that we have a page before proceeding.
  253. .. code-block:: html+Django
  254. {% for translation in page.get_translations.live %}
  255. ...
  256. {% endfor %}
  257. This ``for`` block iterates through all published translations of the current page.
  258. .. code-block:: html+Django
  259. {% get_language_info for translation.locale.language_code as lang %}
  260. This is a Django built-in tag that gets info about the language of the translation.
  261. For more information, see `get_language_info() in the Django docs <https://docs.djangoproject.com/en/3.1/topics/i18n/translation/#django.utils.translation.get_language_info>`_.
  262. .. code-block:: html+Django
  263. <a href="{% pageurl translation %}" rel="alternate" hreflang="{{ language_code }}">
  264. {{ lang.name_local }}
  265. </a>
  266. This adds a link to the translation. We use ``{{ lang.name_local }}`` to display
  267. the name of the locale in its own language. We also add ``rel`` and ``hreflang``
  268. attributes to the ``<a>`` tag for SEO.
  269. Handling locales that share content
  270. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  271. Rather than iterating over pages, this example iterates over all of the configured
  272. languages and finds the page for each one. This works better than the `Basic example`_
  273. above on sites that have extra Django ``LANGUAGES`` that share the same Wagtail content.
  274. For this example to work, you firstly need to add Django's
  275. `django.template.context_processors.i18n <https://docs.djangoproject.com/en/3.1/ref/templates/api/#django-template-context-processors-i18n>`_
  276. context processor to your ``TEMPLATES`` setting:
  277. .. code-block:: python
  278. # myproject/settings.py
  279. TEMPLATES = [
  280. {
  281. # ...
  282. 'OPTIONS': {
  283. 'context_processors': [
  284. # ...
  285. 'django.template.context_processors.i18n',
  286. ],
  287. },
  288. },
  289. ]
  290. Now for the example itself:
  291. .. code-block:: html+Django
  292. {% for language_code, language_name in LANGUAGES %}
  293. {% get_language_info for language_code as lang %}
  294. {% language language_code %}
  295. <a href="{% pageurl page.localized %}" rel="alternate" hreflang="{{ language_code }}">
  296. {{ lang.name_local }}
  297. </a>
  298. {% endlanguage %}
  299. {% endfor %}
  300. Let's break this down too:
  301. .. code-block:: html+Django
  302. {% for language_code, language_name in LANGUAGES %}
  303. ...
  304. {% endfor %}
  305. This ``for`` block iterates through all of the configured languages on the site.
  306. The ``LANGUAGES`` variable comes from the ``django.template.context_processors.i18n``
  307. context processor.
  308. .. code-block:: html+Django
  309. {% get_language_info for language_code as lang %}
  310. Does exactly the same as the previous example.
  311. .. code-block:: html+Django
  312. {% language language_code %}
  313. ...
  314. {% endlanguage %}
  315. This ``language`` tag comes from Django's ``i18n`` tag library. It changes the
  316. active language for just the code contained within it.
  317. .. code-block:: html+Django
  318. <a href="{% pageurl page.localized %}" rel="alternate" hreflang="{{ language_code }}">
  319. {{ lang.name_local }}
  320. </a>
  321. The only difference with the ``<a>`` tag here from the ``<a>`` tag in the previous example
  322. is how we're getting the page's URL: ``{% pageurl page.localized %}``.
  323. All page instances in Wagtail have a ``.localized`` attribute which fetches the translation
  324. of the page in the current active language. This is why we activated the language previously.
  325. Another difference here is that if the same translated page is shared in two locales, Wagtail
  326. will generate the correct URL for the page based on the current active locale. This is the
  327. key difference between this example and the previous one as the previous one can only get the
  328. URL of the page in its default locale.
  329. API filters for headless sites
  330. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  331. For headless sites, the Wagtail API supports two extra filters for internationalised sites:
  332. - ``?locale=`` Filters pages by the given locale
  333. - ``?translation_of=`` Filters pages to only include translations of the given page ID
  334. For more information, see :ref:`apiv2_i18n_filters`.
  335. Translatable snippets
  336. ^^^^^^^^^^^^^^^^^^^^^
  337. You can make a snippet translatable by making it inherit from ``wagtail.core.models.TranslatableMixin``.
  338. For example:
  339. .. code-block:: python
  340. # myapp/models.py
  341. from django.db import models
  342. from wagtail.core.models import TranslatableMixin
  343. from wagtail.snippets.models import register_snippet
  344. @register_snippet
  345. class Advert(TranslatableMixin, models.Model):
  346. name = models.CharField(max_length=255)
  347. The ``TranslatableMixin`` model adds the ``locale`` and ``translation_key`` fields to the model.
  348. Making snippets with existing data translatable
  349. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  350. For snippets with existing data, it's not possible to just add ``TranslatableMixin``,
  351. make a migration, and run it. This is because the ``locale`` and ``translation_key``
  352. fields are both required and ``translation_key`` needs a unique value for each
  353. instance.
  354. To migrate the existing data properly, we firstly need to use ``BootstrapTranslatableMixin``,
  355. which excludes these constraints, then add a data migration to set the two fields, then
  356. switch to ``TranslatableMixin``.
  357. This is only needed if there are records in the database. So if the model is empty, you can
  358. go straight to adding ``TranslatableMixin`` and skip this.
  359. Step 1: Add ``BootstrapTranslatableMixin`` to the model
  360. *******************************************************
  361. This will add the two fields without any constraints:
  362. .. code-block:: python
  363. # myapp/models.py
  364. from django.db import models
  365. from wagtail.core.models import BootstrapTranslatableMixin
  366. from wagtail.snippets.models import register_snippet
  367. @register_snippet
  368. class Advert(BootstrapTranslatableMixin, models.Model):
  369. name = models.CharField(max_length=255)
  370. # if the model has a Meta class, ensure it inherits from
  371. # BootstrapTranslatableMixin.Meta too
  372. class Meta(BootstrapTranslatableMixin.Meta):
  373. verbose_name = 'adverts'
  374. Run ``python manage.py makemigrations myapp`` to generate the schema migration.
  375. Step 2: Create a data migration
  376. *******************************
  377. Create a data migration with the following command:
  378. .. code-block:: bash
  379. python manage.py makemigrations myapp --empty
  380. This will generate a new empty migration in the app's ``migrations`` folder. Edit
  381. that migration and add a ``BootstrapTranslatableModel`` for each model to bootstrap
  382. in that app:
  383. .. code-block:: python
  384. from django.db import migrations
  385. from wagtail.core.models import BootstrapTranslatableModel
  386. class Migration(migrations.Migration):
  387. dependencies = [
  388. ('myapp', '0002_bootstraptranslations'),
  389. ]
  390. # Add one operation for each model to bootstrap here
  391. # Note: Only include models that are in the same app!
  392. operations = [
  393. BootstrapTranslatableModel('myapp.Advert'),
  394. ]
  395. Repeat this for any other apps that contain a model to be bootstrapped.
  396. Step 3: Change ``BootstrapTranslatableMixin`` to ``TranslatableMixin``
  397. **********************************************************************
  398. Now that we have a migration that fills in the required fields, we can swap out
  399. ``BootstrapTranslatableMixin`` for ``TranslatableMixin`` that has all the
  400. constraints:
  401. .. code-block:: python
  402. # myapp/models.py
  403. from wagtail.core.models import TranslatableMixin # Change this line
  404. @register_snippet
  405. class Advert(TranslatableMixin, models.Model): # Change this line
  406. name = models.CharField(max_length=255)
  407. class Meta(TranslatableMixin.Meta): # Change this line, if present
  408. verbose_name = 'adverts'
  409. Step 4: Run ``makemigrations`` to generate schema migrations, then migrate!
  410. ***************************************************************************
  411. Run ``makemigrations`` to generate the schema migration that adds the
  412. constraints into the database, then run ``migrate`` to run all of the
  413. migrations:
  414. .. code-block:: bash
  415. python manage.py makemigrations myapp
  416. python manage.py migrate
  417. When prompted to select a fix for the nullable field 'locale' being changed to
  418. non-nullable, select the option "Ignore for now" (as this has been handled by the
  419. data migration).
  420. Translation workflow
  421. --------------------
  422. As mentioned at the beginning, Wagtail does not supply any built-in user interface
  423. or external integration that provides a translation workflow. This has been left
  424. for third-party packages to solve.
  425. Wagtail Localize
  426. ^^^^^^^^^^^^^^^^
  427. As part of the initial work on implementing internationalisation for Wagtail core,
  428. we also created a translation package called ``wagtail-localize``. This supports
  429. translating pages within Wagtail, using PO files, machine translation, and external
  430. integration with translation services.
  431. Github: https://github.com/wagtail/wagtail-localize
  432. Alternative internationalisation plugins
  433. ========================================
  434. Before official multi-language support was added into Wagtail, site implementors
  435. had to use external plugins. These have not been replaced by Wagtail's own
  436. implementation as they use slightly different approaches, one of them might
  437. fit your use case better:
  438. - `Wagtailtrans <https://github.com/wagtail/wagtailtrans>`_
  439. - `wagtail-modeltranslation <https://github.com/infoportugal/wagtail-modeltranslation>`_
  440. For a comparison of these options, see AccordBox's blog post
  441. `How to support multi-language in Wagtail CMS <https://www.accordbox.com/blog/how-support-multi-language-wagtail-cms/>`_.
  442. Wagtail admin translations
  443. ==========================
  444. The Wagtail admin backend has been translated into many different languages. You can find a list of currently available translations on Wagtail's `Transifex page <https://www.transifex.com/torchbox/wagtail/>`_. (Note: if you're using an old version of Wagtail, this page may not accurately reflect what languages you have available).
  445. If your language isn't listed on that page, you can easily contribute new languages or correct mistakes. Sign up and submit changes to `Transifex <https://www.transifex.com/torchbox/wagtail/>`_. Translation updates are typically merged into an official release within one month of being submitted.
  446. Change Wagtail admin language on a per-user basis
  447. =================================================
  448. Logged-in users can set their preferred language from ``/admin/account/``.
  449. By default, Wagtail provides a list of languages that have a >= 90% translation coverage.
  450. It is possible to override this list via the :ref:`WAGTAILADMIN_PERMITTED_LANGUAGES <WAGTAILADMIN_PERMITTED_LANGUAGES>` setting.
  451. In case there is zero or one language permitted, the form will be hidden.
  452. If there is no language selected by the user, the ``LANGUAGE_CODE`` will be used.
  453. Changing the primary language of your Wagtail installation
  454. ==========================================================
  455. The default language of Wagtail is ``en-us`` (American English). You can change this by tweaking a couple of Django settings:
  456. - Make sure `USE_I18N <https://docs.djangoproject.com/en/stable/ref/settings/#use-i18n>`_ is set to ``True``
  457. - Set `LANGUAGE_CODE <https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-LANGUAGE_CODE>`_ to your websites' primary language
  458. If there is a translation available for your language, the Wagtail admin backend should now be in the language you've chosen.