Skip to content

Build: app-local ICU is now configurable at runtime#23009

Open
Migaroez wants to merge 2 commits into
v17/devfrom
v17/improvement/make-localICU-configurable
Open

Build: app-local ICU is now configurable at runtime#23009
Migaroez wants to merge 2 commits into
v17/devfrom
v17/improvement/make-localICU-configurable

Conversation

@Migaroez
Copy link
Copy Markdown
Contributor

Prerequisites

  • I have added steps to test this contribution in the description below

Fixes #22758. Non funtional breaking approach to #22771.

Description

#22758 reports that an Umbraco app built on Linux or Windows crashes on macOS with Failed to load app-local ICU: libicuuc.68.2.0.9.dylib. Root cause: RuntimeIdentifier is build-time, so the RuntimeHostConfigurationOption for System.Globalization.AppLocalIcu gets baked into runtimeconfig.json whenever the build host is not macOS — even for cross-platform deployment artifacts.

PR #22771 fixes this by removing app-local ICU entirely. That works, but it also throws out the original cross-platform consistency guarantee added in #11276 and silently changes globalization behavior on Windows Server 2016 / Windows 10 1703–1809 (which fall back to NLS without app-local ICU — see Microsoft Learn).

This PR instead keeps the default outcome but introduces an MSBuild property knob (UmbracoUseAppLocalIcu) plus a documented post-publish escape hatch. The default still enables app-local ICU 72.1.0.3 for Linux/Windows builds; deployers who need different behavior on a particular target (macOS, or anywhere else) can override without rebuilding.

Override paths

Scope How
Build / publish dotnet publish -p:UmbracoUseAppLocalIcu=false (or set the property in .csproj / Directory.Build.props)
Post-publish, no rebuild Remove or edit System.Globalization.AppLocalIcu under runtimeOptions.configProperties in the published *.runtimeconfig.json
Env var fallback DOTNET_SYSTEM_GLOBALIZATION_APPLOCALICU is honored only when the runtimeconfig has no AppLocalIcu key — i.e. as a fallback, not as a runtime override of a JSON value already present. The general .NET 9 env-var-precedence rule does not apply here (verified on .NET 10); This is probably because AppLocalIcu is resolved by the native host before the CLR boots. Use the build-time or post-publish path for an actual override.

How to test

  1. Default outcome is unchanged:
    dotnet publish src/Umbraco.Web.UI/Umbraco.Web.UI.csproj -c Release -o ./out

Expected: out/Umbraco.Web.UI.runtimeconfig.json contains "System.Globalization.AppLocalIcu": "72.1.0.3" and out/runtimes/linux-x64/native/libicuuc.so.72.1.0.3 + out/runtimes/win-x64/native/icuuc72.dll are present.

  1. Build-time opt-out:
    dotnet publish src/Umbraco.Web.UI/Umbraco.Web.UI.csproj -c Release -p:UmbracoUseAppLocalIcu=false -o ./out

Expected: AppLocalIcu key absent from runtimeconfig.json; no runtimes/<rid>/native/*icu* files; publish output ~3 MB smaller (ICU natives gone).

  1. Post-publish override (reproduces and resolves Because of System.Globalization.AppLocalIcu, Windows and Linux Umbraco builds will not run on macOS. #22758 without rebuilding):
  • Publish on Linux/Windows with defaults.
  • Open *.runtimeconfig.json and delete the System.Globalization.AppLocalIcu line (or change its value).
  • Run on the target host — no Failed to load app-local ICU crash; falls back to system ICU.
  1. Regression check: app-local ICU still loads on Linux/Windows builds. The runtimeconfig.json contains the entry; the runtime loads icuuc72.dll / libicuuc.so.72.1.0.3 from the publish output as before.

@claude
Copy link
Copy Markdown

claude Bot commented May 28, 2026

Claude finished @Migaroez's task in 6m 2s —— View job


PR Review Complete

  • Gather context and understand request
  • Load review standards and documentation
  • Collect and analyze changed files (3 files, config-only classification)
  • Raw code review
  • Impact analysis (skipped — config-only PR)
  • Breaking changes check (none detected)
  • Post review findings (5 inline comments + summary review)

Summary

Verdict: Approved with Suggestions

The core implementation is solid — UmbracoUseAppLocalIcu is an idiomatic MSBuild property knob that fixes the macOS crash (#22758) without dropping the Windows/Linux globalization guarantee. Default behavior is preserved.

Two minor documentation inconsistencies were flagged in inline comments:

  1. Misleading env var override (Umbraco.Web.UI.csproj:44, template lines 28/61) — the comment implies DOTNET_SYSTEM_GLOBALIZATION_APPLOCALICU is a valid runtime override, but this env var cannot override a value already in runtimeconfig.json (documented in CLAUDE.md, verified on .NET 10).

  2. Self-referential cross-reference (UmbracoProject.csproj:30 and :63) — the "keep in sync with" comment points to the file it's in; should reference src/Umbraco.Web.UI/Umbraco.Web.UI.csproj instead.

@Migaroez
Copy link
Copy Markdown
Contributor Author

Migaroez commented May 28, 2026

@JasonElkin If you could take this one out for a spin and see if it satisfies your needs that would be great. If needed, I can run a "nightly" build on this branch so it ends up on myget.

@Migaroez Migaroez changed the title app-local ICU is now configurable at runtime Build: app-local ICU is now configurable at runtime May 28, 2026
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review - Target: origin/v17/dev - Classified as: Config-only. See inline comments for suggestions. Two minor documentation issues found: (1) misleading env var override bullet in all three comment blocks - the env var cannot override a runtimeconfig.json entry already present; (2) self-referential cross-reference in UmbracoProject.csproj lines 30 and 63. Core implementation is correct. Approved with Suggestions.

Comment thread src/Umbraco.Web.UI/Umbraco.Web.UI.csproj Outdated
Comment thread templates/UmbracoProject/UmbracoProject.csproj Outdated
Comment thread templates/UmbracoProject/UmbracoProject.csproj Outdated
Comment thread templates/UmbracoProject/UmbracoProject.csproj Outdated
Comment thread templates/UmbracoProject/UmbracoProject.csproj Outdated
@Migaroez Migaroez added area/backend category/dx Developer experience labels Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/backend category/dx Developer experience

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant