V16: Localization extensions load unordered#19474
Merged
leekelleher merged 12 commits intorelease/16.0from Jun 3, 2025
Merged
Conversation
also added filter() and distinctUntilChanged() to ensure the logic is not run more often than what is needed
Contributor
There was a problem hiding this comment.
Pull Request Overview
This PR improves the loading of localization extensions by always reloading them and ensuring that translations are applied in the correct priority order using rxjs’s switchMap for cancellation of outdated loads. Key changes include:
- Refactoring the localization registry to remove previously loaded alias checks and always reload extensions.
- Introducing a new observable pipeline with switchMap, distinctUntilChanged, and filter to cancel stale translation loads.
- Enhancing tests to validate asynchronous overrides and correct language/direction setting.
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/packages/core/localization/registry/localization.registry.ts | Refactored to use a new rxjs pipeline ensuring correct ordering & cancellation and removing loaded alias checks; added subscription handling and array comparison helper. |
| src/packages/core/localization/registry/localization.registry.test.ts | Updated tests to register multiple extensions at once and test weight-based translation overrides. |
| src/packages/core/localization/localize.element.test.ts | Added tests for async localization overrides and fallback language scenarios; updated test data structures. |
| src/external/rxjs/index.ts | Added re-exports for additional rxjs operators to support new registry logic. |
leekelleher
approved these changes
Jun 3, 2025
Member
leekelleher
left a comment
There was a problem hiding this comment.
Amazing description and flow charts! 🤩
Tested out and it works as expected! 🚀
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This pull request is difficult to explain, but in summary it fixes #19464.
It makes two changes to the
UmbLocalizationRegistry:First change: Do not check if localizations are already loaded; load them always when something changes
Old Logic (with alias/diff check): Risk of Stale/Un-overridden Translations
flowchart TD A[Language Change or Extension Registered] --> B[Check extension alias against loaded list] B -- Alias already loaded --> C[Skip registration] B -- Alias not loaded --> D[Register translations] D --> E[Translations in localization manager] C --> E E --> F[Result: Some keys may NOT be overridden if new extension has lower weight]New Logic (Always Register All, Sorted by Weight): Reliable Overrides
flowchart TD A[Language Change or Extension Registered] --> B[Collect all matching extensions] B --> C[Sort all by weight, lowest weight = highest priority] C --> D[Register ALL translations in order] D --> E[Translations in localization manager] E --> F[Result: Lower weight always overrides higher, keys are reliably overridden]Second change: Use the power of rxjs with
switchMapto ensure that localizations are loaded in the order they are receivedFor example, if we imagined a user would register the extensions like
en->en-us->en-us->en-us, we would want all of them to finish, e.g. they could register their own keys each and override previous keys as well:Old Logic (with
combineLatest)sequenceDiagram participant User participant Registry participant Loader User->>Registry: Registers "en" Registry->>Loader: Start loading "en" User->>Registry: Quickly registers "en-us" Registry->>Loader: Start loading "en, en-us" (queued) User->>Registry: Quickly registers "en-us" again Registry->>Loader: Start loading "en, en-us, en-us" (queued) User->>Registry: Quickly registers "en-us" a third time Registry->>Loader: Start loading "en, en-us, en-us, en-us" (queued) Loader-->>Registry: "en" finishes (may override) Loader-->>Registry: "en, en-us" finishes (may override) Loader-->>Registry: "en, en-us, en-us" finishes (may override) Loader-->>Registry: "en, en-us, en-us, en-us" finishes (final state) Note right of Registry: All loads run in order, but slow loads may override newer ones if not careful, so that the "en, en-us" could be final state.New Logic (with switchMap, cancellation of previous loads)
sequenceDiagram participant User participant Registry participant Loader User->>Registry: Registers "en" Registry->>Loader: Start loading "en" User->>Registry: Quickly registers "en-us" Registry--xLoader: Cancel loading "en" Registry->>Loader: Start loading "en, en-us" User->>Registry: Quickly registers "en-us" again Registry--xLoader: Cancel loading "en, en-us" Registry->>Loader: Start loading "en, en-us, en-us" User->>Registry: Quickly registers "en-us" a third time Registry--xLoader: Cancel loading "en, en-us, en-us" Registry->>Loader: Start loading "en, en-us, en-us, en-us" Loader-->>Registry: "en, en-us, en-us, en-us" is allowed to finish (final state) Note right of Registry: Only the latest language set ("en, en-us, en-us, en-us") is loaded and applied and in that weighted order.Additionally, Copilot pointed out that if the user switches really fast between languages (for example en -> da -> de), and one of them loads through an async file or otherwise is delayed, it could actually mean that even though it would end up on "de", it would possibly apply the "da" translations. Now, they would never be shown to the user (wrong iso code), but it would possibly not have loaded in the custom translations from "de" in that case.
How to test
"en-us"<umb-localize key="your_key"></umb-localize>that the lowest weight wins