diff options
Diffstat (limited to 'comm/docs/l10n/fluent_migrations.md')
-rw-r--r-- | comm/docs/l10n/fluent_migrations.md | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/comm/docs/l10n/fluent_migrations.md b/comm/docs/l10n/fluent_migrations.md new file mode 100644 index 0000000000..13639ca187 --- /dev/null +++ b/comm/docs/l10n/fluent_migrations.md @@ -0,0 +1,190 @@ +# Migrating Strings to Fluent Files + +Like [Firefox](https://firefox-source-docs.mozilla.org/l10n/migrations/index.html), +Thunderbird developers are working on migrating strings from legacy formats to +Fluent. The process is very similar to how migrations are done for Firefox. The +differences are detailed below. + +## Migration Recipes + +When part of Thunderbird’s UI is migrated to Fluent, a migration recipe should +be included in the same patch that adds new strings to .ftl files. Recipies are +stored in [comm-central](https://hg.mozilla.org/comm-central/file/tip/python/l10n/tb_fluent_migrations). +After a patch with migrations landed, it will be run for all locales as part of +the [Thunderbird Cross-Channel string quarantining process](cross_channel.md). + +Be sure to read [Migrating Legacy Formats](https://firefox-source-docs.mozilla.org/l10n/migrations/legacy.html) +along with the below example. + +The migration recipe’s filename should start with a reference to the associated +bug number, and include a brief description of the bug, e.g. `bug_1805746_calendar_view.py` +for the below example. + +### Example: Migrate Multiple DTD strings to Fluent + +Often, strings are migrated as part of ongoing UI work to convert XUL code +to HTML. Multiple DTD strings may convert to a single Fluent string with +attributes. It really depends on the document structure and what the UI changes +are doing. + +**Legacy strings are in `comm/calendar/locales/en-US/chrome/calendar/calendar.dtd`** + +```dtd +<!ENTITY calendar.day.button.tooltip "Switch to day view" > +<!ENTITY calendar.day.button.label "Day" > +``` + +**The (simplified) XUL code** + +```xml +<radio id="calendar-day-view-button" + label="&calendar.day.button.label;" + tooltiptext="&calendar.day.button.tooltip;" /> +``` + +**The new HTML** + +```html +<button id="calTabDay" data-l10n-id="calendar-view-toggle-day"></button> +``` + +**The new FTL string** + +```fluent +calendar-view-toggle-day = Day + .title = Switch to day view +``` + +**Renders as:** + +```html +<button id="calTabDay" title="Switch to day view">Day</button> +``` + +This case migrates two DTD strings, `calendar.day.button.label` and `calendar.day.button.tooltip` +to create a single FTL string, `calendar-view-toggle-day`, with one (`title`) +attribute. + +**The migration recipe:** + +```python +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from fluent.migratetb.helpers import transforms_from +from fluent.migratetb import COPY + +def migrate(ctx): + """Bug 1805746 - Update Calendar View selection part {index}.""" + target = reference = "calendar/calendar/calendar-widgets.ftl" + source = "calendar/chrome/calendar/calendar.dtd" + + ctx.add_transforms( + target, + reference, + transforms_from( + """ +calendar-view-toggle-day = { COPY(from_path, "calendar.day.button.label") } + .title = { COPY(from_path, "calendar.day.button.tooltip") } +""", + from_path=source, + ), + ) +``` + +Migrations are Python modules, and implement +a single `migrate(MigrationContext)` function. The `migrate()` function makes +calls into `MigrationContext.add_transforms()`. + +The `add_transforms()` function takes three arguments: +- `target_path`: Path to the target l10n file +- `reference_path`: Path to the reference (en-US) file +- A list of Transforms, the `source_path` (legacy translated strings file) is + set here + +```{note} +For Thunderbird migrations, the target and reference path are the same. +``` + +Transforms are rather dense AST nodes. See +[Transforms](https://firefox-source-docs.mozilla.org/l10n/migrations/overview.html#transforms) +for the exact details. + +There are some helper functions that simplify creating the ASTs. The above example uses the +`transforms_from()` helper function. It is equivalent to: + +```python +target = reference = "calendar/calendar/calendar-widgets.ftl" +source = "calendar/chrome/calendar/calendar.dtd" + +ctx.add_transforms( + target, + reference, + [ + FTL.Message( + id=FTL.Identifier("calendar-view-toggle-day"), + value=COPY(source, "calendar.day.button.label"), + attributes=[ + FTL.Attribute( + id=FTL.Identifier("title"), + value=COPY( + source, + "calendar.day.button.tooltip" + ) + ) + ] + ) + ] +) +``` + +`transforms_from()` allows copying reference FTL strings, and replacing the value +of each message with a `COPY` Transform that copies values from the DTD file at +`from_path`. + +There are other Transforms like `COPY`. See +[Migrating Legacy Formats](https://firefox-source-docs.mozilla.org/l10n/migrations/legacy.html) +for usage information. + +### Thunderbird migration helpers + +The `REPLACE` works with `transforms_from` if provided the extra context that +it needs. + +Starting with `aboutDialog.dtd` containing: + +```xml +<!ENTITY update.updateButton.label3 "Restart to update &brandShorterName;"> +``` + +```python +from fluent.migratetb.helpers import TERM_REFERENCE, transforms_from + +# This can't just be a straight up literal dict (eg: {"a":"b"}) because the +# validator fails... so make it a function call that returns a dict.. it works +about_replacements = dict({ + "&brandShorterName;": TERM_REFERENCE("brand-shorter-name"), +}) + + +def migrate(ctx): + """Bug 1816532 - Migrate aboutDialog.dtd strings to Fluent, part {index}""" + target = reference = "mail/messenger/aboutDialog.ftl" + source = "mail/chrome/messenger/aboutDialog.dtd" + + ctx.add_transforms( + target, + reference, + transforms_from( + """ +update-update-button = { REPLACE(source, "update.updateButton.label3", about_replacements) } + .accesskey = { COPY(source, "update.updateButton.accesskey") } +""", source=source, about_replacements=about_replacements)) +``` + +The resulting `aboutDialog.ftl` will get: + +```ftl +update-update-button = Restart to update { -brand-shorter-name } + .accesskey = R +``` |