Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2cb2b4b
Remove Winforms dependency.
aror92 Jun 29, 2025
675a025
Move UI code into WindowsForms/UI
aror92 Jul 15, 2025
d0d1282
Split into two projects with only one dependent on winforms
aror92 Jul 17, 2025
ba40d24
Fix some winforms references
aror92 Jul 21, 2025
c1d263c
Fix static classes so managers can be inherited in winforms code
aror92 Jul 22, 2025
96d547b
Cleanup commented code
aror92 Jul 22, 2025
4aa2bd0
Update SampleApp csproj
aror92 Jul 22, 2025
5cb261d
Cleanup & add ChooseFallbackLanguage in Winforms
aror92 Jul 31, 2025
9e1252f
Update namespaces
aror92 Jul 31, 2025
c6fa510
Move winforms properties & fix SampleApp
aror92 Jul 31, 2025
aae03c7
Fix UI namespace
aror92 Aug 4, 2025
eb0d762
Fix SampleApp build errors
aror92 Aug 4, 2025
fec10e9
Fix ILocalizableComponentTests
aror92 Aug 4, 2025
da0768c
Move send message to winforms side
aror92 Aug 4, 2025
e081195
Move xliff localization winforms test
aror92 Aug 4, 2025
53a0423
Remove unused resources & alt-shift-click handling
aror92 Aug 5, 2025
134510c
Add create method w/o icon to LocalizationManagerWinforms
aror92 Aug 6, 2025
d1c92fd
Add CHANGELOG and remove deprecated create methods
aror92 Aug 13, 2025
836fb96
Cleanup
aror92 Aug 13, 2025
0a13495
Update README
aror92 Aug 13, 2025
1e6a6c1
Update CHANGELOG & CreateXliff method
aror92 Aug 14, 2025
9a7bb09
Cleanup static function naming
aror92 Aug 14, 2025
0c2fa6d
Fix static function call in XliffLocalizationManagerWinforms
aror92 Aug 14, 2025
8071200
Fix null-op apply localization method references.
aror92 Sep 5, 2025
a96ea73
Fix typo in Changelog
aror92 Sep 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,83 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed

- 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.

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.)

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.

- Split ILocalizationManagerInternal into ILocalizationManagerInternal and ILocalizationManagerInternalWinforms.

CHANGED: ILocalizationManagerInternalWinforms\<T> declares a new StringCache object of type ILocalizedStringCacheWinforms\<T>, while ILocalizationManagerInternal\<T> has a StringCache object of type ILocalizedStringCache\<T>.

MOVED: The properties ToolTipCtrls, LocalizableComponents, and ApplicationIcon; and the methods ApplyLocalization, ApplyLocalizationsToILocalizableComponent, ReapplyLocalizationsToAllComponents, and RegisterComponentForLocalizing are moved to ILocalizationManagerInternalWinforms.

- Split ILocalizedStringCache into ILocalizedStringCache and ILocalizedStringCacheWinforms.

MOVED: The property LeafNodeList, and the methods GetShortcutKeys and LoadGroupNodes are moved to ILocalizedStringCacheWinforms.

- Split LocalizationManager into LocalizationManager and LocalizationManagerWinforms.

CHANGED: Remove static designation from the LocalizationManager class in order for LocalizationManagerWinforms to subclass it and share its properties.

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.)

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.

MOVED: The methods ReapplyLocalizationsToAllObjectsInAllManagers, ReapplyLocalizationsToAllObjects, and GetLocalisedToolTipForControl are moved to LocalizationManagerWinforms.

- Split LocalizationManagerInternal into LocalizationManagerInternal and LocalizationManagerInternalWinforms.

CHANGED: Remove static designation from LocalizationManagerInternal class in order for LocalizationManagerInternalWinforms to subclass it and share its s_loadedManagers property.

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.

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.

CHANGED: Remove Icon argument from the CreateXliff method in LocalizationManagerInternal. CreateXliff methods in LocalizationManagerInternalWinforms are available with and without the Icon argument.

CHANGED: In LocalizationManagerInternalWinforms, GetLocalizationManagerForComponent and GetLocalizationManagerForString, return type ILocalizationManagerInternalWinforms\<T> instead of ILocalizationManagerInternal\<T>.

MOVED: The methods ReapplyLocalizationsToAllObjectsInAllManagers, ReapplyLocalizationsToAllObjects, GetLocalizedToolTipForControl, and GetRealTopLevelControl are moved to LocalizationManagerInternalWinforms.

- Split LocalizingInfo into LocalizingInfo and LocalizingInfoWinforms.

CHANGED: Make private properties protected. LocalizingInfo returns null for Id while LocalizingInfoWinforms retains method to make an Id from a winforms component.

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

- Split Utils into Utils and UtilsWinforms.

MOVED: The methods SendMessage, SendMessageWindows and SetWindowRedraw are moved to UtilsWinforms.

- Split XliffLocalizationManager into XliffLocalizationManager and XliffLocalizationManagerWinforms.

MOVED: The following are moved to XliffLocalizationManagerWinforms:

- The properties ApplicationIcon, ToolTipCtrls, LocalizableComponents and StringCache.
- The methods RegisterComponentForLocalizing, GetShortcutKeyFromStringCache, ApplyLocalizationToIlocalizableComponent, ReapplyLocalizationsToAllComponents, RefreshToolTips, ApplyLocalization, ApplyLocalizationsToILocalizableComponent, ApplyLocalizationsToControl, ApplyLocalizedToolTipToControl, HandleToolTipRefChanged, HandleToolTipRefDestroyed, ApplyLocalizationsToToolStripItem, ApplyLocalizationToListViewColumnHeader, and ApplyLocalizationToDataGridViewColumn.

- Split XliffLocalizedStringCache into XliffLocalizedStringCacheWinforms and XliffLocalizedStringCache.

MOVED: The LeafNodeList property and the methods LoadGroupNodes and GetShortcutKeys are moved to XliffLocalizedStringCacheWinforms.

### Removed

- BREAKING CHANGE: Remove code related to doing one's own localization at runtime. Also remove obsolete create methods from LocalizationManager.

In particular:

- Remove the LocalizeItemDlg designer, cs, resx, and viewmodel.
- Remove ShowLocalizationDialogBox from LocalizationManager and LocalizationManagerInternal.
- Remove the following runtime-localization related methods from XliffLocalizationManager:
PrepareComponentForRuntimeLocalization, HandleToolStripItemMouseDown, DoHandleMouseDown, HandeToolStripItemDisposed, HandleControlMouseDouwn, HandleControlDisposed, HandleTabPageDisposed, HandleDataGridViewDisposed, HandleListViewColumnHeaderClicked, HandleListViewDisposed, HandleListViewColumnDisposed, HandleDataGridViewCellMouseDown, HandleColumnDisposed, and ShowLocalizationDialogBox.
- Remove obsolete Create methods from LocalizationManager. These are the two Create methods that included a TranslationMemory argument.

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.

## [8.0.0] - 2025-03-12

### Changed
Expand Down
54 changes: 42 additions & 12 deletions L10NSharp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ VisualStudioVersion = 17.0.32112.339
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "L10NSharp", "src\L10NSharp\L10NSharp.csproj", "{8EE0895A-7B9D-4B49-8F73-9F1270F1E583}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "L10NSharpTests", "src\L10NSharpTests\L10NSharpTests.csproj", "{BCE5B569-057C-4D7E-832E-E44A2DA705AC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApp", "src\SampleApp\SampleApp.csproj", "{58923B30-FD84-4BCC-85E0-607DCA7E7C95}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExtractXliff", "src\ExtractXliff\ExtractXliff.csproj", "{E0666C78-B8DC-4232-952C-753940D54921}"
Expand All @@ -24,6 +22,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFolder", "SolutionF
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "L10NSharp.Windows.Forms", "src\L10NSharp.Windows.Forms\L10NSharp.Windows.Forms.csproj", "{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}"
EndProject
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}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "L10NSharp.Tests", "src\L10NSharp.Tests\L10NSharp.Tests.csproj", "{B0218FB3-62E0-487B-B154-5788D8EF8345}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -44,16 +48,6 @@ Global
{8EE0895A-7B9D-4B49-8F73-9F1270F1E583}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{8EE0895A-7B9D-4B49-8F73-9F1270F1E583}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{8EE0895A-7B9D-4B49-8F73-9F1270F1E583}.Release|x86.ActiveCfg = Release|Any CPU
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Debug|x86.ActiveCfg = Debug|Any CPU
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Release|Any CPU.Build.0 = Release|Any CPU
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{BCE5B569-057C-4D7E-832E-E44A2DA705AC}.Release|x86.ActiveCfg = Release|Any CPU
{58923B30-FD84-4BCC-85E0-607DCA7E7C95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58923B30-FD84-4BCC-85E0-607DCA7E7C95}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58923B30-FD84-4BCC-85E0-607DCA7E7C95}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -89,6 +83,42 @@ Global
{E4BB984D-DFB8-42EF-860D-5A038FF85B1C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{E4BB984D-DFB8-42EF-860D-5A038FF85B1C}.Release|x86.ActiveCfg = Release|Any CPU
{E4BB984D-DFB8-42EF-860D-5A038FF85B1C}.Release|x86.Build.0 = Release|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|x86.ActiveCfg = Debug|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Debug|x86.Build.0 = Debug|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|Any CPU.Build.0 = Release|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|x86.ActiveCfg = Release|Any CPU
{B118A158-F6A9-4346-ADC7-A9FEBCE5BE68}.Release|x86.Build.0 = Release|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|x86.ActiveCfg = Debug|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Debug|x86.Build.0 = Debug|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|Any CPU.Build.0 = Release|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|x86.ActiveCfg = Release|Any CPU
{DCF3741C-9496-4495-BF57-0DBA1DBBB7F5}.Release|x86.Build.0 = Release|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|x86.ActiveCfg = Debug|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Debug|x86.Build.0 = Debug|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|Any CPU.Build.0 = Release|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|x86.ActiveCfg = Release|Any CPU
{B0218FB3-62E0-487B-B154-5788D8EF8345}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
40 changes: 26 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
## Overview

L10NSharp is a .NET localization library for Windows Forms applications. It collects strings which
need localization when your application first runs and saves them in a translation memory file. It
can also dynamically collect strings at runtime.
L10NSharp is a .NET localization library. It collects strings which need localization when your
application first runs and saves them in a translation memory file.

L10NSharp.Windows.Forms builds on L10NSharp and should be used for localization of Windows Forms applications.

L10NSharp works with XLIFF files as translation memory.

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

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

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

To use L10NSharp in your application, simply call the `Create` method on `LocalizationManager`,
passing the location of the translation memory files and some other information:
To use L10NSharp in your application, call the `Create` method on `LocalizationManager`,
passing the location of the translation memory XLIFF files and some other information:

```csharp
using (var lm = LocalizationManager.Create(lang, "SampleApp",
"SampleApp", productVersion, directoryOfInstalledXliffFiles, "MyCompany/L10NSharpSample",
"sample@example.com", "SampleApp")
{
// existing code to run the application
}
```

To use L10NSharp.Windows.Forms in your Windows forms application, you can call the `Create` method
on `LocalizationManagerWinforms` instead, passing the location of the translation memory XLIFF
files and the other information as above. Note that the `Create` for Windows forms applications can
optionally include an additional icon argument:

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

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
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
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
requests `es` but only `Whatever.es-ES.xlf` is available, `Whatever.es-ES.xlf` will be loaded automatically, and vice versa.

In L10NSharp.Windows.Forms, if the client
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
inform the user that the selected language is not available and prompt the user to select from the available languages.

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

## L10NSharpExtender

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

## Localizing Within the Application

L10NSharp provides a dialog for translating terms while running the application. The dialog can be
launched by Alt-Shift-clicking a Windows Forms element.

## Upgrading to a newer version

The [migration](https://github.com/sillsdev/l10nsharp/wiki/Migration) guide describes the
Expand Down
Loading
Loading