Translation coverage as a feature gate

20 views
Skip to first unread message

Andrea Marchesini

unread,
Aug 17, 2026, 10:53:53 AM (8 days ago) Aug 17
to firefox-dev

Project Metronome reduces Firefox’s release cycle to 2 weeks, halving the time localisation volunteers have to translate each release. In Firefox 154, we landed a set of patches that make it possible to use translation coverage as a feature gate. Two new methods are available in mozILocaleService:

Both methods use a translation coverage index generated at build time for the locale of the build or language pack. The index is read by l10nregistry-ffi and exposed through mozILocaleService.

Why all of this now?

Project Metronome is going to reduce the Firefox release cycle from 4 weeks to 2. This has an impact on Mozilla's localization community. Volunteers translate Firefox and other Mozilla products into more than 100 languages, and today they have the entire four-week release cycle to translate new strings. Two weeks will likely be enough for the most active locales, but we don't know that it will be sufficient for all of them.

The localization community has been informed about the move to a biweekly release cycle, but we also want an additional guardrail to avoid shipping features that are only partially translated.

So, the goal of this work is to give Firefox code a way to use translation coverage as a feature gate: if the current locale does not have sufficient translation coverage for feature X, we can decide to disable the feature, disable only part of it, show something different to the user, or apply whatever policy makes sense for that feature. The API provides the data; the feature decides what to do with it.

How does it work?

At build time, we generate Firefox builds and language packs for each locale. moz-l10n, the Python package responsible for localization and for replacing missing translations with strings from the fallback locale (currently always en), now also generates a coverage.json file and includes it in the build (resource://gre/localization/<locale>/coverage.json).

For each Fluent or properties file, coverage.json contains the total number of messages and the IDs of the messages that are missing for that locale. This becomes the source of truth used by mozILocaleService for the coverage checks.

How can I use it?

If your feature's strings are well isolated in a separate localization file, you can use this functionality to implement a translation coverage gate.

More in detail, isLocalizedEnough takes three parameters:

  • A localization file, used to look up its entry in coverage.json.

  • A boolean pref that can override the result. If the pref is true, the localization is always considered sufficient.

  • The minimum translation coverage required, expressed as a float between 0 and 1.

areMessagesLocalized provides finer-grained control. It also takes three parameters:

  • A localization file, used to look up its entry in coverage.json.

  • A boolean pref that can override the result.

  • An array of message IDs that must be translated.

Both methods return a boolean. Please note that these API methods will likely evolve as they get more usage, as we’ll want to internalize details like the coverage ratio number.

How should I not use it?

We do not have strong opinions, but we think we should not:

  • Block a feature in Nightly because that will prevent QA from testing it.

  • Block a feature indefinitely: the translation feature gate is meant to give extra time to developers. A feature should be exposed after a while even if not fully translated.

  • Probably you don’t want to hide a feature already exposed to users.

What about mobile?

The API lives in Gecko, so it is technically available on Android as well. In practice, the coverage index only describes the localization files that go through moz-l10n as part of the Gecko build. Fenix strings are localized through a separate pipeline and have no entry in coverage.json.  So, for now, treat this as Desktop-only. If you have an Android feature that would benefit from a translation coverage gate, please reach out and we can plan it together.

An example: IP Protection

IP Protection is the first Firefox feature using this functionality. Because IP Protection shipped in Firefox 153, we didn't want the new gate to hide a feature from existing users who might already have seen or used it. We therefore apply the translation coverage gate only to new Firefox users.

For those users, the translation gate is 80% of the total IP Protection strings. The gate lasts for one release only. In the following Firefox release, the feature is enabled regardless of its translation coverage. This gives localization an additional release cycle to catch up without permanently blocking the feature. As you immediately tell, this is a starting point for a relatively stable feature. We can do better!

Note that this is only one possible policy. Other features can use the coverage information differently depending on their requirements.

If you have questions, find bugs, or have ideas for other use cases, please reach out to me and/or the l10n team.

More detailed information, and numbers can be found in the initial proposal: Use l10n coverage as a feature flag 

Reply all
Reply to author
Forward
0 new messages