Closed Bug 2046945 Opened 11 days ago Closed 5 days ago

Widgets doesn't match UI locale after switching language from settings

Categories

(Firefox :: New Tab Page, defect)

defect

Tracking

()

VERIFIED FIXED
154 Branch
Tracking Status
relnote-firefox --- 152+
firefox152 + verified
firefox153 + verified
firefox154 + verified

People

(Reporter: flod, Assigned: mconley)

References

(Blocks 1 open bug)

Details

Attachments

(19 files, 5 obsolete files)

124.31 KB, image/png
Details
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
692.03 KB, application/zip
Details
3.24 MB, application/x-xpinstall
Details
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review

Use Firefox Release and make sure the World Cup widget is enabled. In my case, the build is in Italian.

Go to Settings and switch language, e.g. to German. The widget remains in Italian, restarting the browser doesn't update it.

Sadly widgets seem to be all over the place.

I have some widgets partially in German and Italian (Checklist). World Clock shows tooltips in Italian. World Cup widget is in Italian. Time seems to be in German.

[Tracking Requested - why for this release]: this is a very poor experience for users switching language at run-time, which includes MSIX builds and most Linux distro.

I've tested a local build (using these instructions to change locale) and it seems to behave correctly.

I'm starting to think that the problem might be with the train-hop code? Is there a way to verify that, e.g. use the built-in version?

I think I've also seen New Tab settings being half-translated at some point, but can't replicate.

Summary: World Cup widget doesn't match UI after switching language → Widgets doesn't match UI locale after switching language from settings

In my release build, the New Tab XPI is at version 153.3.20260605.21338 (from browser.newtabpage.trainhopAddon.version).

unzip -p newtab@mozilla.org.xpi locales/locales-report.json \
  | python3 -c 'import json,sys; r=json.load(sys.stdin); \
    print("snapshot:", r["meta"]["updated"]); \
    m=r["locales"]["de"].get("missing",{}); \
    print("de missing:", sorted(i for v in m.values() for i in v))'
snapshot: 2026-06-04T19:16:58.548047
de missing: ['newtab-sports-widget-match-vs', 'newtab-sports-widget-no-upcoming-matches', 'newtab-sports-widget-team-tbd']

For example, the checklist add button label is in there.

This is the result of me spending way too much time digging through this bug with Claude. Leaving it for HNT engineers to evaluate if it makes any sense.

Evidence: in the parent process, new Localization(["browser/newtab/newtab.ftl"]).formatValue("newtab-widget-lists-button-add-item") returns the correct German — the registry is complete; only the content document is missing the source.

Possible fix: register the "newtab" source before content renders (read supported-locales.json synchronously instead of await fetch), and re-translate open about:newtab / about:home documents after _updateFluentSourcesRegistration (both initial and on locale change).

The bug is marked as tracked for firefox152 (beta) and tracked for firefox153 (nightly). However, the bug still isn't assigned.

:thecount, could you please find an assignee for this tracked bug? If you disagree with the tracking decision, please talk with the release managers.

For more information, please visit BugBot documentation.

Flags: needinfo?(sdowne)

@maxx can we get a fix for this in the next trainhop?

Flags: needinfo?(mcrawford)

Hey Stephen,

I've started poking at this one, and at this point, I'm fairly convinced that it requires changes in the base application, and cannot be fixed with a trainhop. This means that, given where we are in the release cycle, a fix for this (assuming I can get one crafted in the next day or so) will be available in the first dot release of 152 (June 23rd, so a week tomorrow).

If there is sufficient urgency and user impact here, we could talk to RelMan about an out-of-band dot release, but I believe the weekly dot releases mean that the bar for out-of-band dot releases is much higher than it used to be.

Assignee: nobody → mconley
Flags: needinfo?(sdowne)
Flags: needinfo?(mcrawford)

Long-lived Localization instances cache the bundles they generate on first
use. Until now, no observer notification fired when sources were registered,
updated, or removed in L10nRegistry, so those caches were never invalidated;
any source registered after startup (e.g. by AboutNewTabResourceMapping when
a train-hopped newtab XPI is active) was invisible to already-translated
documents.

We introduce a new intl:l10n-sources-changed observer topic, fired by
L10nRegistry in both the parent (L10nRegistrySendUpdateL10nFileSources) and
content (RegisterFileSourcesFromParentProcess) processes after the registry
has been mutated. Localization::Observe now listens for it and drops cached
bundles, mirroring its existing handling of intl:app-locales-changed.

A dedicated topic is used rather than reusing intl:app-locales-changed so
the ~30 other observers that care only about negotiated-locale changes
(font list, mozIntl caches, sidebar, tabbrowser, …) aren't woken on every
source mutation.

Consumers of L10nRegistry that want to register sources alongside a
langpack's (for example, to provide a locale-specific override for an
individual resource) need two things this module didn't previously
provide: an authoritative enumeration of currently-active langpacks at
the time the consumer initializes, and lifecycle notifications symmetric
to the existing webextension-langpack-startup topic.

We add a static Langpack.activeLangpackIds Set, mutated at the same
callsites that mutate the L10nRegistry, exposing the langpack metasource
strings (startupData.langpackId, which is not the addon's id). We then
fire a new webextension-langpack-shutdown observer topic before the langpack
removes its L10nRegistry sources, so consumers can clean up parallel
registrations in the same metasource before it goes away.

The first consumer in AboutNewTabResourceMapping in the next patch in this
series.

The L10nRegistry solver builds bundles atomically per (locale, metasource):
so every required resource must be satisfiable from sources in that
metasource for that locale, or no bundle is produced.

The "app" metasource's non-newtab sources (toolkit, browser) are packaged en-US
only, so with a non-English langpack the (locale, "app") bundle can never be
built — and the train-hop newtab XPI's locale-specific strings are
unreachable, falling through to en-US. That is why train-hop-only widget
strings (added to the XPI but not yet present in any langpack) were
rendering in the wrong language.

We make AboutNewTabResourceMapping also register a shadow newtab
L10nFileSource into each active langpack's metasource, enumerated via
Langpack.activeLangpackIds and kept in sync with
webextension-langpack-startup/-shutdown observer notifications). Within the
(locale, langpack) bundle, the solver now yields two valid orderings: one
with the langpack's older newtab.ftl, one with the XPI's. Fluent falls
through the former on missing keys and resolves train-hop-only strings
from the latter, while strings the langpack already translates continue
to come from the langpack.

Pushed by rvandermeulen@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/1f508514efb9 https://hg.mozilla.org/integration/autoland/rev/d747305f99fb Part 1: Fire intl:l10n-sources-changed when L10nRegistry sources mutate r=eemeli https://github.com/mozilla-firefox/firefox/commit/b2cb45cec4a4 https://hg.mozilla.org/integration/autoland/rev/695da3586cfe Part 2: Expose active langpack ids and a webextension-langpack-shutdown observer topic r=robwu https://github.com/mozilla-firefox/firefox/commit/c063096fa111 https://hg.mozilla.org/integration/autoland/rev/5e620d8e172d Part 3: Register newtab XPI Fluent source into each active langpack's metasource r=maxx
Pushed by abutkovits@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/ca1fcfd2f0af https://hg.mozilla.org/integration/autoland/rev/a2f41ceb0459 Revert "Bug 2046945 - Part 3: Register newtab XPI Fluent source into each active langpack's metasource r=maxx" for causing failures at test_ext_permissions.js.
Pushed by asilaghi@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/18a6410b0f69 https://hg.mozilla.org/integration/autoland/rev/b402dd4a5458 Revert "Bug 2046945 - Part 3: Register newtab XPI Fluent source into each active langpack's metasource. r=maxx" for causing xpcshells and TV-nofis failures at l10nregistry_observer.js

Backed out for causing xpcshells and TV-nofis failures at l10nregistry_observer.js
Backout Link
Push with failures
Failure Log
Failure line TEST-UNEXPECTED-FAIL | intl/l10n/test/test_l10nregistry_observer.js | test_localization_invalidates_on_topic - [test_localization_invalidates_on_topic : 110] After intl:l10n-sources-changed, Localization picks up the updated source - "before" == "after"

Pushed by rvandermeulen@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/70f3b13322b3 https://hg.mozilla.org/integration/autoland/rev/4cdfcf1ffba7 Part 1: Fire intl:l10n-sources-changed when L10nRegistry sources mutate. r=eemeli https://github.com/mozilla-firefox/firefox/commit/311beab6bed5 https://hg.mozilla.org/integration/autoland/rev/6b0730c30744 Part 1.5: Have AboutNewTabChild retrigger translation of about:newtab on intl:l10n-sources-changed. r=maxx https://github.com/mozilla-firefox/firefox/commit/450693f9e4f1 https://hg.mozilla.org/integration/autoland/rev/203fbb945a56 Part 2: Expose active langpack ids and a webextension-langpack-shutdown observer topic. r=robwu https://github.com/mozilla-firefox/firefox/commit/454f00b7c4b5 https://hg.mozilla.org/integration/autoland/rev/3e5c4b170c49 Part 3: Register newtab XPI Fluent source into each active langpack's metasource. r=maxx

Long-lived Localization instances cache the bundles they generate on first
use. Until now, no observer notification fired when sources were registered,
updated, or removed in L10nRegistry, so those caches were never invalidated;
any source registered after startup (e.g. by AboutNewTabResourceMapping when
a train-hopped newtab XPI is active) was invisible to already-translated
documents.

We introduce a new intl:l10n-sources-changed observer topic, fired by
L10nRegistry in both the parent (L10nRegistrySendUpdateL10nFileSources) and
content (RegisterFileSourcesFromParentProcess) processes after the registry
has been mutated. Localization::Observe now listens for it and drops cached
bundles, mirroring its existing handling of intl:app-locales-changed.

A dedicated topic is used rather than reusing intl:app-locales-changed so
the ~30 other observers that care only about negotiated-locale changes
(font list, mozIntl caches, sidebar, tabbrowser, …) aren't woken on every
source mutation.

Attachment #9598547 - Flags: approval-mozilla-beta?
Attachment #9598548 - Flags: approval-mozilla-beta?

Consumers of L10nRegistry that want to register sources alongside a
langpack's (for example, to provide a locale-specific override for an
individual resource) need two things this module didn't previously
provide: an authoritative enumeration of currently-active langpacks at
the time the consumer initializes, and lifecycle notifications symmetric
to the existing webextension-langpack-startup topic.

We add a static Langpack.activeLangpackIds Set, mutated at the same
callsites that mutate the L10nRegistry, exposing the langpack metasource
strings (startupData.langpackId, which is not the addon's id). We then
fire a new webextension-langpack-shutdown observer topic before the langpack
removes its L10nRegistry sources, so consumers can clean up parallel
registrations in the same metasource before it goes away.

The first consumer in AboutNewTabResourceMapping in the next patch in this
series.

Attachment #9598549 - Flags: approval-mozilla-beta?

firefox-beta Uplift Approval Request

  • User impact if declined/Reason for urgency: Users with non-en-US langpacks installed (So non-en-US users on MSIX on Windows, Linux) may find some of their New Tab UI isn't localized properly, and is falling back to en-US.
  • Code covered by automated testing?: yes
  • Fix verified in Nightly?: no
  • Needs manual QE testing?: yes
  • Steps to reproduce for manual QE testing: Ensure that New Tab 153.5.20260615.213953 is installed. This may require you to force enroll in https://experimenter.services.mozilla.com/nimbus/new-tab-153520260615213953-to-release-152-wcw-v4/summary/.

Install an alternative langpack for release or beta, and ensure that recent strings are available in the relevant locale.

Then, in New Tab, open up the devtools console, and paste / execute this command:

(await document.l10n.formatMessages(["home-homepage-title"]))[0].attributes[0].value

and ensure that a string is returned ("Homepage" in en-US, but something appropriate for the installed langpack).

  • Risk associated with taking this patch: low
  • Explanation of risk level: This set of patches includes unit tests, and while it's scary that it has C++ changes, those changes really just add an observer notification that only the New Tab listens to. Same with the extensions change, which just exposes some things for New Tab to listen to. So really, the blast radius is restricted to New Tab - and I'm fairly confident we've got this right.
  • String changes made/needed?: None.
  • Is Android affected?: no
Attachment #9598550 - Flags: approval-mozilla-beta?
Flags: qe-verify+

The L10nRegistry solver builds bundles atomically per (locale, metasource):
so every required resource must be satisfiable from sources in that
metasource for that locale, or no bundle is produced.

The "app" metasource's non-newtab sources (toolkit, browser) are packaged en-US
only, so with a non-English langpack the (locale, "app") bundle can never be
built — and the train-hop newtab XPI's locale-specific strings are
unreachable, falling through to en-US. That is why train-hop-only widget
strings (added to the XPI but not yet present in any langpack) were
rendering in the wrong language.

We make AboutNewTabResourceMapping also register a shadow newtab
L10nFileSource into each active langpack's metasource, enumerated via
Langpack.activeLangpackIds and kept in sync with
webextension-langpack-startup/-shutdown observer notifications). Within the
(locale, langpack) bundle, the solver now yields two valid orderings: one
with the langpack's older newtab.ftl, one with the XPI's. Fluent falls
through the former on missing keys and resolves train-hop-only strings
from the latter, while strings the langpack already translates continue
to come from the langpack.

Long-lived Localization instances cache the bundles they generate on first
use. Until now, no observer notification fired when sources were registered,
updated, or removed in L10nRegistry, so those caches were never invalidated;
any source registered after startup (e.g. by AboutNewTabResourceMapping when
a train-hopped newtab XPI is active) was invisible to already-translated
documents.

We introduce a new intl:l10n-sources-changed observer topic, fired by
L10nRegistry in both the parent (L10nRegistrySendUpdateL10nFileSources) and
content (RegisterFileSourcesFromParentProcess) processes after the registry
has been mutated. Localization::Observe now listens for it and drops cached
bundles, mirroring its existing handling of intl:app-locales-changed.

A dedicated topic is used rather than reusing intl:app-locales-changed so
the ~30 other observers that care only about negotiated-locale changes
(font list, mozIntl caches, sidebar, tabbrowser, …) aren't woken on every
source mutation.

Attachment #9598551 - Flags: approval-mozilla-release?
Attachment #9598552 - Flags: approval-mozilla-release?

Consumers of L10nRegistry that want to register sources alongside a
langpack's (for example, to provide a locale-specific override for an
individual resource) need two things this module didn't previously
provide: an authoritative enumeration of currently-active langpacks at
the time the consumer initializes, and lifecycle notifications symmetric
to the existing webextension-langpack-startup topic.

We add a static Langpack.activeLangpackIds Set, mutated at the same
callsites that mutate the L10nRegistry, exposing the langpack metasource
strings (startupData.langpackId, which is not the addon's id). We then
fire a new webextension-langpack-shutdown observer topic before the langpack
removes its L10nRegistry sources, so consumers can clean up parallel
registrations in the same metasource before it goes away.

The first consumer in AboutNewTabResourceMapping in the next patch in this
series.

Attachment #9598553 - Flags: approval-mozilla-release?

firefox-release Uplift Approval Request

  • User impact if declined/Reason for urgency: Users with non-en-US langpacks installed (So non-en-US users on MSIX on Windows, Linux) may find some of their New Tab UI isn't localized properly, and is falling back to en-US.
  • Code covered by automated testing?: yes
  • Fix verified in Nightly?: no
  • Needs manual QE testing?: yes
  • Steps to reproduce for manual QE testing: Ensure that New Tab 153.5.20260615.213953 is installed. This may require you to force enroll in https://experimenter.services.mozilla.com/nimbus/new-tab-153520260615213953-to-release-152-wcw-v4/summary/.

Install an alternative langpack for release or beta, and ensure that recent strings are available in the relevant locale.

Then, in New Tab, open up the devtools console, and paste / execute this command:

(await document.l10n.formatMessages(["home-homepage-title"]))[0].attributes[0].value

and ensure that a string is returned ("Homepage" in en-US, but something appropriate for the installed langpack).

  • Risk associated with taking this patch: low
  • Explanation of risk level: This set of patches includes unit tests, and while it's scary that it has C++ changes, those changes really just add an observer notification that only the New Tab listens to. Same with the extensions change, which just exposes some things for New Tab to listen to. So really, the blast radius is restricted to New Tab - and I'm fairly confident we've got this right.
  • String changes made/needed?: None.
  • Is Android affected?: no
Attachment #9598554 - Flags: approval-mozilla-release?

The L10nRegistry solver builds bundles atomically per (locale, metasource):
so every required resource must be satisfiable from sources in that
metasource for that locale, or no bundle is produced.

The "app" metasource's non-newtab sources (toolkit, browser) are packaged en-US
only, so with a non-English langpack the (locale, "app") bundle can never be
built — and the train-hop newtab XPI's locale-specific strings are
unreachable, falling through to en-US. That is why train-hop-only widget
strings (added to the XPI but not yet present in any langpack) were
rendering in the wrong language.

We make AboutNewTabResourceMapping also register a shadow newtab
L10nFileSource into each active langpack's metasource, enumerated via
Langpack.activeLangpackIds and kept in sync with
webextension-langpack-startup/-shutdown observer notifications). Within the
(locale, langpack) bundle, the solver now yields two valid orderings: one
with the langpack's older newtab.ftl, one with the XPI's. Fluent falls
through the former on missing keys and resolves train-hop-only strings
from the latter, while strings the langpack already translates continue
to come from the langpack.

Attachment #9598548 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9598549 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9598550 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9598547 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9598552 - Flags: approval-mozilla-release? → approval-mozilla-release+
Attachment #9598553 - Flags: approval-mozilla-release? → approval-mozilla-release+
Attachment #9598554 - Flags: approval-mozilla-release? → approval-mozilla-release+
Attachment #9598551 - Flags: approval-mozilla-release? → approval-mozilla-release+

Rolled back from beta and release for causing xpc failures

Note this passed in autoland.
Claude says:
The difference is the locale packaging of the build under test, not the code:

  • autoland / central: Android GeckoView test builds are single-locale en-US. Available locales is trivially {en-US}. Registering an en-US source → recomputed list is still {en-US} → no change → topic doesn't fire → PASS.
  • beta / release: Android GeckoView is built multi-locale (it ships all the shipping locales). Available locales is a large list. Registering/removing a source perturbs the recomputed list (membership and/or ordering) enough that SetAvailableLocales sees a difference, re-negotiates, and the negotiated set changes → intl:app-locales-changed fires → assertion !fired is false → FAIL.
Attachment #9598547 - Flags: approval-mozilla-beta+ → approval-mozilla-beta?
Attachment #9598548 - Flags: approval-mozilla-beta+ → approval-mozilla-beta?
Attachment #9598549 - Flags: approval-mozilla-beta+ → approval-mozilla-beta?
Attachment #9598550 - Flags: approval-mozilla-beta+ → approval-mozilla-beta?
Attachment #9598551 - Flags: approval-mozilla-release+ → approval-mozilla-release?
Attachment #9598552 - Flags: approval-mozilla-release+ → approval-mozilla-release?
Attachment #9598553 - Flags: approval-mozilla-release+ → approval-mozilla-release?
Attachment #9598554 - Flags: approval-mozilla-release+ → approval-mozilla-release?
Attachment #9598554 - Flags: approval-mozilla-release? → approval-mozilla-release+
Attachment #9598553 - Flags: approval-mozilla-release? → approval-mozilla-release+
Attachment #9598552 - Flags: approval-mozilla-release? → approval-mozilla-release+
Attachment #9598551 - Flags: approval-mozilla-release? → approval-mozilla-release+
Attachment #9598551 - Flags: approval-mozilla-release+ → approval-mozilla-release?
Attachment #9598553 - Flags: approval-mozilla-release+ → approval-mozilla-release?
Attachment #9598554 - Flags: approval-mozilla-release+ → approval-mozilla-release?
Attachment #9598552 - Flags: approval-mozilla-release+ → approval-mozilla-release?
QA Whiteboard: [qa-triage-done-c154/b153] [qa-ver-needed-c154/b153]
Pushed by rperta@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/17b0783f75b7 https://hg.mozilla.org/mozilla-central/rev/896e001153ff Part 1: Fire intl:l10n-sources-changed when L10nRegistry sources mutate. r=eemeli https://github.com/mozilla-firefox/firefox/commit/4f43c549a840 https://hg.mozilla.org/mozilla-central/rev/0d14db284fc2 Part 1.5: Have AboutNewTabChild retrigger translation of about:newtab on intl:l10n-sources-changed. r=maxx https://github.com/mozilla-firefox/firefox/commit/f1c5a3c77480 https://hg.mozilla.org/mozilla-central/rev/828a785c733d Part 2: Expose active langpack ids and a webextension-langpack-shutdown observer topic. r=robwu
Blocks: 2048663

The test asserted that registering an L10nFileSource with a locale
already in availableLocales would not fire intl:app-locales-changed.
But L10nRegistry::getAvailableLocales builds its result from a Rust
HashSet, whose iteration order is platform-randomized, and
LocaleService::SetAvailableLocales compares as an order-sensitive
nsTArray, so a no-op-for-the-set registration can still cascade
through LocalesChanged on platforms where the order differs
(reproducibly on Android shippable).

This was a belt-and-suspenders test I added for the first iteration of
the patches for bug 2046945, when we were having Localization.cpp flush
its internal notion of bundles when the sources changed. Since we're
no longer doing that, this test is just getting in the way.

Attachment #9599062 - Flags: approval-mozilla-release?

Comment on attachment 9599062 [details]
Bug 2046945 - Remove platform-fragile test_topic_separation_from_app_locales_changed r?eemeli!

Revision D307673 was moved to bug 2048663. Setting attachment 9599062 [details] to obsolete.

Attachment #9599062 - Attachment is obsolete: true
Attachment #9599062 - Flags: approval-mozilla-release?
QA Whiteboard: [qa-triage-done-c154/b153] [qa-ver-needed-c154/b153] → [qa-triage-done-c154/b153] [qa-ver-needed-c154/b153][uplift]

Long-lived Localization instances cache the bundles they generate on first
use. Until now, no observer notification fired when sources were registered,
updated, or removed in L10nRegistry, so those caches were never invalidated;
any source registered after startup (e.g. by AboutNewTabResourceMapping when
a train-hopped newtab XPI is active) was invisible to already-translated
documents.

We introduce a new intl:l10n-sources-changed observer topic, fired by
L10nRegistry in both the parent (L10nRegistrySendUpdateL10nFileSources) and
content (RegisterFileSourcesFromParentProcess) processes after the registry
has been mutated. Localization::Observe now listens for it and drops cached
bundles, mirroring its existing handling of intl:app-locales-changed.

A dedicated topic is used rather than reusing intl:app-locales-changed so
the ~30 other observers that care only about negotiated-locale changes
(font list, mozIntl caches, sidebar, tabbrowser, …) aren't woken on every
source mutation.

Attachment #9599291 - Flags: approval-mozilla-beta?
Attachment #9599292 - Flags: approval-mozilla-beta?

Consumers of L10nRegistry that want to register sources alongside a
langpack's (for example, to provide a locale-specific override for an
individual resource) need two things this module didn't previously
provide: an authoritative enumeration of currently-active langpacks at
the time the consumer initializes, and lifecycle notifications symmetric
to the existing webextension-langpack-startup topic.

We add a static Langpack.activeLangpackIds Set, mutated at the same
callsites that mutate the L10nRegistry, exposing the langpack metasource
strings (startupData.langpackId, which is not the addon's id). We then
fire a new webextension-langpack-shutdown observer topic before the langpack
removes its L10nRegistry sources, so consumers can clean up parallel
registrations in the same metasource before it goes away.

The first consumer in AboutNewTabResourceMapping in the next patch in this
series.

Attachment #9599293 - Flags: approval-mozilla-beta?

The L10nRegistry solver builds bundles atomically per (locale, metasource):
so every required resource must be satisfiable from sources in that
metasource for that locale, or no bundle is produced.

The "app" metasource's non-newtab sources (toolkit, browser) are packaged en-US
only, so with a non-English langpack the (locale, "app") bundle can never be
built — and the train-hop newtab XPI's locale-specific strings are
unreachable, falling through to en-US. That is why train-hop-only widget
strings (added to the XPI but not yet present in any langpack) were
rendering in the wrong language.

We make AboutNewTabResourceMapping also register a shadow newtab
L10nFileSource into each active langpack's metasource, enumerated via
Langpack.activeLangpackIds and kept in sync with
webextension-langpack-startup/-shutdown observer notifications). Within the
(locale, langpack) bundle, the solver now yields two valid orderings: one
with the langpack's older newtab.ftl, one with the XPI's. Fluent falls
through the former on missing keys and resolves train-hop-only strings
from the latter, while strings the langpack already translates continue
to come from the langpack.

Attachment #9599294 - Flags: approval-mozilla-beta?

Long-lived Localization instances cache the bundles they generate on first
use. Until now, no observer notification fired when sources were registered,
updated, or removed in L10nRegistry, so those caches were never invalidated;
any source registered after startup (e.g. by AboutNewTabResourceMapping when
a train-hopped newtab XPI is active) was invisible to already-translated
documents.

We introduce a new intl:l10n-sources-changed observer topic, fired by
L10nRegistry in both the parent (L10nRegistrySendUpdateL10nFileSources) and
content (RegisterFileSourcesFromParentProcess) processes after the registry
has been mutated. Localization::Observe now listens for it and drops cached
bundles, mirroring its existing handling of intl:app-locales-changed.

A dedicated topic is used rather than reusing intl:app-locales-changed so
the ~30 other observers that care only about negotiated-locale changes
(font list, mozIntl caches, sidebar, tabbrowser, …) aren't woken on every
source mutation.

Attachment #9599296 - Flags: approval-mozilla-release?
Attachment #9599297 - Flags: approval-mozilla-release?

Consumers of L10nRegistry that want to register sources alongside a
langpack's (for example, to provide a locale-specific override for an
individual resource) need two things this module didn't previously
provide: an authoritative enumeration of currently-active langpacks at
the time the consumer initializes, and lifecycle notifications symmetric
to the existing webextension-langpack-startup topic.

We add a static Langpack.activeLangpackIds Set, mutated at the same
callsites that mutate the L10nRegistry, exposing the langpack metasource
strings (startupData.langpackId, which is not the addon's id). We then
fire a new webextension-langpack-shutdown observer topic before the langpack
removes its L10nRegistry sources, so consumers can clean up parallel
registrations in the same metasource before it goes away.

The first consumer in AboutNewTabResourceMapping in the next patch in this
series.

Attachment #9599298 - Flags: approval-mozilla-release?

The L10nRegistry solver builds bundles atomically per (locale, metasource):
so every required resource must be satisfiable from sources in that
metasource for that locale, or no bundle is produced.

The "app" metasource's non-newtab sources (toolkit, browser) are packaged en-US
only, so with a non-English langpack the (locale, "app") bundle can never be
built — and the train-hop newtab XPI's locale-specific strings are
unreachable, falling through to en-US. That is why train-hop-only widget
strings (added to the XPI but not yet present in any langpack) were
rendering in the wrong language.

We make AboutNewTabResourceMapping also register a shadow newtab
L10nFileSource into each active langpack's metasource, enumerated via
Langpack.activeLangpackIds and kept in sync with
webextension-langpack-startup/-shutdown observer notifications). Within the
(locale, langpack) bundle, the solver now yields two valid orderings: one
with the langpack's older newtab.ftl, one with the XPI's. Fluent falls
through the former on missing keys and resolves train-hop-only strings
from the latter, while strings the langpack already translates continue
to come from the langpack.

Attachment #9599299 - Flags: approval-mozilla-release?
Attachment #9599291 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9599292 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9599293 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9599294 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9599296 - Flags: approval-mozilla-release? → approval-mozilla-release+
Attachment #9599297 - Flags: approval-mozilla-release? → approval-mozilla-release+
Attachment #9599298 - Flags: approval-mozilla-release? → approval-mozilla-release+
Attachment #9599299 - Flags: approval-mozilla-release? → approval-mozilla-release+
Flags: in-testsuite+
Flags: needinfo?(mconley)

Added to the 152.0.2 relnotes.

Attachment #9598550 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9598549 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9598548 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9598547 - Flags: approval-mozilla-beta? → approval-mozilla-beta+

Verified that this is fixed on Firefox 152.0.2, Firefox 153.0b3 and Firefox 154.0a1 (2026-06-21) by following the info provided in Comment 29. Tests were performed on macOS 26.5.1, Windows 11 and Ubuntu 26.04.

Status: RESOLVED → VERIFIED
QA Whiteboard: [qa-triage-done-c154/b153] [qa-ver-needed-c154/b153][uplift] → [qa-triage-done-c154/b153] [qa-ver-done-c154/b153][uplift]
Flags: qe-verify+
QA Contact: csasca
Attachment #9598551 - Attachment is obsolete: true
Attachment #9598551 - Flags: approval-mozilla-release?
Attachment #9598552 - Attachment is obsolete: true
Attachment #9598552 - Flags: approval-mozilla-release?
Attachment #9598553 - Attachment is obsolete: true
Attachment #9598553 - Flags: approval-mozilla-release?
Attachment #9598554 - Attachment is obsolete: true
Attachment #9598554 - Flags: approval-mozilla-release?
Duplicate of this bug: 2049106
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: