зеркало из https://github.com/mozilla/bedrock.git
Add wagtail-localize-smartling to the project, for Smartling L10N support (#14794)
* Add wagtail-localize-smartling to the project, for Smartling L10N support
* Add docs for wagtail-localize-smartling
* Minor reformatting
* Fix duplicated env var reference 🤦
* Add a management command that wraps the sync_smartling command so we can monitor it with a DMS
This commit is contained in:
Родитель
5fd5d4f524
Коммит
1829904358
|
@ -0,0 +1,34 @@
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from django.core.management import call_command
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from bedrock.base.config_manager import config
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = """Wraps the sync_smartling management command from
|
||||||
|
wagtail-localize-smartling so that we can monitor its
|
||||||
|
operation via a Dead Man's Snitch"""
|
||||||
|
|
||||||
|
def handle(self, *args, **kwargs):
|
||||||
|
SMARTLING_SYNC_SNITCH_URL = config("SMARTLING_SYNC_SNITCH_URL", default="")
|
||||||
|
|
||||||
|
try:
|
||||||
|
call_command("sync_smartling")
|
||||||
|
|
||||||
|
sys.stdout.write(
|
||||||
|
"\nsync_smartling executed successfully\n",
|
||||||
|
)
|
||||||
|
if SMARTLING_SYNC_SNITCH_URL:
|
||||||
|
requests.get(SMARTLING_SYNC_SNITCH_URL)
|
||||||
|
sys.stdout.write("Snitch pinged\n")
|
||||||
|
except Exception as ex:
|
||||||
|
sys.stderr.write(f"\nsync_smartling did not execute successfully: {ex}\n")
|
|
@ -749,6 +749,7 @@ INSTALLED_APPS = [
|
||||||
"wagtail.users",
|
"wagtail.users",
|
||||||
"wagtail.snippets",
|
"wagtail.snippets",
|
||||||
"wagtail.images",
|
"wagtail.images",
|
||||||
|
"wagtail_localize_smartling", # Has to come before wagtail_localize
|
||||||
"wagtail_localize",
|
"wagtail_localize",
|
||||||
"wagtail_localize.locales", # This replaces "wagtail.locales"
|
"wagtail_localize.locales", # This replaces "wagtail.locales"
|
||||||
"wagtail.search",
|
"wagtail.search",
|
||||||
|
@ -2122,6 +2123,29 @@ else:
|
||||||
# Wagtailed, but we need something valid so Pocket mode will boot up
|
# Wagtailed, but we need something valid so Pocket mode will boot up
|
||||||
WAGTAIL_CONTENT_LANGUAGES = [("en", "English")]
|
WAGTAIL_CONTENT_LANGUAGES = [("en", "English")]
|
||||||
|
|
||||||
|
# Settings for https://github.com/mozilla/wagtail-localize-smartling
|
||||||
|
WAGTAIL_LOCALIZE_SMARTLING = {
|
||||||
|
# Required settings (get these from "Account settings" > "API" in the Smartling dashboard)
|
||||||
|
"PROJECT_ID": config("WAGTAIL_LOCALIZE_SMARTLING_PROJECT_ID", default="setme"),
|
||||||
|
"USER_IDENTIFIER": config("WAGTAIL_LOCALIZE_SMARTLING_USER_IDENTIFIER", default="setme"),
|
||||||
|
"USER_SECRET": config("WAGTAIL_LOCALIZE_SMARTLING_USER_SECRET", default="setme"),
|
||||||
|
# Optional settings and their default values
|
||||||
|
"REQUIRED": config(
|
||||||
|
"WAGTAIL_LOCALIZE_SMARTLING_ALWAYS_SEND",
|
||||||
|
default="False",
|
||||||
|
parser=bool,
|
||||||
|
), # Set this to True to always send translations to Smartling
|
||||||
|
"ENVIRONMENT": config(
|
||||||
|
"WAGTAIL_LOCALIZE_SMARTLING_ENVIRONMENT",
|
||||||
|
default="production",
|
||||||
|
), # Set this to "staging" to use Smartling's staging API
|
||||||
|
"API_TIMEOUT_SECONDS": config(
|
||||||
|
"WAGTAIL_LOCALIZE_SMARTLING_API_TIMEOUT_SECONDS",
|
||||||
|
default="5",
|
||||||
|
parser=float,
|
||||||
|
), # Timeout in seconds for requests to the Smartling API
|
||||||
|
}
|
||||||
|
|
||||||
# Custom settings, not a core Wagtail ones, to scope out RichText options
|
# Custom settings, not a core Wagtail ones, to scope out RichText options
|
||||||
WAGTAIL_RICHEXT_FEATURES_FULL = [
|
WAGTAIL_RICHEXT_FEATURES_FULL = [
|
||||||
# https://docs.wagtail.org/en/stable/advanced_topics/customisation/page_editing_interface.html#limiting-features-in-a-rich-text-field
|
# https://docs.wagtail.org/en/stable/advanced_topics/customisation/page_editing_interface.html#limiting-features-in-a-rich-text-field
|
||||||
|
|
67
docs/cms.rst
67
docs/cms.rst
|
@ -415,6 +415,68 @@ This approach will not be a problem if we stick to image filter-specs from the
|
||||||
'approved' list. Note that extending the list of filter-specs is possible, if
|
'approved' list. Note that extending the list of filter-specs is possible, if
|
||||||
we need to.
|
we need to.
|
||||||
|
|
||||||
|
L10N and Translation Management
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
.. important::
|
||||||
|
|
||||||
|
Localization via Wagtail is something we are ramping up on, so please
|
||||||
|
do not assume the following notes are final, or that the workflows are
|
||||||
|
currently all rock-solid. We're learning as we go.
|
||||||
|
|
||||||
|
Page-tree concept
|
||||||
|
=================
|
||||||
|
|
||||||
|
Our Wagtail setup uses the official `wagtail-localize`_ package to manage
|
||||||
|
localization of pages.
|
||||||
|
|
||||||
|
This package supports page-level localization rather than field-level localization, which means that each locale has its own distinct tree of pages, rather than each page having a stack of duplicate fields, one per destination language.
|
||||||
|
|
||||||
|
These language-specific trees can be "synchronised" with the default ``en-US`` page tree, so would have the same page structure, field by field) — or they can not be synchronised, so can have their own extra pages, or some specific pages in the tree can be made not "synchronised", while others are.
|
||||||
|
|
||||||
|
Basically, there is plenty of flexibility. The flipside of that flexibility is we may also create an edge-case situation that ``wagtail-localize`` won't work with, but we'll have to see and deal with it.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
It's worth investing 15 mins in watching the `Wagtail Localize original demo`_ to get a good feel of how it can work.
|
||||||
|
|
||||||
|
Localization process
|
||||||
|
====================
|
||||||
|
|
||||||
|
Manual updates
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
At its most basic, there's nothing stopping us using copy-and-paste to enter translations into lang-specific pages, which might work well if we have a page in just one non-en-US lang and an in-house colleague doing the translation.
|
||||||
|
|
||||||
|
Automated via Smartling
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
However, we also have automation available to send source strings to translation vendor Smartling. This uses the ``wagtail-localize-smartling`` package.
|
||||||
|
|
||||||
|
Here's the workflow:
|
||||||
|
|
||||||
|
1. CMS page "MyPage" is created in the default lang (``en-US``)
|
||||||
|
2. The "Translate this page" option is triggered for MyPage, and relevant langs are selected from the configured langs that Smartling supports. (We don't have to translate into all of them)
|
||||||
|
3. A translation Job is created in Smartling, awaiting authorization by our L10N team
|
||||||
|
4. A L10N team colleague authorizes the Job and selects the relevant translation workflow(s) for the relevant lang(s)
|
||||||
|
5. Once the jobs are completed, the localised strings flow back to Wagtail and populate a draft version of each language-specific page
|
||||||
|
6. A human reviews these draft pages and publishes them
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
|
||||||
|
* Smartling/``wagtail-localize-smartling`` will only translate pages from the base lang (``en-US``) to another lang - it won't treat, say, a Page in ``fr`` as a source-language document.
|
||||||
|
* If a string is received from Smartling into the CMS and then manually edited on the CMS side, the change will `not` be overwritten by subsequent Smartling syncs and the manual edit needs to be added on the Smartling side for consistency and stability.
|
||||||
|
* If a page is translated from ``en-US`` once, then has new ``en-US`` content added that is sent for translation, that will trigger a new Smartling Job. When that job is complete, it `will` overwrite any manual edits made to a translation within the CMS. This is why it's important to make sure Smartling contains any manual tweaks done to translations in the CMS.
|
||||||
|
|
||||||
|
|
||||||
|
Automated via Pontoon
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
It should also be possible to use `Pontoon`_ with `wagtail-localize`. (There are notes on the `Pontoon integration`_ here, but we have not yet tried to enable this alongside `wagtail-localize-smartling`).
|
||||||
|
|
||||||
|
Additionally using Pontoon would let us benefit from community translations across a broad range of languages. However, we have yet to try to set this up and would need to agree which parts of the site do and do not use Pontoon.
|
||||||
|
|
||||||
|
|
||||||
Infrastructure notes
|
Infrastructure notes
|
||||||
====================
|
====================
|
||||||
|
|
||||||
|
@ -451,3 +513,8 @@ admin user in your local build.
|
||||||
.. _Custom Block types: https://docs.wagtail.org/en/stable/advanced_topics/customisation/streamfield_blocks.html#custom-streamfield-blocks
|
.. _Custom Block types: https://docs.wagtail.org/en/stable/advanced_topics/customisation/streamfield_blocks.html#custom-streamfield-blocks
|
||||||
.. _Django migrations docs: https://docs.djangoproject.com/en/4.2/topics/migrations/
|
.. _Django migrations docs: https://docs.djangoproject.com/en/4.2/topics/migrations/
|
||||||
.. _Squashing migrations: https://docs.djangoproject.com/en/4.2/topics/migrations/
|
.. _Squashing migrations: https://docs.djangoproject.com/en/4.2/topics/migrations/
|
||||||
|
.. _wagtail-localize: https://wagtail-localize.org/
|
||||||
|
.. _wagtail-localize-smartling: https://github.com/mozilla/wagtail-localize-smartling
|
||||||
|
.. _Pontoon: https://pontoon.mozilla.org/
|
||||||
|
.. _Pontoon integration: https://wagtail-localize.org/stable/how-to/integrations/pontoon/
|
||||||
|
.. _Wagtail Localize original demo: https://www.youtube.com/watch?v=mEzQcOMUzoc
|
||||||
|
|
|
@ -478,6 +478,7 @@ django==4.2.14 \
|
||||||
# mozilla-django-oidc
|
# mozilla-django-oidc
|
||||||
# wagtail
|
# wagtail
|
||||||
# wagtail-localize
|
# wagtail-localize
|
||||||
|
# wagtail-localize-smartling
|
||||||
django-allow-cidr==0.7.1 \
|
django-allow-cidr==0.7.1 \
|
||||||
--hash=sha256:11126c5bb9df3a61ff9d97304856ba7e5b26d46c6d456709a6d9e28483bff47f \
|
--hash=sha256:11126c5bb9df3a61ff9d97304856ba7e5b26d46c6d456709a6d9e28483bff47f \
|
||||||
--hash=sha256:382c5d7a9807279e3e96e4f4892b59163a2b30128c596902bf5f80e133e1ccbb
|
--hash=sha256:382c5d7a9807279e3e96e4f4892b59163a2b30128c596902bf5f80e133e1ccbb
|
||||||
|
@ -567,6 +568,7 @@ djangorestframework==3.15.2 \
|
||||||
# via
|
# via
|
||||||
# -r requirements/prod.txt
|
# -r requirements/prod.txt
|
||||||
# wagtail
|
# wagtail
|
||||||
|
# wagtail-localize-smartling
|
||||||
docutils==0.21.2 \
|
docutils==0.21.2 \
|
||||||
--hash=sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f \
|
--hash=sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f \
|
||||||
--hash=sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2
|
--hash=sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2
|
||||||
|
@ -1885,6 +1887,7 @@ requests==2.32.3 \
|
||||||
# pytest-selenium
|
# pytest-selenium
|
||||||
# responses
|
# responses
|
||||||
# wagtail
|
# wagtail
|
||||||
|
# wagtail-localize-smartling
|
||||||
responses==0.25.0 \
|
responses==0.25.0 \
|
||||||
--hash=sha256:01ae6a02b4f34e39bffceb0fc6786b67a25eae919c6368d05eabc8d9576c2a66 \
|
--hash=sha256:01ae6a02b4f34e39bffceb0fc6786b67a25eae919c6368d05eabc8d9576c2a66 \
|
||||||
--hash=sha256:2f0b9c2b6437db4b528619a77e5d565e4ec2a9532162ac1a131a83529db7be1a
|
--hash=sha256:2f0b9c2b6437db4b528619a77e5d565e4ec2a9532162ac1a131a83529db7be1a
|
||||||
|
@ -2209,6 +2212,7 @@ wagtail==6.1.3 \
|
||||||
# -r requirements/prod.txt
|
# -r requirements/prod.txt
|
||||||
# wagtail-factories
|
# wagtail-factories
|
||||||
# wagtail-localize
|
# wagtail-localize
|
||||||
|
# wagtail-localize-smartling
|
||||||
wagtail-factories==4.2.1 \
|
wagtail-factories==4.2.1 \
|
||||||
--hash=sha256:7a180fc1b074af7a78648c634740ee89d4dbb45899917744b66431d38155b6ae \
|
--hash=sha256:7a180fc1b074af7a78648c634740ee89d4dbb45899917744b66431d38155b6ae \
|
||||||
--hash=sha256:bfe158092982a2b30a3e603c482242905df0b163fc69573fa6f159df482175c5
|
--hash=sha256:bfe158092982a2b30a3e603c482242905df0b163fc69573fa6f159df482175c5
|
||||||
|
@ -2216,6 +2220,12 @@ wagtail-factories==4.2.1 \
|
||||||
wagtail-localize==1.9 \
|
wagtail-localize==1.9 \
|
||||||
--hash=sha256:a680fc33c17145e6726f03a57b2ec465405847ae7cb77943ecc0e56463ad68c7 \
|
--hash=sha256:a680fc33c17145e6726f03a57b2ec465405847ae7cb77943ecc0e56463ad68c7 \
|
||||||
--hash=sha256:f4fa9c36d8dbab5c27d1b675ed6fd7b9e8f012cf4bb308464168de7ebbad8324
|
--hash=sha256:f4fa9c36d8dbab5c27d1b675ed6fd7b9e8f012cf4bb308464168de7ebbad8324
|
||||||
|
# via
|
||||||
|
# -r requirements/prod.txt
|
||||||
|
# wagtail-localize-smartling
|
||||||
|
wagtail-localize-smartling==0.2.3 \
|
||||||
|
--hash=sha256:0701444976c6b5392616d5dcdbf202fdce730b591e9d6794efee99c613107dc5 \
|
||||||
|
--hash=sha256:6bef31958c24229a663b81b889879c845bed021dde0eba44a9527eb45e6cf3ed
|
||||||
# via -r requirements/prod.txt
|
# via -r requirements/prod.txt
|
||||||
wcwidth==0.2.13 \
|
wcwidth==0.2.13 \
|
||||||
--hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \
|
--hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \
|
||||||
|
|
|
@ -57,3 +57,4 @@ timeago==1.0.16
|
||||||
whitenoise==6.7.0
|
whitenoise==6.7.0
|
||||||
Wagtail==6.1.3
|
Wagtail==6.1.3
|
||||||
wagtail-localize==1.9
|
wagtail-localize==1.9
|
||||||
|
wagtail-localize-smartling==0.2.3
|
||||||
|
|
|
@ -325,6 +325,7 @@ django==4.2.14 \
|
||||||
# mozilla-django-oidc
|
# mozilla-django-oidc
|
||||||
# wagtail
|
# wagtail
|
||||||
# wagtail-localize
|
# wagtail-localize
|
||||||
|
# wagtail-localize-smartling
|
||||||
django-allow-cidr==0.7.1 \
|
django-allow-cidr==0.7.1 \
|
||||||
--hash=sha256:11126c5bb9df3a61ff9d97304856ba7e5b26d46c6d456709a6d9e28483bff47f \
|
--hash=sha256:11126c5bb9df3a61ff9d97304856ba7e5b26d46c6d456709a6d9e28483bff47f \
|
||||||
--hash=sha256:382c5d7a9807279e3e96e4f4892b59163a2b30128c596902bf5f80e133e1ccbb
|
--hash=sha256:382c5d7a9807279e3e96e4f4892b59163a2b30128c596902bf5f80e133e1ccbb
|
||||||
|
@ -401,7 +402,9 @@ django-watchman==1.3.0 \
|
||||||
djangorestframework==3.15.2 \
|
djangorestframework==3.15.2 \
|
||||||
--hash=sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20 \
|
--hash=sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20 \
|
||||||
--hash=sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad
|
--hash=sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad
|
||||||
# via wagtail
|
# via
|
||||||
|
# wagtail
|
||||||
|
# wagtail-localize-smartling
|
||||||
docutils==0.21.2 \
|
docutils==0.21.2 \
|
||||||
--hash=sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f \
|
--hash=sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f \
|
||||||
--hash=sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2
|
--hash=sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2
|
||||||
|
@ -1365,6 +1368,7 @@ requests==2.32.3 \
|
||||||
# mozilla-django-oidc
|
# mozilla-django-oidc
|
||||||
# pygithub
|
# pygithub
|
||||||
# wagtail
|
# wagtail
|
||||||
|
# wagtail-localize-smartling
|
||||||
rich-text-renderer==0.2.8 \
|
rich-text-renderer==0.2.8 \
|
||||||
--hash=sha256:74e28bde639f737e2bc50f3dfb147bdbad4b2d7ab3f8f76a9db2d444edb8d13b \
|
--hash=sha256:74e28bde639f737e2bc50f3dfb147bdbad4b2d7ab3f8f76a9db2d444edb8d13b \
|
||||||
--hash=sha256:e4680109372b55611250ebe0745f59cbf3f8932afa6f5cb5d1f3cc282a4bf95c
|
--hash=sha256:e4680109372b55611250ebe0745f59cbf3f8932afa6f5cb5d1f3cc282a4bf95c
|
||||||
|
@ -1591,9 +1595,16 @@ wagtail==6.1.3 \
|
||||||
# via
|
# via
|
||||||
# -r requirements/prod.in
|
# -r requirements/prod.in
|
||||||
# wagtail-localize
|
# wagtail-localize
|
||||||
|
# wagtail-localize-smartling
|
||||||
wagtail-localize==1.9 \
|
wagtail-localize==1.9 \
|
||||||
--hash=sha256:a680fc33c17145e6726f03a57b2ec465405847ae7cb77943ecc0e56463ad68c7 \
|
--hash=sha256:a680fc33c17145e6726f03a57b2ec465405847ae7cb77943ecc0e56463ad68c7 \
|
||||||
--hash=sha256:f4fa9c36d8dbab5c27d1b675ed6fd7b9e8f012cf4bb308464168de7ebbad8324
|
--hash=sha256:f4fa9c36d8dbab5c27d1b675ed6fd7b9e8f012cf4bb308464168de7ebbad8324
|
||||||
|
# via
|
||||||
|
# -r requirements/prod.in
|
||||||
|
# wagtail-localize-smartling
|
||||||
|
wagtail-localize-smartling==0.2.3 \
|
||||||
|
--hash=sha256:0701444976c6b5392616d5dcdbf202fdce730b591e9d6794efee99c613107dc5 \
|
||||||
|
--hash=sha256:6bef31958c24229a663b81b889879c845bed021dde0eba44a9527eb45e6cf3ed
|
||||||
# via -r requirements/prod.in
|
# via -r requirements/prod.in
|
||||||
webencodings==0.5.1 \
|
webencodings==0.5.1 \
|
||||||
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
|
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
|
||||||
|
|
Загрузка…
Ссылка в новой задаче