ResourceManager and not supported platform - c#

I use ResourceManager for UI localization of my WinCE 5 software. I have some resource files with text strings on different languages
Resourse.resx
Resourse.de-DE.resx
Resourse.ru-RU.resx
When I want to display UI in English I call:
Resourse.Culture = new CultureInfo("en-US");
label1.Text = Resourse.LabelText;
in German:
Resourse.Culture = new CultureInfo("de-DE");
label1.Text = Resourse.LabelText;
in Russian:
Resourse.Culture = new CultureInfo("ru-RU");
label1.Text = Resourse.LabelText;
but here I get PlatformNotSupportedException.
I know that my WinCE does not contain Russian and I cannot modify OS to appened this, so my question is how I can say to ResourceManger to use Resourse.ru-RU.resx when I set Culture = new CultureInfo("ru-RU") ?

The answer Jonathan provided is the exact work around I had to do to get my device to show Simplified Chinese. I used "en-ZW" English(Zimbabwe). This worked on 3 different devices all running a different OS (CE5, CE6, and WEH/WM 6.5.3)
If the base Tahoma font doesn't contain everything you need, as in my case, you also need to put the font on the device and make some additional registry changes to enable font linking. It's not very complex, only a couple of registry entries.
This MSDN link provides the information for the Chinese fonts but it would be used the same way for any other font set.
http://msdn.microsoft.com/en-us/library/ms901082.aspx
The more generic MSDN articles on font linking can be found here:
http://msdn.microsoft.com/en-us/library/ms901098.aspx
Other than this the only other option I was able to determine was to roll your own translation resource class.

The following is a rather HACKED workaround, but it will solve the PlatformNotSupportedException issue. I would also recommend doing this only as a last resort. Please note that I have only tested this on WinCE 6.0.
If the culture you are attempting to implement is not supported by WinCE 6.0, simply re-label it as a different culture. For example, rather than marking the Russian culture as "ru-RU" (as above), you could re-name it as "eu-ES" (Basque). Provided that the font being used supports the Cyrillic character set, the values should display as you have written them.
Note: You MUST also rename your resource file to match the target culture you are substituting. If you are using "eu-ES" in place of "ru-RU", you must rename your "Resourse.ru-RU.resx" to "Resourse.eu-ES.resx".
What you lose: Any native support provided by the target culture (Russian in this case), (e.g. correctly formatted currencies, dates, etc), since these would now be being drawn from the work-around target culture (Basque in this case). Note that this should only be a problem in your application if you are formatting your strings via culture (i.e. stringFormat({some CultureInfo.GetCurrentCulture}, {additional formatting}, {some numerical value})).

Seems like you're stuck unfortunately. Your issue is unusual because typically a mobile app does not need to decide on which culture identifier to use. If it just relies on whatever culture the system has set up for it when launches, then users can switch the global culture setting which would affect your app and make it use your localizations if present.
If you are implementing a language selector inside your app, then I guess you need to filter down your list of choices so that you only offer cultures which the device supports (CultureInfo.GetCultures will give you a list of supported cultures, and you can find the subset for which you have localizations available).

Related

How to use custom cultures?

One of our clients requested that some terminology we're using should be changed according to their needs. That means changing a bunch of labels in forms and user messages. Our application is developed as multi-language application so everything is in resource files.
To solve this need I've decided to create a custom culture. I have created hr-HR-HP from standard hr-HR language. I did some tests and everything worked fine.
However, in our project, our third party components break down with the following exception
CultureNotFoundException: Culture is not supported.
Parameter name: culture
4096 (0x1000) is an invalid culture identifier.
Google says that this happens when CultureInfo is created via LCID and that is not supported for custom cultures. So, to avoid this i set Culture parameters as follows:
Thread.CurrentThread.CurrentCulture = new CultureInfo("hr-HR");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("hr-HR-HP");
Great, the error is gone and forms read their resources as expected. However, now ResourceManager is the problem. It's using hr satellite assembly instead of hr-HR-HP one. I use ResourceManager to read the user messages from satellite assemblies.
Any suggestions? Is it possible to specify which language I want for ResourceManager? Should I try some other approach?
Silly me, I was so close to the answer. Just a little more googling reveals that I can specify what culture I want in ResourceManager.GetString() method.

Is it possible to manually specify fallback cultures with .NET resx globalization?

I am working on a website where we need to deploy partially-tested translations (resx key-value pairs) to some users for review before rolling out those translations for all users.
One potential way to do this would be a to create a "beta" culture for a specific language and populate that culture's resx file with these untested translations. Then, we could switch our test users to this culture so that they can see the beta translations. Thus, I would like to establish a fallback chain like:
beta-chinese => chinese => default (english)
Is this possible within the .NET/ASP.NET resx architecture? If so, how do I set this up?
If you have the following resources it should work:
Resources.resx
Resources.zh.resx
Resources.zh-BT.resx
See here too:
http://www.hanselman.com/blog/GlobalizationInternationalizationAndLocalizationInASPNETMVC3JavaScriptAndJQueryPart1.aspx
If you named your Chinese resources zh-CN then I think it will not work.
For zh-BT you have to create a custom culture:
Create custom culture in ASP.NET

Identify unlocalized text

In ASP.NET, an application can be localized using resource files. Resource files hold different translations. For example, one might have an English resource file and a Spanish resource file. When resource files are used, an attribute can be applied to controls on a web page to automatically populate that control with values from a resource file. Alternatively, the values can be programmatically loaded from a resource file and assigned to a control's property.
ASP.NET uses a fallback mechanism for loading translations. It tries to find the resource file that is most similar to the current user's culture. If the current user's culture is Spanish, ASP.NET tries to load the appropriate resource from the Spanish resource file. If the Spanish resource is not available, it falls back to a default resource file. Because of this behavior, text for a Spanish user may be shown in the default language for two reasons:
No Spanish translation is available. (The translators haven't provided a translation for this item yet.)
The text is not localized. (This may be the result of plain text appearing in the page or the message being hard-coded somewhere.)
If text appears in the default language, I want to know whether it was because of reason 1 or because of reason 2.
For every missing translation, I could insert some kind of placeholder text in a resource file. However, this means that I am throwing away the fallback mechanism. Even worse, if placeholder text accidentally makes it through to production, it looks much worse than showing the default text.
Does anyone have any suggestions (or solutions) for determining which of these two conditions is the reason for default text appearing during manual testing?
If I understood you correctly you want to verify that every localizable text is indeed in fact localizable and not burned in the code. To do this you should not be using a real culture (Spanish), instead you should create resources for a fake unsupported culture and provide an automatic translation for every localizable resource entry available in the default resources.
For example, if you have a default resource containing:
Entry1: This is a test!
you should create a resource in your fake culture containing:
Entry1: Th1s 1s # t€st!
You could even (and should) perform the creation of the fake resources automatically using a simple character mapping. This way, when you set the application to use your custom fake culture you know that every entry has a translation so you can find harcoded text. This strategy is used by Windows and is known as pseudo-locales. The use of pseudo translated strings makes it possible do development using the fake culture because the text is still readable and this improves your probability of finding hardcoded text.
Windows supports pseudo-locales since Windows Vista and Windows 2008 R2, so if your build and testing environment uses these operating systems you can associate your fake culture to one of these pseudo locales (for example qps-ploc). If you have unsupported operating systems just associate your fake resources to a real culture that you probably will never be supporting or just create your own culture.
Also note that even in a supported operating system, Visual Studio will not create satellite assemblies for these pseudo-locales unless you enable them on the registry.

Localization using resource file

I use a *.resx file for the localization purpose. The Name - it's a phrase or word in English. The Value - the translation to another language of that phrase. I choose this approach to have a one localization file for the whole application. And anyone who have this file can make translation by themselves.
But in the Visual Studio 2010 resx editor, each record with name which have spaces in it, have a warning: "The resource name is not a valid identifier."
Though it compiles and works, but please tell me if I am doing something wrong here.
First of all, the idea of the resx files is to have a separate resource file for each culture. You can provide the new translation by creating a new file with different values for the same keys.
For example, you can create Forms.en-GB.resx, Forms.pl-PL.resx, Forms.de-DE.resx and the appropriate file will be picked up based on the current UI culture without you having to do anything (except ensuring relevant culture is set).
Visual Studio will generate a resource class that contains all your key/value pairs from resource file as properties - that makes it easier to use in code. The warning you get means that the keys you've provided in resource file are not a valid identifiers (they contain spaces). You might want to use _ instead of space in the keys.
If you don't want to use the generated class you can ignore this warning - your resx files are fine and can be used directly. You can remove ResXFileCodeGenerator from 'Custom Tool' property of your resx file (properties windows) or set 'Access Modifier' to 'No code generation' in resx file editor if you do not need to generate a class, but you will still get the warning.
The strength of localization with resx files is that the culture on your computer decides what language your application should be in. If you keep to one resx file, according to me, you ignore it's power. Instead, try making a resx file for each language you want to integrate. for example: the default language is english, then you have a default page localization.resx where you only keep english sentences. Say you need a French translation, make another resx file called localization.fr-FR.resx. So users who have the fr-FR culture enabled on there computer will have that language on the program without any code specific work. If someone with a culture not integrated in your application starts the program, it will look for it, and if it doesn't find it, it chooses the default, ie english, one.
So to my opinion, don't use 1 resx file for different languages, but use the powers given in the framework.
I suppose it works, but it's not really the strategy you are supposed to follow.
Take a look here; the basic idea is that you take advantage of the controls in .NET to automatically get the correct localisation themselves, so you kind of don't need to worry about doing the translating.
Though, I don't use this all the time, and I do somewhat do as you do, but I tend to use an identifier, so I may have:
UserWelcome Hey, {name}, thanks for dropping by ...
And then I'll translate that. It's helpful because it allows generality in the languages (say, for example, some languages should be greeted formally, and others not, you don't want to be contrained by a direct translation of, "You", say).
Hope this is clear.
If what you've got works, then I suppose that's something, but it's not the "general" way of doing it.

C# Satellite Assemblies? Do I need to link default culture resource

We would like to employ satellite assemblies to contain various locale dependent resource files.
Question is ... do we need to link the default culture?
We have a separate project which will contain all of our different culture resource files. As is shown below, we have the project with two resource files inside of it.
ProjRES
Resource.resx
Resource.it-IT.resx
I am assuming that the "Resource.resx" will act as the default culture and if the Italian culture is selected, the application will adopt the it-IT resource file.
What do we need to do in order to get the rest of the application and projects to access the resource files. How do we set the namespaces for the resource files in order to be able to reference them.
Any help is greatly appreciated.
Basically,
if the current culture that the OS is using matches a certain culture that you've shipped, it will be used, if the current culture matches none of the cultures you've shipped, it will use the neutral culture.
In the most simplistic cases, you'll just need to include any of the localized dlls with the deployment and all will be fine..
When you're using resource managers, I think you can also pass in which culture you want to use explicitly, and the runtime will search for resources that match - this is better when a user of an ASP.Net site might have a certain culture preference that is different from that of the machine that the site is running on.
http://msdn.microsoft.com/en-us/magazine/cc163609.aspx seems to be a good starting point.

Categories