Good day everyone. I want to present to the public (one more) a simple way to make application localization. The standard mechanism with resource assemblies does not suit me for the following reasons:
Getting the value of the localized string in the code, I really want to rely on the power of OOP and the compiler's hints. It’s very unpleasant to put together a project on Friday evening, and on Saturday morning, to receive a call from QA overtime that someone carelessly wrote GetResource (“asdf”) instead of GetResource (“assf”), and now something is falling or is displayed incorrectly, and the project on Monday is already being submitted to print ...
(In continuation of 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 hints.
')
Sometimes you need to localize not strings, but whole objects. For example, a noun (line + gender M / F / S / Mn) and an adjective (line M + line F + line C + line Mn). To shove a serialized string into resources, and then get and deserialize each time? Monsieur knows a lot about perversions ...
The resource file is a flat list of strings, but I would like the data to have a more complex hierarchical structure that you do not need to crawl with Ctrl + F.
Creating a new language should be as simple as possible. The application must be localized by a person who knows how to handle a computer and speaks the necessary languages. And he does not need neither Visual Studio, nor fussing with the creation of resource assemblies.
Another mandatory requirement is the ability to simply bind to the localization of UI elements. It is desirable - at the same time and WPF, and WinForms.
The decision lies on the surface and is able to compete with simplicity with an ax and a shovel. Watch your hands:
Create a class with a name, for example, Language, which will contain all localized resources.
We fill it with properties of the “string” type and properties-objects with string properties (“categories”), and properties-objects of the properties-objects, and ... Select the depth of the attachment to taste.
We make the Language class (and all enclosed in it) serializable using a method that will cause an almost ordinary user to have minimal rejection when trying to edit a file with a serialized language. I am most impressed with XML, so I choose, respectively, the attributes XmlType, XmlRoot, XmlElement, XmlAttribute. JSON fans can use JSON. If you have a convenient wrapper for working with ini-files, you can use it. All in your hands.
We pull the language onto the form using the BindingSource (WinForms) component, {x: Static} or <ObjectDataProvider> (WPF) and simple data binding.
Create a folder “Languages”, “Localizations” (or something like that) in the folder with our application and create one or several files in it that contain the languages ​​serialized by the selected method.
If it is necessary to localize more complex things (pictures, for example), the language will store the relative path to the resource file. The file itself in this case will be located in the subfolder of the “Languages ​​/ Localizations” folder.
When loading the application using the standard deserializer, the languages ​​are loaded. The current selected language is determined from the saved settings, selected in the drop-down list of the dialog at the start of the application (for example, if the application is launched for the first time and there is nothing in the config), or is automatically selected from those based on CultureInfo.CurrentCulture. The selected language can be saved 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 strings in it.
Use on health. Sample code is available for download here . It is written, obviously, in a hurry, and therefore bears the imprint of ill-conceived design: for example, languages ​​are loaded in the code of the main form, and not of the Main method. Well, for the way in which the language is tied to the form in the example Wpf, you can compress the fingers with pliers. But - it works at 100%. I will be glad to suggestions for improving this method.