kopia lustrzana https://github.com/wagtail/wagtail
				
				
				
			
		
			
				
	
	
		
			630 wiersze
		
	
	
		
			22 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
			
		
		
	
	
			630 wiersze
		
	
	
		
			22 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
| ====================
 | |
| Internationalisation
 | |
| ====================
 | |
| 
 | |
| .. contents::
 | |
|     :local:
 | |
|     :depth: 3
 | |
| 
 | |
| Multi-language content
 | |
| ======================
 | |
| 
 | |
| .. versionadded:: 2.11
 | |
| 
 | |
| 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 and, optionally, set up a workflow that allows users to
 | |
| translate content between languages.
 | |
| 
 | |
| 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
 | |
| builtin 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"),
 | |
|     ]
 | |
| 
 | |
| 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.core.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 %}
 | |
| 
 | |
|     {% 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 %}
 | |
| 
 | |
| Let's break this down:
 | |
| 
 | |
| .. 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.core.models.TranslatableMixin``.
 | |
| For example:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     # myapp/models.py
 | |
| 
 | |
|     from django.db import models
 | |
| 
 | |
|     from wagtail.core.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.core.models import BootstrapTranslatableMixin
 | |
|     from wagtail.snippets.models import register_snippet
 | |
| 
 | |
| 
 | |
|     @register_snippet
 | |
|     class Advert(BootstrapTranslatableMixin, models.Model):
 | |
|         name = models.CharField(max_length=255)
 | |
| 
 | |
| 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_localize.bootstrap 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.core.models import TranslatableMixin  # Change this line
 | |
| 
 | |
|     @register_snippet
 | |
|     class Advert(TranslatableMixin, models.Model):  # Change this line
 | |
|         name = models.CharField(max_length=255)
 | |
| 
 | |
| 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 --empty
 | |
|     python manage.py migrate
 | |
| 
 | |
| Translation workflow
 | |
| --------------------
 | |
| 
 | |
| As mentioned at the beginning, Wagtail does not supply any built-in user interface
 | |
| or external integration that provides a translation workflow. This has been left
 | |
| for third-party packages to solve.
 | |
| 
 | |
| 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.
 |