Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GetResourceSet does not load fallback values

Tags:

c#

resources

I have two files: Resources.resx and Resources.de.resx.

enter image description here

The Resources.de.resx contains only one translated value. I am using the following method to load all resource keys/values:

        ResourceSet resourceSet = Resources.ResourceManager.GetResourceSet(Thread.CurrentThread.CurrentCulture, true, true);

When I load the resource set first time my Thread.CurrentThread.CurrentCulture.Name is empty string, Thread.CurrentThread.CurrentCulture.NativeName = "Invariant Language (Invariant Country)", Thread.CurrentThread.CurrentCulture.LCID = 127.

So, the resource set has 200 keys with values loaded from Resources.resx as expected. Then I switch the current culture using the following code which is triggered by clicking a button:

        Thread.CurrentThread.CurrentCulture = new CultureInfo("de");
        Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

When I load the resource set now, I have only one key in the set. It is the translated key from Resources.de.resx. But I still expect to have 200 keys with only one item translated to German (de) language.

The parent culture of current German(de) culture is the same invariant language culture like it was when I call the method to fetch resource set first time. Basically, it looks like the fallback is not working for some reasons. Could you tell me what am I doing wrong?

like image 364
Antipod Avatar asked Jul 16 '14 17:07

Antipod


3 Answers

You have to get all keys from the invariant culture and then you can lookup all translation. So the fallback works.

The looked-up resources can be stored in a dictionary.

var keys = Resources.ResourceManager
    .GetResourceSet(CultureInfo.InvariantCulture, true, true)
    .Cast<DictionaryEntry>()
    .Select(entry => entry.Key)
    .Cast<string>();

var enUsResources = keys.ToDictionary(
    key => key, 
    key => Resources.ResourceManager.GetString(key, CultureInfo.GetCultureInfo("de")));
like image 123
Heiner Avatar answered Sep 17 '22 15:09

Heiner


The way you are calling the Resources is actually preventing the fallback, as you are getting the localized(de) Resource Set first and then trying to access its specific values, in the Resources.de.resx file. That is what the method Resources.ResourceManager.GetResourceSet(Thread.CurrentThread.CurrentCulture, true, true) will do, return a Resource Set.

The fallback parameter of GetResourceSet will just be applied if the Resource Set does not exist at all. Once you create the Resources.de.resx file, that Resource Set will start to be returned.

In order to take advantage of the implicit fallback rules for the resources, you should use 'Resources.ResourceManager.GetString(token)' as it will go through the Resource Set hierarchy and fall back on the closest implementation of your token.

like image 32
Jorge Rodrigues dos Santos Avatar answered Sep 21 '22 15:09

Jorge Rodrigues dos Santos


Your German resource set still only has the keys you defined for it. I assume the ultimate problem your trying to solve is "Why does asking for the localized value of a particular key not fallback to the English entry if it isn't found in the localized resource set?" If so, you're probably doing something like this...

var resourceSet = resourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, true);
var localizedValue = resourceSet.GetString(key);

when in fact, you should simply be doing this...

var localizedValue = resourceManager.GetString(key, CultureInfo.CurrentCulture); 

In other words, have the resource manager perform the lookup, not the resource set.

like image 26
ctsears Avatar answered Sep 21 '22 15:09

ctsears