Skip to content

Fix: OrchardCore.Setup silently overrides tenant localization settings - #19898

Open
DavidHolmlabs wants to merge 2 commits into
OrchardCMS:mainfrom
DavidHolmlabs:fix/admin-culture-picker-setup-localization-override
Open

DavidHolmlabs wants to merge 2 commits into
OrchardCMS:mainfrom
DavidHolmlabs:fix/admin-culture-picker-setup-localization-override

Conversation

@DavidHolmlabs

@DavidHolmlabs DavidHolmlabs commented Sep 17, 2026

Copy link
Copy Markdown

Summary

OrchardCore.Setup.Startup.Configure() unconditionally calls app.UseRequestLocalization(...), using its own hard-coded, setup-wizard-only culture list (~20 languages). Nothing disables the OrchardCore.Setup feature once a tenant finishes setup, and this Startup has no ConfigureOrder override, so it runs after OrchardCore.Localization.Startup (ConfigureOrder = -100).

Both resolve the same shared IOptions<RequestLocalizationOptions>.Value instance, and AddSupportedCultures/AddSupportedUICultures replace SupportedCultures/SupportedUICultures rather than merge into them. So on every running (already set-up) tenant, OrchardCore.Setup's hard-coded culture list silently clobbers the tenant's real LocalizationSettings.SupportedCultures right after OrchardCore.Localization correctly configures it — and since Setup's middleware is registered second, it also runs last and wins.

Symptom

The admin culture picker (OrchardCore.Localization.AdminCulturePicker) sets its cookie correctly, but any tenant-configured culture that isn't also in the setup wizard's hard-coded list (most regional variants without an OrchardCore admin translation — e.g. sl-SI) is silently rejected by RequestLocalizationMiddleware, and the request falls back to the tenant's default culture. Cultures that happen to overlap with the hard-coded list (or whose parent does, when "fall back to parent culture" is enabled) appear to work, which makes the bug confusing to diagnose — it looks culture-specific rather than systemic.

Confirmed via Serilog.MinimumLevel.Override["Microsoft.AspNetCore.Localization"] = "Debug", which logs AdminCookieCultureProvider returned the following unsupported cultures [...], and via dumping the live IOptions<RequestLocalizationOptions>.Value, which showed exactly OrchardCore.Setup's hard-coded list instead of the tenant's configured cultures.

Fix

Guard the request-localization configuration in OrchardCore.Setup.Startup.Configure() behind ShellSettings.IsUninitialized(). The setup wizard's own culture list is only relevant while the tenant genuinely hasn't been set up yet; once it's running, OrchardCore.Localization's configuration (driven by the tenant's real Localization settings) should be the only source of truth. The route registration is left untouched — this only affects the localization options mutation.

Workaround (for anyone hitting this before this ships)

Disable the OrchardCore.Setup feature on any tenant that has already completed setup (Admin → Configuration → Features → Setup → Disable). It's only needed for the initial tenant-provisioning wizard.

Test plan

  • dotnet build src/OrchardCore.Modules/OrchardCore.Setup/OrchardCore.Setup.csproj — 0 errors, both before and after pulling latest main
  • Reproduced and verified the fix live against a real multi-tenant OrchardCore app: with OrchardCore.Setup enabled, a tenant-configured culture (sl-SI) not in the setup wizard's hard-coded list was silently rejected; disabling the feature (the operational equivalent of this code fix not mattering once the tenant is running) immediately resolved it
  • Would appreciate a maintainer sanity-check on whether the actual first-run setup wizard flow (an uninitialized tenant, ShellSettings.State == Uninitialized) still localizes correctly with this change — the guarded branch should behave identically to before in that case, but I don't have an easy way to exercise the very first setup request in my repro environment

🤖 Generated with Claude Code

…etup

OrchardCore.Setup.Startup.Configure() unconditionally calls
UseRequestLocalization() with its own hard-coded, setup-wizard-only culture
list. Since this feature commonly stays enabled after a tenant finishes
setup, and its Startup has no ConfigureOrder override, it runs after
OrchardCore.Localization.Startup (ConfigureOrder -100) and registers a
second RequestLocalizationMiddleware on the same shared
RequestLocalizationOptions instance. AddSupportedCultures/
AddSupportedUICultures replace rather than merge the list, so this silently
discards the tenant's real Localization settings (Admin > Configuration >
Settings > Localization) in favor of the setup wizard's ~20-language list.

Symptom: the admin culture picker cookie is set correctly, but any
configured culture that isn't also in the setup wizard's hard-coded list
(most regional variants, e.g. sl-SI) is silently rejected and the request
falls back to the tenant's default culture instead.

Fix: only run this module's own request-localization configuration while
the tenant is still uninitialized (ShellSettings.IsUninitialized()). Once
a tenant is running, its real Localization settings should be the only
source of truth for RequestLocalizationOptions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Thank you for submitting your first pull request, awesome! 🚀 If you haven't already, please take a moment to review our contribution guide. This guide provides helpful information to ensure your contribution aligns with our standards. A core team member will review your pull request.
If you like Orchard Core, please star our repo and join our community channels.

@DavidHolmlabs

DavidHolmlabs commented Sep 17, 2026 via email

Copy link
Copy Markdown
Author

@sebastienros

Copy link
Copy Markdown
Member

Would you be able to add a functional test to verify it's doing what you need now and we don't regress?

Regresses OrchardCore.Setup.Startup silently re-applying its own
hard-coded, setup-wizard-only culture list once a tenant is running
and the Setup feature is enabled, which discards cultures configured
in the tenant's own Localization settings (e.g. "sl-SI", requested by
Sebastien Ros for coverage of #987490b).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@DavidHolmlabs

DavidHolmlabs commented Sep 22, 2026 via email

Copy link
Copy Markdown
Author

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants