mirror of
https://github.com/wagtail/wagtail.git
synced 2024-11-29 17:36:49 +01:00
680 lines
24 KiB
ReStructuredText
680 lines
24 KiB
ReStructuredText
====================
|
|
Internationalisation
|
|
====================
|
|
|
|
.. contents::
|
|
:local:
|
|
:depth: 3
|
|
|
|
.. _multi_language_content:
|
|
|
|
Multi-language content
|
|
======================
|
|
|
|
Overview
|
|
--------
|
|
|
|
Out of the box, Wagtail assumes all content will be authored in a single language.
|
|
This document describes how to configure Wagtail for authoring content in
|
|
multiple languages.
|
|
|
|
.. note::
|
|
Wagtail provides the infrastructure for creating and serving content in multiple languages.
|
|
There are two options for managing translations across different languages in the admin interface:
|
|
:ref:`wagtail.contrib.simple_translation<simple_translation>` or the more advanced `wagtail-localize <https://github.com/wagtail/wagtail-localize>`_ (third-party package).
|
|
|
|
This document only covers the internationalisation of content managed by Wagtail.
|
|
For information on how to translate static content in template files, JavaScript
|
|
code, etc, refer to the `Django internationalisation docs <https://docs.djangoproject.com/en/3.1/topics/i18n/translation/>`_.
|
|
Or, if you are building a headless site, refer to the docs of the frontend framework you are using.
|
|
|
|
Wagtail's approach to multi-lingual content
|
|
-------------------------------------------
|
|
|
|
This section provides an explanation of Wagtail's internationalisation approach.
|
|
If you're in a hurry, you can skip to `Configuration`_.
|
|
|
|
In summary:
|
|
|
|
- Wagtail stores content in a separate page tree for each locale
|
|
- It has a built-in ``Locale`` model and all pages are linked to a ``Locale`` with the ``locale`` foreign key field
|
|
- It records which pages are translations of each other using a shared UUID stored in the ``translation_key`` field
|
|
- It automatically routes requests through translations of the site's homepage
|
|
- It uses Django's ``i18n_patterns`` and ``LocaleMiddleware`` for language detection
|
|
|
|
Page structure
|
|
^^^^^^^^^^^^^^
|
|
|
|
Wagtail stores content in a separate page tree for each locale.
|
|
|
|
For example, if you have two sites in two locales, then you will see four
|
|
homepages at the top level of the page hierarchy in the explorer.
|
|
|
|
This approach has some advantages for the editor experience as well:
|
|
|
|
- There is no default language for editing, so content can be authored in any
|
|
language and then translated to any other.
|
|
- Translations of a page are separate pages so they can be published at
|
|
different times.
|
|
- Editors can be given permission to edit content in one locale and not others.
|
|
|
|
How locales and translations are recorded in the database
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
All pages (and any snippets that have translation enabled) have a ``locale`` and
|
|
``translation_key`` field:
|
|
|
|
- ``locale`` is a foreign key to the ``Locale`` model
|
|
- ``translation_key`` is a UUID that's used to find translations of a piece of content.
|
|
Translations of the same page/snippet share the same value in this field
|
|
|
|
These two fields have a 'unique together' constraint so you can't have more than
|
|
one translation in the same locale.
|
|
|
|
Translated homepages
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
When you set up a site in Wagtail, you select the site's homepage in the 'root page'
|
|
field and all requests to that site's root URL will be routed to that page.
|
|
|
|
Multi-lingual sites have a separate homepage for each locale that exist as siblings
|
|
in the page tree. Wagtail finds the other homepages by looking for translations of
|
|
the site's 'root page'.
|
|
|
|
This means that to make a site available in another locale, you just need to
|
|
translate and publish its homepage in that new locale.
|
|
|
|
If Wagtail can't find a homepage that matches the user's language, it will fall back
|
|
to the page that is selected as the 'root page' on the site record, so you can use
|
|
this field to specify the default language of your site.
|
|
|
|
Language detection and routing
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
For detecting the user's language and adding a prefix to the URLs
|
|
(``/en/``, ``/fr-fr/``, for example), Wagtail is designed to work with Django's
|
|
built-in internationalisation utilities such as ``i18n_patterns`` and
|
|
`LocaleMiddleware`. This means that Wagtail should work seamlessly with any
|
|
other internationalised Django applications on your site.
|
|
|
|
Locales
|
|
~~~~~~~
|
|
|
|
The locales that are enabled on a site are recorded in the ``Locale`` model in
|
|
``wagtailcore``. This model has just two fields: ID and ``language_code`` which
|
|
stores the `BCP-47 language tag <https://en.wikipedia.org/wiki/IETF_language_tag>`_
|
|
that represents this locale.
|
|
|
|
The locale records can be set up with an :ref:`optional management UI <enabling_locale_management>` or created
|
|
in the shell. The possible values of the ``language_code`` field are controlled
|
|
by the ``WAGTAIL_CONTENT_LANGUAGES`` setting.
|
|
|
|
.. note:: Read this if you've changed ``LANGUAGE_CODE`` before enabling internationalisation
|
|
|
|
On initial migration, Wagtail creates a ``Locale`` record for the language that
|
|
was set in the ``LANGUAGE_CODE`` setting at the time the migration was run. All
|
|
pages will be assigned to this ``Locale`` when Wagtail's internationalisation is disabled.
|
|
|
|
If you have changed the ``LANGUAGE_CODE`` setting since updating to Wagtail 2.11,
|
|
you will need to manually update the record in the ``Locale`` model too before
|
|
enabling internationalisation, as your existing content will be assigned to the old code.
|
|
|
|
Configuration
|
|
-------------
|
|
|
|
In this section, we will go through the minimum configuration required to enable
|
|
content to be authored in multiple languages.
|
|
|
|
.. contents::
|
|
:local:
|
|
:depth: 1
|
|
|
|
.. _enabling_internationalisation:
|
|
|
|
Enabling internationalisation
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
To enable internationalisation in both Django and Wagtail, set the following
|
|
settings to ``True``:
|
|
|
|
.. code-block:: python
|
|
|
|
# my_project/settings.py
|
|
|
|
USE_I18N = True
|
|
WAGTAIL_I18N_ENABLED = True
|
|
|
|
In addition, you might also want to enable Django's localisation support. This
|
|
will make dates and numbers display in the user's local format:
|
|
|
|
.. code-block:: python
|
|
|
|
# my_project/settings.py
|
|
|
|
USE_L10N = True
|
|
|
|
Configuring available languages
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Next we need to configure the available languages. There are two settings
|
|
for this that are each used for different purposes:
|
|
|
|
- ``LANGUAGES`` - This sets which languages are available on the frontend of the site.
|
|
- ``WAGTAIL_CONTENT_LANGUAGES`` - This sets which the languages Wagtail content
|
|
can be authored in.
|
|
|
|
You can set both of these settings to the exact same value. For example, to
|
|
enable English, French, and Spanish:
|
|
|
|
.. code-block:: python
|
|
|
|
# my_project/settings.py
|
|
|
|
WAGTAIL_CONTENT_LANGUAGES = LANGUAGES = [
|
|
('en', "English"),
|
|
('fr', "French"),
|
|
('es', "Spanish"),
|
|
]
|
|
|
|
.. note::
|
|
|
|
Whenever ``WAGTAIL_CONTENT_LANGUAGES`` is changed, the ``Locale`` model needs
|
|
to be updated as well to match.
|
|
|
|
This can either be done with a data migration or with the optional locale
|
|
management UI described in the next section.
|
|
|
|
You can also set these to different values. You might want to do this if you
|
|
want to have some programmatic localisation (like date formatting or currency,
|
|
for example) but use the same Wagtail content in multiple regions:
|
|
|
|
.. code-block:: python
|
|
|
|
# my_project/settings.py
|
|
|
|
LANGUAGES = [
|
|
('en-GB', "English (Great Britain)"),
|
|
('en-US', "English (United States)"),
|
|
('en-CA', "English (Canada)"),
|
|
('fr-FR', "French (France)"),
|
|
('fr-CA', "French (Canada)"),
|
|
]
|
|
|
|
WAGTAIL_CONTENT_LANGUAGES = [
|
|
('en-GB', "English"),
|
|
('fr-FR', "French"),
|
|
]
|
|
|
|
When configured like this, the site will be available in all the different
|
|
locales in the first list, but there will only be two language trees in
|
|
Wagtail.
|
|
|
|
All the ``en-`` locales will use the "English" language tree, and the ``fr-``
|
|
locales will use the "French" language tree. The differences between each locale
|
|
in a language would be programmatic. For example: which date/number format to
|
|
use, and what currency to display prices in.
|
|
|
|
.. _enabling_locale_management:
|
|
|
|
Enabling the locale management UI (optional)
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
An optional locale management app exists to allow a Wagtail administrator to
|
|
set up the locales from the Wagtail admin interface.
|
|
|
|
To enable it, add ``wagtail.locales`` into ``INSTALLED_APPS``:
|
|
|
|
.. code-block:: python
|
|
|
|
# my_project/settings.py
|
|
|
|
INSTALLED_APPS = [
|
|
# ...
|
|
'wagtail.locales',
|
|
# ...
|
|
]
|
|
|
|
Adding a language prefix to URLs
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
To allow all of the page trees to be served at the same domain, we need
|
|
to add a URL prefix for each language.
|
|
|
|
To implement this, we can use Django's built-in
|
|
`i18n_patterns <https://docs.djangoproject.com/en/3.1/topics/i18n/translation/#language-prefix-in-url-patterns>`_
|
|
function, which adds a language prefix to all of the URL patterns passed into it.
|
|
This activates the language code specified in the URL and Wagtail takes this into
|
|
account when it decides how to route the request.
|
|
|
|
In your project's ``urls.py`` add Wagtail's core URLs (and any other URLs you
|
|
want to be translated) into an ``i18n_patterns`` block:
|
|
|
|
.. code-block:: python
|
|
|
|
# /my_project/urls.py
|
|
|
|
...
|
|
|
|
from django.conf.urls.i18n import i18n_patterns
|
|
|
|
# Non-translatable URLs
|
|
# Note: if you are using the Wagtail API or sitemaps,
|
|
# these should not be added to `i18n_patterns` either
|
|
urlpatterns = [
|
|
path('django-admin/', admin.site.urls),
|
|
|
|
path('admin/', include(wagtailadmin_urls)),
|
|
path('documents/', include(wagtaildocs_urls)),
|
|
]
|
|
|
|
# Translatable URLs
|
|
# These will be available under a language code prefix. For example /en/search/
|
|
urlpatterns += i18n_patterns(
|
|
path('search/', search_views.search, name='search'),
|
|
path("", include(wagtail_urls)),
|
|
)
|
|
|
|
User language auto-detection
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
After wrapping your URL patterns with ``i18n_patterns``, your site will now
|
|
respond on URL prefixes. But now it won't respond on the root path.
|
|
|
|
To fix this, we need to detect the user's browser language and redirect them
|
|
to the best language prefix. The recommended approach to do this is with
|
|
Django's ``LocaleMiddleware``:
|
|
|
|
.. code-block:: python
|
|
|
|
# my_project/settings.py
|
|
|
|
MIDDLEWARE = [
|
|
# ...
|
|
'django.middleware.locale.LocaleMiddleware',
|
|
# ...
|
|
]
|
|
|
|
Custom routing/language detection
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
You don't strictly have to use ``i18n_patterns`` or ``LocaleMiddleware`` for
|
|
this and you can write your own logic if you need to.
|
|
|
|
All Wagtail needs is the language to be activated (using Django's
|
|
``django.utils.translation.activate`` function) before the
|
|
``wagtail.views.serve`` view is called.
|
|
|
|
Recipes for internationalised sites
|
|
-----------------------------------
|
|
|
|
Language/region selector
|
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Perhaps the most important bit of internationalisation-related UI you can add
|
|
to your site is a selector to allow users to switch between different
|
|
languages.
|
|
|
|
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.
|
|
|
|
Basic example
|
|
~~~~~~~~~~~~~
|
|
|
|
Here is a basic example of how to add links between translations of a page.
|
|
|
|
This example, however, will only include languages defined in
|
|
``WAGTAIL_CONTENT_LANGUAGES`` and not any extra languages that might be defined
|
|
in ``LANGUAGES``. For more information on what both of these settings mean, see
|
|
`Configuring available languages`_.
|
|
|
|
If both settings are set to the same value, this example should work well for you,
|
|
otherwise skip to the next section that has a more complicated example which takes
|
|
this into account.
|
|
|
|
.. code-block:: html+Django
|
|
|
|
{# make sure these are at the top of the file #}
|
|
{% load i18n wagtailcore_tags %}
|
|
|
|
{% if page %}
|
|
{% for translation in page.get_translations.live %}
|
|
{% get_language_info for translation.locale.language_code as lang %}
|
|
<a href="{% pageurl translation %}" rel="alternate" hreflang="{{ language_code }}">
|
|
{{ lang.name_local }}
|
|
</a>
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
Let's break this down:
|
|
|
|
.. code-block:: html+Django
|
|
|
|
{% if page %}
|
|
...
|
|
{% endif %}
|
|
|
|
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.
|
|
|
|
.. code-block:: html+Django
|
|
|
|
{% for translation in page.get_translations.live %}
|
|
...
|
|
{% endfor %}
|
|
|
|
This ``for`` block iterates through all published translations of the current page.
|
|
|
|
.. code-block:: html+Django
|
|
|
|
{% get_language_info for translation.locale.language_code as lang %}
|
|
|
|
This is a Django built-in tag that gets info about the language of the translation.
|
|
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>`_.
|
|
|
|
.. code-block:: html+Django
|
|
|
|
<a href="{% pageurl translation %}" rel="alternate" hreflang="{{ language_code }}">
|
|
{{ lang.name_local }}
|
|
</a>
|
|
|
|
This adds a link to the translation. We use ``{{ lang.name_local }}`` to display
|
|
the name of the locale in its own language. We also add ``rel`` and ``hreflang``
|
|
attributes to the ``<a>`` tag for SEO.
|
|
|
|
Handling locales that share content
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Rather than iterating over pages, this example iterates over all of the configured
|
|
languages and finds the page for each one. This works better than the `Basic example`_
|
|
above on sites that have extra Django ``LANGUAGES`` that share the same Wagtail content.
|
|
|
|
For this example to work, you firstly need to add Django's
|
|
`django.template.context_processors.i18n <https://docs.djangoproject.com/en/3.1/ref/templates/api/#django-template-context-processors-i18n>`_
|
|
context processor to your ``TEMPLATES`` setting:
|
|
|
|
.. code-block:: python
|
|
|
|
# myproject/settings.py
|
|
|
|
TEMPLATES = [
|
|
{
|
|
# ...
|
|
'OPTIONS': {
|
|
'context_processors': [
|
|
# ...
|
|
'django.template.context_processors.i18n',
|
|
],
|
|
},
|
|
},
|
|
]
|
|
|
|
Now for the example itself:
|
|
|
|
.. code-block:: html+Django
|
|
|
|
{% for language_code, language_name in LANGUAGES %}
|
|
{% get_language_info for language_code as lang %}
|
|
|
|
{% language language_code %}
|
|
<a href="{% pageurl page.localized %}" rel="alternate" hreflang="{{ language_code }}">
|
|
{{ lang.name_local }}
|
|
</a>
|
|
{% endlanguage %}
|
|
{% endfor %}
|
|
|
|
Let's break this down too:
|
|
|
|
.. code-block:: html+Django
|
|
|
|
{% for language_code, language_name in LANGUAGES %}
|
|
...
|
|
{% endfor %}
|
|
|
|
This ``for`` block iterates through all of the configured languages on the site.
|
|
The ``LANGUAGES`` variable comes from the ``django.template.context_processors.i18n``
|
|
context processor.
|
|
|
|
.. code-block:: html+Django
|
|
|
|
{% get_language_info for language_code as lang %}
|
|
|
|
Does exactly the same as the previous example.
|
|
|
|
.. code-block:: html+Django
|
|
|
|
{% language language_code %}
|
|
...
|
|
{% endlanguage %}
|
|
|
|
This ``language`` tag comes from Django's ``i18n`` tag library. It changes the
|
|
active language for just the code contained within it.
|
|
|
|
.. code-block:: html+Django
|
|
|
|
<a href="{% pageurl page.localized %}" rel="alternate" hreflang="{{ language_code }}">
|
|
{{ lang.name_local }}
|
|
</a>
|
|
|
|
The only difference with the ``<a>`` tag here from the ``<a>`` tag in the previous example
|
|
is how we're getting the page's URL: ``{% pageurl page.localized %}``.
|
|
|
|
All page instances in Wagtail have a ``.localized`` attribute which fetches the translation
|
|
of the page in the current active language. This is why we activated the language previously.
|
|
|
|
Another difference here is that if the same translated page is shared in two locales, Wagtail
|
|
will generate the correct URL for the page based on the current active locale. This is the
|
|
key difference between this example and the previous one as the previous one can only get the
|
|
URL of the page in its default locale.
|
|
|
|
API filters for headless sites
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
For headless sites, the Wagtail API supports two extra filters for internationalised sites:
|
|
|
|
- ``?locale=`` Filters pages by the given locale
|
|
- ``?translation_of=`` Filters pages to only include translations of the given page ID
|
|
|
|
For more information, see :ref:`apiv2_i18n_filters`.
|
|
|
|
Translatable snippets
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
You can make a snippet translatable by making it inherit from ``wagtail.models.TranslatableMixin``.
|
|
For example:
|
|
|
|
.. code-block:: python
|
|
|
|
# myapp/models.py
|
|
|
|
from django.db import models
|
|
|
|
from wagtail.models import TranslatableMixin
|
|
from wagtail.snippets.models import register_snippet
|
|
|
|
|
|
@register_snippet
|
|
class Advert(TranslatableMixin, models.Model):
|
|
name = models.CharField(max_length=255)
|
|
|
|
The ``TranslatableMixin`` model adds the ``locale`` and ``translation_key`` fields to the model.
|
|
|
|
Making snippets with existing data translatable
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
For snippets with existing data, it's not possible to just add ``TranslatableMixin``,
|
|
make a migration, and run it. This is because the ``locale`` and ``translation_key``
|
|
fields are both required and ``translation_key`` needs a unique value for each
|
|
instance.
|
|
|
|
To migrate the existing data properly, we firstly need to use ``BootstrapTranslatableMixin``,
|
|
which excludes these constraints, then add a data migration to set the two fields, then
|
|
switch to ``TranslatableMixin``.
|
|
|
|
This is only needed if there are records in the database. So if the model is empty, you can
|
|
go straight to adding ``TranslatableMixin`` and skip this.
|
|
|
|
Step 1: Add ``BootstrapTranslatableMixin`` to the model
|
|
*******************************************************
|
|
|
|
This will add the two fields without any constraints:
|
|
|
|
.. code-block:: python
|
|
|
|
# myapp/models.py
|
|
|
|
from django.db import models
|
|
|
|
from wagtail.models import BootstrapTranslatableMixin
|
|
from wagtail.snippets.models import register_snippet
|
|
|
|
|
|
@register_snippet
|
|
class Advert(BootstrapTranslatableMixin, models.Model):
|
|
name = models.CharField(max_length=255)
|
|
|
|
# if the model has a Meta class, ensure it inherits from
|
|
# BootstrapTranslatableMixin.Meta too
|
|
class Meta(BootstrapTranslatableMixin.Meta):
|
|
verbose_name = 'adverts'
|
|
|
|
Run ``python manage.py makemigrations myapp`` to generate the schema migration.
|
|
|
|
Step 2: Create a data migration
|
|
*******************************
|
|
|
|
Create a data migration with the following command:
|
|
|
|
.. code-block:: bash
|
|
|
|
python manage.py makemigrations myapp --empty
|
|
|
|
This will generate a new empty migration in the app's ``migrations`` folder. Edit
|
|
that migration and add a ``BootstrapTranslatableModel`` for each model to bootstrap
|
|
in that app:
|
|
|
|
.. code-block:: python
|
|
|
|
from django.db import migrations
|
|
from wagtail.models import BootstrapTranslatableModel
|
|
|
|
class Migration(migrations.Migration):
|
|
dependencies = [
|
|
('myapp', '0002_bootstraptranslations'),
|
|
]
|
|
|
|
# Add one operation for each model to bootstrap here
|
|
# Note: Only include models that are in the same app!
|
|
operations = [
|
|
BootstrapTranslatableModel('myapp.Advert'),
|
|
]
|
|
|
|
Repeat this for any other apps that contain a model to be bootstrapped.
|
|
|
|
Step 3: Change ``BootstrapTranslatableMixin`` to ``TranslatableMixin``
|
|
**********************************************************************
|
|
|
|
Now that we have a migration that fills in the required fields, we can swap out
|
|
``BootstrapTranslatableMixin`` for ``TranslatableMixin`` that has all the
|
|
constraints:
|
|
|
|
.. code-block:: python
|
|
|
|
# myapp/models.py
|
|
|
|
from wagtail.models import TranslatableMixin # Change this line
|
|
|
|
@register_snippet
|
|
class Advert(TranslatableMixin, models.Model): # Change this line
|
|
name = models.CharField(max_length=255)
|
|
|
|
class Meta(TranslatableMixin.Meta): # Change this line, if present
|
|
verbose_name = 'adverts'
|
|
|
|
Step 4: Run ``makemigrations`` to generate schema migrations, then migrate!
|
|
***************************************************************************
|
|
|
|
Run ``makemigrations`` to generate the schema migration that adds the
|
|
constraints into the database, then run ``migrate`` to run all of the
|
|
migrations:
|
|
|
|
.. code-block:: bash
|
|
|
|
python manage.py makemigrations myapp
|
|
python manage.py migrate
|
|
|
|
When prompted to select a fix for the nullable field 'locale' being changed to
|
|
non-nullable, select the option "Ignore for now" (as this has been handled by the
|
|
data migration).
|
|
|
|
|
|
Translation workflow
|
|
--------------------
|
|
|
|
As mentioned at the beginning, Wagtail does supply ``wagtail.contrib.simple_translation``.
|
|
|
|
The simple_translation module provides a user interface that allows users to copy pages and translatable snippets into another language.
|
|
|
|
- Copies are created in the source language (not translated)
|
|
- Copies of pages are in draft status
|
|
|
|
Content editors need to translate the content and publish the pages.
|
|
|
|
To enable add ``"wagtail.contrib.simple_translation"`` to ``INSTALLED_APPS``
|
|
and run ``python manage.py migrate`` to create the ``submit_translation`` permissions.
|
|
In the Wagtail admin, go to settings and give some users or groups the "Can submit translations" permission.
|
|
|
|
.. note::
|
|
Simple Translation is optional. It can be switched out by third-party packages. Like the more advanced `wagtail-localize <https://github.com/wagtail/wagtail-localize>`_.
|
|
|
|
|
|
Wagtail Localize
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
As part of the initial work on implementing internationalisation for Wagtail core,
|
|
we also created a translation package called ``wagtail-localize``. This supports
|
|
translating pages within Wagtail, using PO files, machine translation, and external
|
|
integration with translation services.
|
|
|
|
Github: https://github.com/wagtail/wagtail-localize
|
|
|
|
Alternative internationalisation plugins
|
|
========================================
|
|
|
|
Before official multi-language support was added into Wagtail, site implementors
|
|
had to use external plugins. These have not been replaced by Wagtail's own
|
|
implementation as they use slightly different approaches, one of them might
|
|
fit your use case better:
|
|
|
|
- `Wagtailtrans <https://github.com/wagtail/wagtailtrans>`_
|
|
- `wagtail-modeltranslation <https://github.com/infoportugal/wagtail-modeltranslation>`_
|
|
|
|
For a comparison of these options, see AccordBox's blog post
|
|
`How to support multi-language in Wagtail CMS <https://www.accordbox.com/blog/how-support-multi-language-wagtail-cms/>`_.
|
|
|
|
Wagtail admin translations
|
|
==========================
|
|
|
|
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).
|
|
|
|
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.
|
|
|
|
Change Wagtail admin language on a per-user basis
|
|
=================================================
|
|
|
|
Logged-in users can set their preferred language from ``/admin/account/``.
|
|
By default, Wagtail provides a list of languages that have a >= 90% translation coverage.
|
|
It is possible to override this list via the :ref:`WAGTAILADMIN_PERMITTED_LANGUAGES <WAGTAILADMIN_PERMITTED_LANGUAGES>` setting.
|
|
|
|
In case there is zero or one language permitted, the form will be hidden.
|
|
|
|
If there is no language selected by the user, the ``LANGUAGE_CODE`` will be used.
|
|
|
|
|
|
Changing the primary language of your Wagtail installation
|
|
==========================================================
|
|
|
|
The default language of Wagtail is ``en-us`` (American English). You can change this by tweaking a couple of Django settings:
|
|
|
|
- Make sure `USE_I18N <https://docs.djangoproject.com/en/stable/ref/settings/#use-i18n>`_ is set to ``True``
|
|
- Set `LANGUAGE_CODE <https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-LANGUAGE_CODE>`_ to your websites' primary language
|
|
|
|
If there is a translation available for your language, the Wagtail admin backend should now be in the language you've chosen.
|