Windows forms localization using *.resx and Common.resx - c#

Lets say there are bunch of forms: A.cs, B.cs, C.cs...
Each form is localized - A.resx, A.NL-nl.resx, etc.
These forms contain some specific labels and some common in all forms used labels. So specific strings go to A.resx (A.NL-nl.resx) and common ones - to lets say Common.resx (Common.NL-nl.resx)
Is there any way to force when form is initialized to use resource strings from A.resx and from Common.resx where all common strings go? Of course I could in some OnLoad method set captions for my form layout items, but then built in localization functionality would be lost.
The reason I would like such functionality, because there are lot of commonly used strings in different forms and it would much easier to manage/translate these *.resx files.
I've done some reading about localization in C#, but probably I am missing something.

From my experience I can say:
You will be better of to create one locatization resx file for all the forms.
Assign all localizable strings manually (I did that in constructor).
Store each string for each form in different localizable property, like Form1_OkButtonText, Form2_OkButtonText.
The last one really does matter, when you translate your app to different languages, because translation may really depend on context. And on one form default button may be named OK and on the other it should be named Accept. While in English both buttons may be named Ok, in some other languages, this will sound awkward, and different names will be required. This is be problematic, if you use same resource strings for all buttons.
And to mitigate the problems of translating several same strings many times, you should use some software for translator, that keep dictionary of string, and supply you with already translated ones.

Resources have a fully qualified name. Which means they have one source. If you want to use texts from Common.resx in your form, you must write code for that. Easy code but code nonetheless.

Related

How to exports strings from a WPF application code for internationalization?

I'm trying to modify an existing C# application for internationalization. The process for WPF has some documentation here and seems reasonably transparent as I can continue to develop normally and run msbuild from time to time and check if everything holds. However, while going through the sample project, I realized that it won't cover strings defined in code. In my case, most of them are used for logging and could more or less be easily exported with regexes. This seems a bit hazardous as well as I'm not certain the center will hold if I try to extract C# source with regex. I guess that I could wrap every string in a translation function that will perform the lookup in resources.
I'm not sure how to proceed from there. I'll have a bunch of strings that I could dump in a resx file and another set of strings extracted from the baml files internationalized in another way. Since I'm expecting each method to bring their own complications, I'd rather deal with only half of those complications if possible.
Is there any way to have either method work for both cases? I'd honestly prefer the second one since it makes more sense to me but I guess I could roll with generating a gazillion of Uids and only using 5% - 10% of them.
I develop multi-language check-in kiosks for one of the worlds busiest international airports (either #1 or #3, depending on how you define it), and in my experience the best solution for this in WPF apps is custom markup extensions. First, you can use regular language as your key, which means all of your XAML can be written in whatever language is most convenient for your developers. Secondly, you can add custom namespaces to the XAML namespaces, which helps keep your XAML tidy. Third, it's very easy to write utilities to extract your XAML extensions and collate them into Excel spreadsheets (say) for your translators, then incorporate the translations themselves back into your application. Finally, the translation tables themselves can be easily switched at runtime, allowing you to change your language on-the-fly.
Put all this together and all your XAML looks like this:
<TextBlock Text="{Translate 'Text to be translated appears here'}" />
And of course it's easy to control which text goes through your translation engine and which text doesn't, by simply controlling exactly where you use your Translate markup extension.

WPF Resources Localization from webservice

I'm struggling with this issue. I have a webservice that retrieves all the possible labels (with keys) for my application. This labels may vary from culture to culture (en, fr, de, pt, etc).
My doubt is how can I create/fill a resource file for that culture and fill with those labels/keys?
Those labels are managed by a backend server, and I have a GET to a REST webservice to get those strings.
Thanks
I don't think that there are any best practices for this. You need to write a mini-framework that could do one of the things listed bellow:
[If using MVVM] You could put the labels on your view model and bind to them in XAML. Involves writing lots of properties even when using snippets. Also, lots of properties are a pain when binding.
[If using MVVM] A better design similar to 1 where you store the labels in a separate class which is a property in your view model. Let your imagination go wild, use singleton, caching, etc. This is the most dangerous approach.
You could create one (or more classes) like any view model (at least with INotifyPropertyChanged), store it as a XAML resource and bind to it, populate it when you want. More XAML when binding labels but does what you're asking for and it's easily readable for others.
In all the options listed above you can change locale at runtime with translation being effective immediately (assuming you implemented INotifyPropertyChanged and bound label to take account of this), which you don't get with .resx and changing thread culture.
I would try all 3 as sample projects and see which would make a time-efficient way of manipulating label resources (adding, removing, changing, renaming them, and of course maintaining their contents).
Personally, I would go with 3. I listed the others just to be a little exhaustive.

Loading .resx file by custom string that doesn't map to a culture

I'm making a website for use by multiple clients and I need to offer the flexibility to change labels on various places. For example, if one client wants to call the login "Email" and another wants to call it "Employee ID." Though I've never used them, I thought that resx resource files used for localization would be a good idea, but I'm having problems setting it because what I'm doing isn't a real localization that maps to any culture.
My testing has these resource files:
Global.resx
Hello "Hello!"
Global.Casual.resx
Hello "Sup!"
Global.Formal.resx
Hello "Greetings!"
Then in my cshtml view, I can say #Resources.Global.Hello and that works as expected. My question is, how can I set it to display Casual by default? If I rename Casual and Formal to es and ru, I can do something like this:
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("es");
And that works just fine. But if I try that with "Casual" I get that it "is an invalid culture identifier." I can explicitly show it by saying #Resources.Global_Casual.Hello in the view, but that's obviously not what I'm after.
Am I going the complete wrong direction here, trying to use something for a purpose contrary to its design? I just want to load resource files by arbitrary string values. Do I need to roll my own database-driven approach?
This looks very similar to this SO question, which never got an answer: How to specify a custom culture?
Personally I feel that this kind of customisation belongs in the database - not least because you can then allow the clients to customise it themselves if required. If you are concerned about performance then you can cache the terms into a dictionary and even create a class that will expose the strings either from the dictionary (if the client has customised them) or from a resource file if not. This allows you to present reasonable defaults which can be changed on demand. Alternatively you could present a number of alternatives in the database, and a flag to allow selection per term of the word to be displayed in the UI.
I had a similar problem of allowing customisation within an application in the SO question Localization vs Customization which you may find useful.

Using only 1 resource file instead of 1 resource file per form/other strings

We are localizing our forms and strings in a project and are having a problem; Visual Studio creates a resource file for each form when setting Localizable to true.
It's nothing more than a minor nuisance having to send all of the resource files to translators, but is it possible to get VS to use a global resources file instead?
Thanks!
Like Yoda would say, possible it is.
You will have to dynamically translate the dialogs when they are loaded. I did this on several projects and I would say it's much better than having localized resource files.
As others already said, it is possible to use global resource file manually. I believe that it is actually more problematic and less maintainable but still possible.
Now onto why MS decided on one resource file per form. Well, from Internationalization point of view, this solution is better. On one hand it gives translators one important thing: the context. On the other hand, it is typical for project to grow. It is really unlikely that you will make changes to all forms at once. And you know what? Depending on your deal with translation vendor, you can usually spend less on Localization if just few percent of strings would change. That is just because they can use Translation Memory (TM) software.
With one global resource file, there is usually no context and no way to reasonably use TM. The result is, translations are less accurate and take longer (one needs to actually read large blocks of text to make sure everything is correctly translated).
By the way, you do not need to send out individual resource files. Instead you can use some kind of translation kit generator (or translation manager software) to create something useful for translators (for example translation memory friendly file). Sadly, I cannot give you the names of such tools (although I know that there are few of them) since my employer is using custom system for that and I didn't have a chance to work with other tools.
WinFrom doesn't support generating a global resources for Forms automatically in VS.
You must assign the strings by yourself. For example:
Add a Resources.resx with Resources.designer.cs to your project;
Define your strings in Resources.resx.
In your form.cs code, assign the strings in constructor like:
Label1.Text = Resources.Label1Text;

Are resx files a suitable way to customise for different customers?

I'm looking at customising the various pieces of text in an application for different customers. It seems like .resx resources would be a sensible way to do this. However, all the literature for resx I come across seems to be about localising for language differences (as in English, French, Spanish, etc.), so just want to check it is the best thing simply for customer differences in text as well.
And, hypothetically, could it also deal with different languages for different customers, e.g.:
CustomerA.resx
CustomerA.en-US.resx
CustomerA.de-DE.resx
CustomerB.resx
CustomerB.en-US.resx
CustomerB.de-DE.resx
... etc
Is resx the way to go for customer differences?
You can use them for storing different strings per customer - it will work. I imagine you don't have many customer to cater for and they do not require the strings to be modified very often. Otherwise the management of multiple files may become a real pain.
Storing per-customer strings in the database (with caching) may be a better option, especially if you want the customers to modify their strings.
I wouldn't customize like this per customers, how do you specify then if you have to loadCustomerA or CustomerB resources? Resx are ok for languages localizations but if you want to have different texts for different customers, I would probably read the strings from a database table which would contain initially the default values then you customize values in the customer specific database.
Yes, it is possible to do what you need with resx files. You can use custom cultures to achieve that. Please take a look at How to load different RESX files based on some parameter.

Categories