Skip to content

Commit 3eeffa1

Browse files
authored
Split L10NSharp to remove winforms dependency (#125)
* Remove Winforms dependency. * Move UI code into WindowsForms/UI * Split into two projects with only one dependent on winforms * Update SampleApp csproj * Cleanup & add ChooseFallbackLanguage in Winforms Split L10NSharp into two parts to separate out the portion that does not require use of Windows Forms from the portion that does. Additionally, remove System.Drawing dependency from the Windows Forms independent portion. Change L10NSharpWinforms to L10NSharp.Windows.Forms Change L10NSharpWinformsTests to L10NSharp.Windows.Forms.Tests Change L10NSharpTests folder to L10NSharp.Tests +semver:major
1 parent bd579ae commit 3eeffa1

133 files changed

Lines changed: 2540 additions & 4472 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,83 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1616

1717
## [Unreleased]
1818

19+
### Changed
20+
21+
- BREAKING CHANGE: Move code that depends on Windows.Forms or System.Drawing into an L10NSharp.Windows.Forms namespace. Rename L10NSharp.UI as L10NSharp.Windows.Forms.UIComponents. Move L10NExtender out of UI subfolder into L10NSharp.Windows.Forms. Move Winforms related tests to L10NSharp.Windows.Forms.Tests. Change the folder for L10NSharp tests to match its namespace L10NSharp.Tests.
22+
23+
Classes that contain some properties or methods that depend on Windows.Forms are split into Winforms-dependent and Winforms-independent classes. The Winforms-dependent classes subclass the Winforms-independent ones and can be found in the L10NSharp.Windows.Forms namespace. (e.g. LocalizationManagerWinforms in the L10NSharp.Windows.Forms namespace is a subclass of LocalizationManager in the L10NSharp namespace.)
24+
25+
To handle Windows forms related objects, call the Winforms versions of these classes and methods (e.g. LocalizationManagerWinforms.Create() instead of LocalizationManager.Create()). Each affected interface or class and its affected properties and methods are listed below.
26+
27+
- Split ILocalizationManagerInternal into ILocalizationManagerInternal and ILocalizationManagerInternalWinforms.
28+
29+
CHANGED: ILocalizationManagerInternalWinforms\<T> declares a new StringCache object of type ILocalizedStringCacheWinforms\<T>, while ILocalizationManagerInternal\<T> has a StringCache object of type ILocalizedStringCache\<T>.
30+
31+
MOVED: The properties ToolTipCtrls, LocalizableComponents, and ApplicationIcon; and the methods ApplyLocalization, ApplyLocalizationsToILocalizableComponent, ReapplyLocalizationsToAllComponents, and RegisterComponentForLocalizing are moved to ILocalizationManagerInternalWinforms.
32+
33+
- Split ILocalizedStringCache into ILocalizedStringCache and ILocalizedStringCacheWinforms.
34+
35+
MOVED: The property LeafNodeList, and the methods GetShortcutKeys and LoadGroupNodes are moved to ILocalizedStringCacheWinforms.
36+
37+
- Split LocalizationManager into LocalizationManager and LocalizationManagerWinforms.
38+
39+
CHANGED: Remove static designation from the LocalizationManager class in order for LocalizationManagerWinforms to subclass it and share its properties.
40+
41+
CHANGED: The Icon argument is removed from the Create methods in LocalizationManager. Create methods for LocalizationManagerWinforms are available with and without the Icon argument. (The two obsolete create methods in LocalizationManager, which included a TranslationMemory argument, are removed.)
42+
43+
CHANGED: SetUILanguage in LocalizationManager no longer reapplies localizations based on a reapplyLocalizationsToAllObjectsInAllManagers argument, since reapplying localizations is a Winforms method. SetUILanguage in LocalizationManagerWinforms retains this argument and reapplies localizations depending on its value.
44+
45+
MOVED: The methods ReapplyLocalizationsToAllObjectsInAllManagers, ReapplyLocalizationsToAllObjects, and GetLocalisedToolTipForControl are moved to LocalizationManagerWinforms.
46+
47+
- Split LocalizationManagerInternal into LocalizationManagerInternal and LocalizationManagerInternalWinforms.
48+
49+
CHANGED: Remove static designation from LocalizationManagerInternal class in order for LocalizationManagerInternalWinforms to subclass it and share its s_loadedManagers property.
50+
51+
CHANGED: Use different handling for ChooseFallbackLanguage in LocalizationManagerInternal that omits use of a Windows forms dialog for choosing the fallback. Retain original Winforms-dependent handling for ChooseFallbackLanguage in LocalizationManagerInternalWinforms.
52+
53+
CHANGED: Use different handling for GetString in LocalizationManagerInternal that omits handling of Winforms objects and methods. Retain original Winforms-dependent handling of GetString in LocalizationManagerInternalWinforms.
54+
55+
CHANGED: Remove Icon argument from the CreateXliff method in LocalizationManagerInternal. CreateXliff methods in LocalizationManagerInternalWinforms are available with and without the Icon argument.
56+
57+
CHANGED: In LocalizationManagerInternalWinforms, GetLocalizationManagerForComponent and GetLocalizationManagerForString, return type ILocalizationManagerInternalWinforms\<T> instead of ILocalizationManagerInternal\<T>.
58+
59+
MOVED: The methods ReapplyLocalizationsToAllObjectsInAllManagers, ReapplyLocalizationsToAllObjects, GetLocalizedToolTipForControl, and GetRealTopLevelControl are moved to LocalizationManagerInternalWinforms.
60+
61+
- Split LocalizingInfo into LocalizingInfo and LocalizingInfoWinforms.
62+
63+
CHANGED: Make private properties protected. LocalizingInfo returns null for Id while LocalizingInfoWinforms retains method to make an Id from a winforms component.
64+
65+
MOVED: The get methods for ShortcutKeys and Id properties are moved to LocalizingInfoWinforms, since they involve winforms components; LocalizingInfo will return null for ShortcutKeys and Id. The methods UpdateTextFromObject, CreateIdIfMissing, MakeId, MakeIdForCtrl, MakeIdForColumnHeader, MakeIdForDataGridViewColumn, GetIdPrefix, OwningFormName and GetCategory are moved to LocalizingInfoWinforms
66+
67+
- Split Utils into Utils and UtilsWinforms.
68+
69+
MOVED: The methods SendMessage, SendMessageWindows and SetWindowRedraw are moved to UtilsWinforms.
70+
71+
- Split XliffLocalizationManager into XliffLocalizationManager and XliffLocalizationManagerWinforms.
72+
73+
MOVED: The following are moved to XliffLocalizationManagerWinforms:
74+
75+
- The properties ApplicationIcon, ToolTipCtrls, LocalizableComponents and StringCache.
76+
- The methods RegisterComponentForLocalizing, GetShortcutKeyFromStringCache, ApplyLocalizationToIlocalizableComponent, ReapplyLocalizationsToAllComponents, RefreshToolTips, ApplyLocalization, ApplyLocalizationsToILocalizableComponent, ApplyLocalizationsToControl, ApplyLocalizedToolTipToControl, HandleToolTipRefChanged, HandleToolTipRefDestroyed, ApplyLocalizationsToToolStripItem, ApplyLocalizationToListViewColumnHeader, and ApplyLocalizationToDataGridViewColumn.
77+
78+
- Split XliffLocalizedStringCache into XliffLocalizedStringCacheWinforms and XliffLocalizedStringCache.
79+
80+
MOVED: The LeafNodeList property and the methods LoadGroupNodes and GetShortcutKeys are moved to XliffLocalizedStringCacheWinforms.
81+
82+
### Removed
83+
84+
- BREAKING CHANGE: Remove code related to doing one's own localization at runtime. Also remove obsolete create methods from LocalizationManager.
85+
86+
In particular:
87+
88+
- Remove the LocalizeItemDlg designer, cs, resx, and viewmodel.
89+
- Remove ShowLocalizationDialogBox from LocalizationManager and LocalizationManagerInternal.
90+
- Remove the following runtime-localization related methods from XliffLocalizationManager:
91+
PrepareComponentForRuntimeLocalization, HandleToolStripItemMouseDown, DoHandleMouseDown, HandeToolStripItemDisposed, HandleControlMouseDouwn, HandleControlDisposed, HandleTabPageDisposed, HandleDataGridViewDisposed, HandleListViewColumnHeaderClicked, HandleListViewDisposed, HandleListViewColumnDisposed, HandleDataGridViewCellMouseDown, HandleColumnDisposed, and ShowLocalizationDialogBox.
92+
- Remove obsolete Create methods from LocalizationManager. These are the two Create methods that included a TranslationMemory argument.
93+
94+
Also, remove RefreshToolTips from ILocalizationManager. All references were already to specific implementations of the method, and RefreshToolTips is not needed in the Winforms-free side of L10NSharp.
95+
1996
## [8.0.0] - 2025-03-12
2097

2198
### Changed

L10NSharp.sln

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ VisualStudioVersion = 17.0.32112.339
44
MinimumVisualStudioVersion = 10.0.40219.1
55
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "L10NSharp", "src\L10NSharp\L10NSharp.csproj", "{8EE0895A-7B9D-4B49-8F73-9F1270F1E583}"
66
EndProject
7-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "L10NSharpTests", "src\L10NSharpTests\L10NSharpTests.csproj", "{BCE5B569-057C-4D7E-832E-E44A2DA705AC}"
8-
EndProject
97
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApp", "src\SampleApp\SampleApp.csproj", "{58923B30-FD84-4BCC-85E0-607DCA7E7C95}"
108
EndProject
119
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExtractXliff", "src\ExtractXliff\ExtractXliff.csproj", "{E0666C78-B8DC-4232-952C-753940D54921}"
@@ -24,6 +22,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFolder", "SolutionF
2422
README.md = README.md
2523
EndProjectSection
2624
EndProject
25+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "L10NSharp.Windows.Forms", "src\L10NSharp.Windows.Forms\L10NSharp.Windows.Forms.csproj", "{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}"
26+
EndProject
27+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "L10NSharp.Windows.Forms.Tests", "src\L10NSharp.Windows.Forms.Tests\L10NSharp.Windows.Forms.Tests.csproj", "{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}"
28+
EndProject
29+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "L10NSharp.Tests", "src\L10NSharp.Tests\L10NSharp.Tests.csproj", "{B0218FB3-62E0-487B-B154-5788D8EF8345}"
30+
EndProject
2731
Global
2832
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2933
Debug|Any CPU = Debug|Any CPU
@@ -44,16 +48,6 @@ Global
4448
{8EE0895A-7B9D-4B49-8F73-9F1270F1E583}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
4549
{8EE0895A-7B9D-4B49-8F73-9F1270F1E583}.Release|Mixed Platforms.Build.0 = Release|Any CPU
4650
{8EE0895A-7B9D-4B49-8F73-9F1270F1E583}.Release|x86.ActiveCfg = Release|Any CPU
47-
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
48-
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
49-
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
50-
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
51-
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Debug|x86.ActiveCfg = Debug|Any CPU
52-
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
53-
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Release|Any CPU.Build.0 = Release|Any CPU
54-
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
55-
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
56-
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Release|x86.ActiveCfg = Release|Any CPU
5751
{58923B30-FD84-4BCC-85E0-607DCA7E7C95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5852
{58923B30-FD84-4BCC-85E0-607DCA7E7C95}.Debug|Any CPU.Build.0 = Debug|Any CPU
5953
{58923B30-FD84-4BCC-85E0-607DCA7E7C95}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -89,6 +83,42 @@ Global
8983
{E4BB984D-DFB8-42EF-860D-5A038FF85B1C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
9084
{E4BB984D-DFB8-42EF-860D-5A038FF85B1C}.Release|x86.ActiveCfg = Release|Any CPU
9185
{E4BB984D-DFB8-42EF-860D-5A038FF85B1C}.Release|x86.Build.0 = Release|Any CPU
86+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
87+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|Any CPU.Build.0 = Debug|Any CPU
88+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
89+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
90+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|x86.ActiveCfg = Debug|Any CPU
91+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|x86.Build.0 = Debug|Any CPU
92+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|Any CPU.ActiveCfg = Release|Any CPU
93+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|Any CPU.Build.0 = Release|Any CPU
94+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
95+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|Mixed Platforms.Build.0 = Release|Any CPU
96+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|x86.ActiveCfg = Release|Any CPU
97+
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|x86.Build.0 = Release|Any CPU
98+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
99+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
100+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
101+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
102+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|x86.ActiveCfg = Debug|Any CPU
103+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|x86.Build.0 = Debug|Any CPU
104+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
105+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|Any CPU.Build.0 = Release|Any CPU
106+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
107+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
108+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|x86.ActiveCfg = Release|Any CPU
109+
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|x86.Build.0 = Release|Any CPU
110+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
111+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|Any CPU.Build.0 = Debug|Any CPU
112+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
113+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
114+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|x86.ActiveCfg = Debug|Any CPU
115+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|x86.Build.0 = Debug|Any CPU
116+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|Any CPU.ActiveCfg = Release|Any CPU
117+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|Any CPU.Build.0 = Release|Any CPU
118+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
119+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|Mixed Platforms.Build.0 = Release|Any CPU
120+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|x86.ActiveCfg = Release|Any CPU
121+
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|x86.Build.0 = Release|Any CPU
92122
EndGlobalSection
93123
GlobalSection(SolutionProperties) = preSolution
94124
HideSolutionNode = FALSE

README.md

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
## Overview
22

3-
L10NSharp is a .NET localization library for Windows Forms applications. It collects strings which
4-
need localization when your application first runs and saves them in a translation memory file. It
5-
can also dynamically collect strings at runtime.
3+
L10NSharp is a .NET localization library. It collects strings which need localization when your
4+
application first runs and saves them in a translation memory file.
5+
6+
L10NSharp.Windows.Forms builds on L10NSharp and should be used for localization of Windows Forms applications.
67

78
L10NSharp works with XLIFF files as translation memory.
89

@@ -12,10 +13,24 @@ L10NSharp works with XLIFF files as translation memory.
1213

1314
[![NuGet version (L10NSharp)](https://img.shields.io/nuget/v/L10NSharp.svg?style=flat-square)](https://www.nuget.org/packages/L10NSharp/)
1415

15-
L10NSharp is provided as a [nuget package](https://www.nuget.org/packages/L10NSharp).
16+
L10NSharp and L10NSharp.Windows.Forms are provided as [nuget packages](https://www.nuget.org/packages/L10NSharp).
1617

17-
To use L10NSharp in your application, simply call the `Create` method on `LocalizationManager`,
18-
passing the location of the translation memory files and some other information:
18+
To use L10NSharp in your application, call the `Create` method on `LocalizationManager`,
19+
passing the location of the translation memory XLIFF files and some other information:
20+
21+
```csharp
22+
using (var lm = LocalizationManager.Create(lang, "SampleApp",
23+
"SampleApp", productVersion, directoryOfInstalledXliffFiles, "MyCompany/L10NSharpSample",
24+
"sample@example.com", "SampleApp")
25+
{
26+
// existing code to run the application
27+
}
28+
```
29+
30+
To use L10NSharp.Windows.Forms in your Windows forms application, you can call the `Create` method
31+
on `LocalizationManagerWinforms` instead, passing the location of the translation memory XLIFF
32+
files and the other information as above. Note that the `Create` for Windows forms applications can
33+
optionally include an additional icon argument:
1934

2035
```csharp
2136
using (var lm = LocalizationManager.Create(lang, "SampleApp",
@@ -39,8 +54,10 @@ or `es/Whatever.xlf`).
3954
### Selecting a Language
4055

4156
If an exact match for the requested language is not available, L10NSharp will try to find the best available language. For example, if the client
42-
requests `es` but only `Whatever.es-ES.xlf` is available, `Whatever.es-ES.xlf` will be loaded automatically, and vice versa. However, if the client
43-
requests `es` and both `Whatever.es-ES.xlf` and `Whatever.es-MX.xlf` are available, or if no `Whatever.es[-details].xlf` is available, a dialog will
57+
requests `es` but only `Whatever.es-ES.xlf` is available, `Whatever.es-ES.xlf` will be loaded automatically, and vice versa.
58+
59+
In L10NSharp.Windows.Forms, if the client
60+
requests `es` and both `Whatever.es-ES.xlf` and `Whatever.es-MX.xlf` are available, or if no `Whatever.es[-details].xlf` is available, a Windows forms dialog will
4461
inform the user that the selected language is not available and prompt the user to select from the available languages.
4562

4663
## Thread safety
@@ -51,14 +68,9 @@ attempted to make the various varieties of `GetString` thread-safe,.
5168

5269
## L10NSharpExtender
5370

54-
To localize a Windows Forms form or control, simply add the `L10NSharpExtender`. It will
71+
To localize a Windows Forms form or control, simply add the `L10NSharpExtender` from L10NSharp.Windows.Forms. It will
5572
automatically collect all the localizable strings on your form or control and its children.
5673

57-
## Localizing Within the Application
58-
59-
L10NSharp provides a dialog for translating terms while running the application. The dialog can be
60-
launched by Alt-Shift-clicking a Windows Forms element.
61-
6274
## Upgrading to a newer version
6375

6476
The [migration](https://github.com/sillsdev/l10nsharp/wiki/Migration) guide describes the
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)