![](http://habrastorage.org/getpro/habr/avatars/7f1/d77/52a/7f1d7752a4d7ae4428bbdd28dc5bd966.png)
Another way to localize applications
Good day to all. I want to introduce to the public (another) an easy way to make application localization. The standard mechanism with resource assemblies does not suit me for the following reasons:
Another mandatory requirement is the ability to easily bind to the localization of UI elements. Desirable - both WPF and WinForms.
The solution lies on the surface and in simplicity is able to compete with an ax and a shovel. Watch your hands:
Anyone who wants to make a new locale will just need to copy the file with a convenient language in the “Languages / Localizations” folder and translate the lines in it.
Use on health. An example code is available for download here . It was obviously written in a hurry, and therefore bears the stamp of an ill-conceived design: for example, languages are loaded in the code of the main form, and not the Main method. Well, for the way that the language is attached to the form in the Wpf example, you can squeeze your fingers with pliers. But - it works 100%. I will be glad to suggestions for improving this method.
- Getting the value of a localized string in the code, I really want to rely on the full power of OOP and the compiler hints. It’s very unpleasant to put together a project in the evening on Friday, and on Saturday morning to receive a call from the overhaul QT overtime that someone inattentively wrote GetResource (“asdf”) instead of GetResource (“assf”), and now something falls or displayed incorrectly, and the project on Monday is already in print ...
- (Continuing the previous paragraph ...) Writing string foo = language.Ui.PromtDialog.AdditionalQuestion is simply nicer than string foo = Resources.GetResource ("Ui_PromtDialog_AdditionalQuestion"). Yes, including due to compiler prompts.
- Sometimes you need to localize not strings, but whole objects. For example, a noun (line + gender M / W / C / Mn) and an adjective (line M + line W + line C + line Mn). Shove a serialized string into resources, and then get and deserialize each time? Monsieur knows a lot about perversions ...
- A resource file is a flat list of lines, but I would like the data to have a more complex hierarchical structure, which does not need to be crawled with Ctrl + F.
- Creating a new language should be as simple as possible. Localize the application should be capable of people who can handle a computer and speak the necessary languages. And for this, he does not need either Visual Studio or fuss with the creation of resource assemblies.
Another mandatory requirement is the ability to easily bind to the localization of UI elements. Desirable - both WPF and WinForms.
The solution lies on the surface and in simplicity is able to compete with an ax and a shovel. Watch your hands:
- We create a class with the name, for example, Language, which will contain all the localized resources.
- We fill it with properties of the "string" type and properties-objects with string properties ("categories"), and properties-objects of properties-objects, and ... Choose the depth of attachment to taste.
- We make the Language class (and all nested in it) serializable using a method that will cause an almost ordinary user to get minimal rejection when trying to edit a file with a serialized language. Most of all I am impressed with XML, so I choose the attributes XmlType, XmlRoot, XmlElement, XmlAttribute, respectively. JSON fans can use JSON. If at hand there is a convenient wrapper for working with ini-files - you can use it. All in your hands.
- Pull the language onto the form using the BindingSource component (WinForms), {x: Static} or
(WPF) and simple data binding. - Create a folder “Languages”, “Localizations” in a folder with our application (or something like that) and create one or several files in it, in which languages will be serialized in the selected way.
- If it is necessary to localize more complex things (pictures, for example), the language will store the relative path to the resource file. In this case, the file itself will be located in a subfolder of the Languages / Localizations folder.
- When loading the application using the standard deserializer, languages are loaded. The current selected language is determined from the saved settings, selected in the drop-down list of the dialog at the application start (for example, if the application is launched for the first time and there is nothing in the config), or automatically selected from the ones available based on CultureInfo.CurrentCulture. The selected language can be stored in any object, access to which (no matter how - even through singleton, even through dependency injection, ... - enter the preferred option) can be obtained from those places where localized resources are required.
Anyone who wants to make a new locale will just need to copy the file with a convenient language in the “Languages / Localizations” folder and translate the lines in it.
Use on health. An example code is available for download here . It was obviously written in a hurry, and therefore bears the stamp of an ill-conceived design: for example, languages are loaded in the code of the main form, and not the Main method. Well, for the way that the language is attached to the form in the Wpf example, you can squeeze your fingers with pliers. But - it works 100%. I will be glad to suggestions for improving this method.