From 78fda5522c2776cb74d303050277144317fea0b0 Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Tue, 30 Jun 2026 15:16:40 -0400 Subject: [PATCH 1/5] Make WritingSystemSetupDialog controls localizable via L10NSharpExtender (#1337) Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 1 + .../UITests.cs | 17 +++++++ .../WritingSystemSetupDialog.Designer.cs | 44 ++++++++++++++----- .../WritingSystemSetupDialog.cs | 10 +++-- 4 files changed, 58 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7345a668f..81507156c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added +- [SIL.Windows.Forms.WritingSystems] Made WritingSystemSetupDialog controls localizable via L10NSharpExtender (#1337) - [SIL.Windows.Forms.Archiving, SIL.Windows.Forms.DblBundle] Added `net8.0-windows` target. - [SIL.Core.Clearshare] Added new classes MetadataCore, CreativeCommonsLicenseInfo, and CustomLicenseInfo; these are Winforms-free base versions of the classes Metadata, CreativeCommonsLicense, and CustomLicense. - [SIL.Core.Clearshare and SIL.Windows.Forms.Clearshare] Added LicenseUtils and LicenseWithImageUtils to handle the FromXmp method for creating a license. LicenseUtils constructs a bare license object that is Winforms-independent; LicenseWithImageUtils constructs a Winforms-dependent license object with access to license images. diff --git a/SIL.Windows.Forms.WritingSystems.Tests/UITests.cs b/SIL.Windows.Forms.WritingSystems.Tests/UITests.cs index 907e80286..26796adc1 100644 --- a/SIL.Windows.Forms.WritingSystems.Tests/UITests.cs +++ b/SIL.Windows.Forms.WritingSystems.Tests/UITests.cs @@ -14,6 +14,23 @@ namespace SIL.Windows.Forms.WritingSystems.Tests [TestFixture] public class UITests { + [Test] + [Apartment(ApartmentState.STA)] + public void WritingSystemSetupDialog_Construct_DoesNotThrow() + { + using (var folder = new TemporaryFolder("WS-Test-Smoke")) + { + var repository = LdmlInFolderWritingSystemRepository.Initialize(folder.Path); + Assert.DoesNotThrow(() => + { + using (var dlg = new WritingSystemSetupDialog(repository)) + { + Assert.That(dlg, Is.Not.Null); + } + }); + } + } + //NB: in Mar 2011, I couldn't get these to run in vs 2010 with resharper, because // of the need to be in single apartment thread mode. The app.config is there, requesting // it, but it doesn't work. So I had to plug in this CrossThreadTestRunner thing diff --git a/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.Designer.cs b/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.Designer.cs index 59bc3de53..d7b9566e4 100644 --- a/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.Designer.cs +++ b/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.Designer.cs @@ -36,11 +36,14 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); this._writingSystemSetupView = new WritingSystemSetupView(); this._closeButton = new System.Windows.Forms.Button(); this._openGlobal = new System.Windows.Forms.Button(); this._openDirectory = new System.Windows.Forms.Button(); this._openLabel = new System.Windows.Forms.Label(); + this._L10NSharpExtender = new L10NSharp.Windows.Forms.L10NSharpExtender(this.components); + ((System.ComponentModel.ISupportInitialize)(this._L10NSharpExtender)).BeginInit(); this.SuspendLayout(); // // _writingSystemSetupView @@ -53,42 +56,55 @@ private void InitializeComponent() this._writingSystemSetupView.Size = new System.Drawing.Size(841, 461); this._writingSystemSetupView.TabIndex = 0; // - // + // _L10NSharpExtender + // + this._L10NSharpExtender.LocalizationManagerId = "Palaso"; + this._L10NSharpExtender.PrefixForNewItems = "WritingSystemSetupDialog"; + // // _closeButton - // + // this._closeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this._closeButton.Location = new System.Drawing.Point(767, 444); this._closeButton.Name = "_closeButton"; this._closeButton.Size = new System.Drawing.Size(75, 23); this._closeButton.TabIndex = 1; this._closeButton.Text = "Close"; + this._L10NSharpExtender.SetLocalizableToolTip(this._closeButton, null); + this._L10NSharpExtender.SetLocalizationComment(this._closeButton, null); + this._L10NSharpExtender.SetLocalizingId(this._closeButton, "WritingSystemSetupDialog._closeButton"); this._closeButton.UseVisualStyleBackColor = true; this._closeButton.Click += new System.EventHandler(this._closeButton_Click); - // + // // _openGlobal - // + // this._openGlobal.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this._openGlobal.Location = new System.Drawing.Point(521, 444); this._openGlobal.Name = "_openGlobal"; this._openGlobal.Size = new System.Drawing.Size(75, 23); this._openGlobal.TabIndex = 2; this._openGlobal.Text = "Computer"; + this._L10NSharpExtender.SetLocalizableToolTip(this._openGlobal, null); + this._L10NSharpExtender.SetLocalizationComment(this._openGlobal, null); + this._L10NSharpExtender.SetLocalizingId(this._openGlobal, "WritingSystemSetupDialog._openGlobal"); this._openGlobal.UseVisualStyleBackColor = true; this._openGlobal.Click += new System.EventHandler(this._openGlobal_Click); - // + // // _openDirectory - // + // this._openDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this._openDirectory.Location = new System.Drawing.Point(602, 444); this._openDirectory.Name = "_openDirectory"; this._openDirectory.Size = new System.Drawing.Size(75, 23); this._openDirectory.TabIndex = 4; this._openDirectory.Text = "Directory"; + this._L10NSharpExtender.SetLocalizableToolTip(this._openDirectory, null); + this._L10NSharpExtender.SetLocalizationComment(this._openDirectory, null); + this._L10NSharpExtender.SetLocalizingId(this._openDirectory, "WritingSystemSetupDialog._openDirectory"); this._openDirectory.UseVisualStyleBackColor = true; this._openDirectory.Click += new System.EventHandler(this._openDirectory_Click); - // + // // _openLabel - // + // this._openLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this._openLabel.AutoSize = true; this._openLabel.Location = new System.Drawing.Point(380, 448); @@ -96,9 +112,12 @@ private void InitializeComponent() this._openLabel.Size = new System.Drawing.Size(36, 13); this._openLabel.TabIndex = 10; this._openLabel.Text = "Open Writing Systems:"; - // + this._L10NSharpExtender.SetLocalizableToolTip(this._openLabel, null); + this._L10NSharpExtender.SetLocalizationComment(this._openLabel, null); + this._L10NSharpExtender.SetLocalizingId(this._openLabel, "WritingSystemSetupDialog._openLabel"); + // // WritingSystemSetupDialog - // + // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(855, 479); @@ -107,8 +126,12 @@ private void InitializeComponent() this.Controls.Add(this._openGlobal); this.Controls.Add(this._closeButton); this.Controls.Add(this._writingSystemSetupView); + this._L10NSharpExtender.SetLocalizableToolTip(this, null); + this._L10NSharpExtender.SetLocalizationComment(this, null); + this._L10NSharpExtender.SetLocalizingId(this, "WritingSystemSetupDialog.WindowTitle"); this.Name = "WritingSystemSetupDialog"; this.Text = "Writing Systems"; + ((System.ComponentModel.ISupportInitialize)(this._L10NSharpExtender)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -121,5 +144,6 @@ private void InitializeComponent() private System.Windows.Forms.Button _openGlobal; private System.Windows.Forms.Button _openDirectory; private System.Windows.Forms.Label _openLabel; + private L10NSharp.Windows.Forms.L10NSharpExtender _L10NSharpExtender; } } \ No newline at end of file diff --git a/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.cs b/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.cs index a066823c2..782ce9c22 100644 --- a/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.cs +++ b/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Forms; +using L10NSharp; using SIL.Windows.Forms.WritingSystems.WSTree; using SIL.WritingSystems; @@ -74,7 +75,8 @@ private void _closeButton_Click(object sender, EventArgs e) catch (ArgumentException exception) { MessageBox.Show ( - this, exception.Message, "Input Systems Error", + this, exception.Message, + LocalizationManager.GetString("WritingSystemSetupDialog.InputSystemsError", "Input Systems Error"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation ); } @@ -87,7 +89,7 @@ private void _openDirectory_Click(object sender, EventArgs e) openDir.RootFolder = Environment.SpecialFolder.Personal; // Set the help text description for the FolderBrowserDialog. - openDir.Description = "Select the folder with Writing Systems"; + openDir.Description = LocalizationManager.GetString("WritingSystemSetupDialog.SelectFolderDescription", "Select the folder with Writing Systems"); // Allow the user to create new files via the FolderBrowserDialog. openDir.ShowNewFolderButton = true; @@ -105,7 +107,7 @@ private void _openDirectory_Click(object sender, EventArgs e) dlg.WritingSystemSuggestor.SuggestVoice = true; dlg.WritingSystemSuggestor.OtherKnownWritingSystems = null; - dlg.Text = String.Format("Writing Systems in folder {0}", newDir); + dlg.Text = String.Format(LocalizationManager.GetString("WritingSystemSetupDialog.TitleWithFolder", "Writing Systems in folder {0}", "The {0} is replaced with the folder path."), newDir); dlg.Show(); } @@ -117,7 +119,7 @@ private void _openGlobal_Click(object sender, EventArgs e) dlg.WritingSystemSuggestor.SuggestVoice = true; dlg.WritingSystemSuggestor.OtherKnownWritingSystems = null; dlg.DisposeRepository = true; - dlg.Text = String.Format("Writing Systems for all users of this computer"); + dlg.Text = LocalizationManager.GetString("WritingSystemSetupDialog.TitleAllUsers", "Writing Systems for all users of this computer"); dlg.Show(); } From 64b172ee2d9a6ec43e958e38ecc282f680e9bd2a Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Tue, 30 Jun 2026 15:19:14 -0400 Subject: [PATCH 2/5] Remove issue number from CHANGELOG entry --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81507156c..30856eaaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Change Log +# Change Log All notable changes to this project will be documented in this file. @@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added -- [SIL.Windows.Forms.WritingSystems] Made WritingSystemSetupDialog controls localizable via L10NSharpExtender (#1337) +- [SIL.Windows.Forms.WritingSystems] Made WritingSystemSetupDialog controls localizable via L10NSharpExtender - [SIL.Windows.Forms.Archiving, SIL.Windows.Forms.DblBundle] Added `net8.0-windows` target. - [SIL.Core.Clearshare] Added new classes MetadataCore, CreativeCommonsLicenseInfo, and CustomLicenseInfo; these are Winforms-free base versions of the classes Metadata, CreativeCommonsLicense, and CustomLicense. - [SIL.Core.Clearshare and SIL.Windows.Forms.Clearshare] Added LicenseUtils and LicenseWithImageUtils to handle the FromXmp method for creating a license. LicenseUtils constructs a bare license object that is Winforms-independent; LicenseWithImageUtils constructs a Winforms-dependent license object with access to license images. @@ -45,7 +45,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [SIL.Windows.Forms.Keyboarding] Removed Timer-based deferred IME conversion status restore from WindowsKeyboardSwitchingAdapter, which disrupted active Chinese Pinyin IME compositions (LT-22442). Added diagnostic tracing for keyboard switching and IME state. - [SIL.DictionaryServices] Fix memory leak in LiftWriter - [SIL.WritingSystems] Fix IetfLanguageTag.GetGeneralCode to handle cases when zh-CN or zh-TW is a prefix and not the whole string. -- [SIL.WritingSystems] More fixes to consistently use 繁体中文 and 简体中文 for Traditional and Simplified Chinese native language names, and Chinese (Traditional) and Chinese (Simplified) for their English names. +- [SIL.WritingSystems] More fixes to consistently use 繁体中文 and 简体中文 for Traditional and Simplified Chinese native language names, and Chinese (Traditional) and Chinese (Simplified) for their English names. - [SIL.Windows.Forms] Prevent BetterLabel from responding to OnTextChanged when it has been disposed. - [SIL.Windows.Forms] Prevent ContributorsListControl.GetContributionFromRow from throwing an exception when the DataGridView has no valid rows selected. - [SIL.Media] BREAKING CHANGE (subtle and unlikely): WindowsAudioSession.OnPlaybackStopped now passes itself as the sender instead of a private implementation object, making the event arguments correct. @@ -115,7 +115,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - [SIL.Windows.Forms] In `CustomDropDown.OnOpening`, fixed check that triggers timer to stop. -- [SIL.Windows.Forms] Fixed HtmlBrowserHandled.OnNewWindow to open external URLs (`target="_blank"`) in the system’s default browser instead of Internet Explorer. This improves behavior in SILAboutBox and other components that use the embedded browser. +- [SIL.Windows.Forms] Fixed HtmlBrowserHandled.OnNewWindow to open external URLs (`target="_blank"`) in the system’s default browser instead of Internet Explorer. This improves behavior in SILAboutBox and other components that use the embedded browser. ### Changed From a7757145ecd83b5c736ed5217375873c193e90f8 Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Tue, 30 Jun 2026 15:44:37 -0400 Subject: [PATCH 3/5] =?UTF-8?q?Mark=20smoke=20test=20Explicit=20=E2=80=94?= =?UTF-8?q?=20requires=20KeyboardController=20and=20LocalizationManager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SIL.Windows.Forms.WritingSystems.Tests/UITests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/SIL.Windows.Forms.WritingSystems.Tests/UITests.cs b/SIL.Windows.Forms.WritingSystems.Tests/UITests.cs index 26796adc1..b5bf8aab8 100644 --- a/SIL.Windows.Forms.WritingSystems.Tests/UITests.cs +++ b/SIL.Windows.Forms.WritingSystems.Tests/UITests.cs @@ -15,6 +15,7 @@ namespace SIL.Windows.Forms.WritingSystems.Tests public class UITests { [Test] + [Explicit("Requires KeyboardController and LocalizationManager infrastructure — run by hand")] [Apartment(ApartmentState.STA)] public void WritingSystemSetupDialog_Construct_DoesNotThrow() { From 95da2f54648526164941ff9825e62488d8213a08 Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Tue, 30 Jun 2026 16:18:38 -0400 Subject: [PATCH 4/5] Fix CHANGELOG encoding corruption Restore from base commit to fix double-encoded UTF-8 (Chinese characters and curly apostrophe were corrupted by PowerShell Get-Content/Set-Content mishandling UTF-8-without-BOM), then re-apply our entry using the Edit tool which preserves encoding correctly. Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30856eaaa..ffdc2e09b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Change Log +# Change Log All notable changes to this project will be documented in this file. @@ -45,7 +45,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [SIL.Windows.Forms.Keyboarding] Removed Timer-based deferred IME conversion status restore from WindowsKeyboardSwitchingAdapter, which disrupted active Chinese Pinyin IME compositions (LT-22442). Added diagnostic tracing for keyboard switching and IME state. - [SIL.DictionaryServices] Fix memory leak in LiftWriter - [SIL.WritingSystems] Fix IetfLanguageTag.GetGeneralCode to handle cases when zh-CN or zh-TW is a prefix and not the whole string. -- [SIL.WritingSystems] More fixes to consistently use 繁体中文 and 简体中文 for Traditional and Simplified Chinese native language names, and Chinese (Traditional) and Chinese (Simplified) for their English names. +- [SIL.WritingSystems] More fixes to consistently use 繁体中文 and 简体中文 for Traditional and Simplified Chinese native language names, and Chinese (Traditional) and Chinese (Simplified) for their English names. - [SIL.Windows.Forms] Prevent BetterLabel from responding to OnTextChanged when it has been disposed. - [SIL.Windows.Forms] Prevent ContributorsListControl.GetContributionFromRow from throwing an exception when the DataGridView has no valid rows selected. - [SIL.Media] BREAKING CHANGE (subtle and unlikely): WindowsAudioSession.OnPlaybackStopped now passes itself as the sender instead of a private implementation object, making the event arguments correct. @@ -115,7 +115,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - [SIL.Windows.Forms] In `CustomDropDown.OnOpening`, fixed check that triggers timer to stop. -- [SIL.Windows.Forms] Fixed HtmlBrowserHandled.OnNewWindow to open external URLs (`target="_blank"`) in the system’s default browser instead of Internet Explorer. This improves behavior in SILAboutBox and other components that use the embedded browser. +- [SIL.Windows.Forms] Fixed HtmlBrowserHandled.OnNewWindow to open external URLs (`target="_blank"`) in the system’s default browser instead of Internet Explorer. This improves behavior in SILAboutBox and other components that use the embedded browser. ### Changed From fdc054a631512ba964f7bd738651c9b809f289fd Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Tue, 30 Jun 2026 16:44:09 -0400 Subject: [PATCH 5/5] Use descriptive localization IDs without underscore prefixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Match the naming style of sibling dialogs (e.g. WSKeyboardControl.KeymanConfigurationLink, LanguageLookupDialog title) — no private-field underscore prefixes in IDs exposed to translators. Co-Authored-By: Claude Sonnet 4.6 --- .../WritingSystemSetupDialog.Designer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.Designer.cs b/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.Designer.cs index d7b9566e4..e0a29d465 100644 --- a/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.Designer.cs +++ b/SIL.Windows.Forms.WritingSystems/WritingSystemSetupDialog.Designer.cs @@ -71,7 +71,7 @@ private void InitializeComponent() this._closeButton.Text = "Close"; this._L10NSharpExtender.SetLocalizableToolTip(this._closeButton, null); this._L10NSharpExtender.SetLocalizationComment(this._closeButton, null); - this._L10NSharpExtender.SetLocalizingId(this._closeButton, "WritingSystemSetupDialog._closeButton"); + this._L10NSharpExtender.SetLocalizingId(this._closeButton, "WritingSystemSetupDialog.CloseButton"); this._closeButton.UseVisualStyleBackColor = true; this._closeButton.Click += new System.EventHandler(this._closeButton_Click); // @@ -85,7 +85,7 @@ private void InitializeComponent() this._openGlobal.Text = "Computer"; this._L10NSharpExtender.SetLocalizableToolTip(this._openGlobal, null); this._L10NSharpExtender.SetLocalizationComment(this._openGlobal, null); - this._L10NSharpExtender.SetLocalizingId(this._openGlobal, "WritingSystemSetupDialog._openGlobal"); + this._L10NSharpExtender.SetLocalizingId(this._openGlobal, "WritingSystemSetupDialog.ComputerButton"); this._openGlobal.UseVisualStyleBackColor = true; this._openGlobal.Click += new System.EventHandler(this._openGlobal_Click); // @@ -99,7 +99,7 @@ private void InitializeComponent() this._openDirectory.Text = "Directory"; this._L10NSharpExtender.SetLocalizableToolTip(this._openDirectory, null); this._L10NSharpExtender.SetLocalizationComment(this._openDirectory, null); - this._L10NSharpExtender.SetLocalizingId(this._openDirectory, "WritingSystemSetupDialog._openDirectory"); + this._L10NSharpExtender.SetLocalizingId(this._openDirectory, "WritingSystemSetupDialog.DirectoryButton"); this._openDirectory.UseVisualStyleBackColor = true; this._openDirectory.Click += new System.EventHandler(this._openDirectory_Click); // @@ -114,7 +114,7 @@ private void InitializeComponent() this._openLabel.Text = "Open Writing Systems:"; this._L10NSharpExtender.SetLocalizableToolTip(this._openLabel, null); this._L10NSharpExtender.SetLocalizationComment(this._openLabel, null); - this._L10NSharpExtender.SetLocalizingId(this._openLabel, "WritingSystemSetupDialog._openLabel"); + this._L10NSharpExtender.SetLocalizingId(this._openLabel, "WritingSystemSetupDialog.OpenWritingSystemsLabel"); // // WritingSystemSetupDialog //