From 6a29742d25d6bc9f6e0634a5d995cccf6fde8c18 Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Fri, 5 Jun 2026 11:00:18 -0400 Subject: [PATCH 1/3] Validate l10n ID is non-empty in GetDynamicString and XliffTransUnitUpdater (#104) An empty string ID propagated silently through the system, producing a malformed .xlf file that crashed the application on next launch. Added ArgumentException at the GetDynamicString/GetDynamicStringOrEnglish entry points and a defensive early-return in XliffTransUnitUpdater.Update mirroring the existing LangId guard. --- src/L10NSharp/LocalizationManagerInternal.cs | 4 ++++ src/L10NSharp/XLiffUtils/XliffTransUnitUpdater.cs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/L10NSharp/LocalizationManagerInternal.cs b/src/L10NSharp/LocalizationManagerInternal.cs index e8ecef8..e3996ed 100644 --- a/src/L10NSharp/LocalizationManagerInternal.cs +++ b/src/L10NSharp/LocalizationManagerInternal.cs @@ -464,6 +464,8 @@ public static string GetDynamicString(string appId, string id, string englishTex /// ------------------------------------------------------------------------------------ public static string GetDynamicString(string appId, string id, string englishText, string comment) { + if (string.IsNullOrWhiteSpace(id)) + throw new ArgumentException("id may not be null or empty.", nameof(id)); return GetDynamicStringOrEnglish(appId, id, englishText, comment, LocalizationManager.UILanguageId); } @@ -482,6 +484,8 @@ public static string GetDynamicString(string appId, string id, string englishTex public static string GetDynamicStringOrEnglish(string appId, string id, string englishText, string comment, string langId) { + if (string.IsNullOrWhiteSpace(id)) + throw new ArgumentException("id may not be null or empty.", nameof(id)); // This happens in unit test environments or apps that have imported a library that // is localized, but the app itself isn't initializing L10N yet. if (LoadedManagers.Count == 0) diff --git a/src/L10NSharp/XLiffUtils/XliffTransUnitUpdater.cs b/src/L10NSharp/XLiffUtils/XliffTransUnitUpdater.cs index 6d9cd27..c8a028c 100644 --- a/src/L10NSharp/XLiffUtils/XliffTransUnitUpdater.cs +++ b/src/L10NSharp/XLiffUtils/XliffTransUnitUpdater.cs @@ -46,6 +46,8 @@ internal bool Update(LocalizingInfo locInfo) // Can't do anything without a language id. if (string.IsNullOrEmpty(locInfo.LangId)) return _updated; + if (string.IsNullOrEmpty(locInfo.Id)) + return _updated; var xliffSource = _stringCache.GetDocument(_defaultLang); Debug.Assert(xliffSource != null); From 921de44f275bbbcb2688c3298c0a21dc05361970 Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Fri, 5 Jun 2026 11:26:23 -0400 Subject: [PATCH 2/3] Update CHANGELOG for #104 breaking change --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 895773a..22b8916 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [L10NSharp] Removed emailForSubmissions parameter from LocalizationManager.Create. Since the localization dialog was jettisoned, it no longer makes sense to store this information on the localization manager. - [L10NSharp.Windows.Forms] Removed emailForSubmissions parameter (8th parameter) from LocalizationManagerWinforms.Create. Since the localization dialog was jettisoned, it no longer makes sense to store this information on the localization manager. - [L10NSharp] Replaced the .NET 8.0 target with .NET Standard 2.0 for broader compatibility. +- [L10NSharp] BREAKING CHANGE: `LocalizationManager.GetString`, `GetDynamicString`, and `GetDynamicStringOrEnglish` now throw `ArgumentException` when called with a null or empty string ID. Previously, empty IDs were silently accepted and could produce a malformed XLIFF file that crashed on next launch. (#104) ### Fixed From 6be1a222c09cd9bafeb78d40a9fa2cc692485876 Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Fri, 5 Jun 2026 11:42:24 -0400 Subject: [PATCH 3/3] Add regression test: empty id throws ArgumentException (#104) --- .../LocalizationManagerTestsBase.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/L10NSharp.Tests/LocalizationManagerTestsBase.cs b/src/L10NSharp.Tests/LocalizationManagerTestsBase.cs index 5189f53..9949eff 100644 --- a/src/L10NSharp.Tests/LocalizationManagerTestsBase.cs +++ b/src/L10NSharp.Tests/LocalizationManagerTestsBase.cs @@ -292,6 +292,20 @@ public void GetDynamicStringInEnglish_NoDefault_FindsEnglish() } } + [Test] + public void GetDynamicString_WithEmptyId_ThrowsArgumentException() + { + Assert.Throws(() => + LocalizationManager.GetDynamicString(AppId, "", "some text")); + } + + [Test] + public void GetDynamicStringOrEnglish_WithEmptyId_ThrowsArgumentException() + { + Assert.Throws(() => + LocalizationManagerInternal.GetDynamicStringOrEnglish(AppId, "", "some text", null, "en")); + } + [Test] public void GetDynamicStringOrEnglish_LmDisposed_GivesUsefulException() {