Custom Neutral Culture does not show in Visual Studio Winform Language combobox

577 views Asked by At

We need to create an OEM version of our WinForms app, which would have some different resource strings (OEM branding) than the base (en-US) version. This app is already localized for the neutral Japanese culture (ja).

I am trying to use custom cultures to accomplish this, modeled on an article I found here. I have created two cultures: en-US-Acme and ja-Acme. The idea is that, for the OEM English and Japanese versions, we'd set the CurrentUICulture at startup time as appropriate. .Net would then pull the correct resource automatically: looking first in the OEM's resource file (en-US-Acme or ja-Acme), and if not found, falling back to the default resource file (en-US or ja).

I've written a small proof-of-concept app to try this out, and it works great for the specific culture (en-US-Acme). Once my culture is created, I can set the form's Language property to use it, and Visual Studio creates the appropriate resource file. At runtime, the resources are automatically selected (with fallback) as expected.

enter image description here

There is a problem for the neutral culture (ja-Acme) however: although the custom culture can be created, it does not show up as a choice in Visual Studio:

enter image description here

My code for creating the custom cultures, adapted from the article mentioned above, is shown below. I am not entirely sure I am creating custom neutral cultures correctly, although the code works.

So two questions:

  • Is this the right way to create a custom neutral culture?
  • Why doesn't my custom neutral culture show up in Visual Studio?

I am starting to think that custom neutral cultures are just not supported by Visual Studio, and that I'll have to use a custom specific culture (ja-JP-Acme) instead. I haven't tested this yet, but I think the fallback (to ja) would still work as I need.

var customCultures = CultureInfo.GetCultures( CultureTypes.UserCustomCulture );

if ( customCultures.Any( c => c.Name == "en-US-Acme" ) ) {
    CultureAndRegionInfoBuilder.Unregister( "en-US-Acme" );
}
var builder = CultureAndRegionInfoBuilderHelper.CreateChildCultureAndRegionInfoBuilder( new CultureInfo( "en-US" ), "Acme", "(Acme)" );
builder.Register();

if ( customCultures.Any( c => c.Name == "ja-Acme" ) ) {
    CultureAndRegionInfoBuilder.Unregister( "ja-Acme" );
}
builder = CultureAndRegionInfoBuilderHelper.CreateChildCultureAndRegionInfoBuilder( new CultureInfo( "ja" ), "Acme", "(Acme)" );
builder.Register();

//...

internal class CultureAndRegionInfoBuilderHelper {

    public static CultureAndRegionInfoBuilder CreateChildCultureAndRegionInfoBuilder( CultureInfo parentCultureInfo, string childNameSuffix, string childDescriptiveSuffix ) {
        var cultureName = parentCultureInfo.Name + "-" + childNameSuffix;
        RegionInfo parentRegionInfo;
        CultureAndRegionModifiers flags;

        // Set region info and flags based on whether the parent culture is neutral or not.
        if ( parentCultureInfo.IsNeutralCulture ) {
            parentRegionInfo = null;
            flags = CultureAndRegionModifiers.Neutral;
        }
        else {
            parentRegionInfo = new RegionInfo( parentCultureInfo.Name );
            flags = CultureAndRegionModifiers.None;
        }

        var builder = new CultureAndRegionInfoBuilder( cultureName, flags );

        // load the culture and region data from the parent
        builder.LoadDataFromCultureInfo( parentCultureInfo );
        if ( parentRegionInfo != null ) {
            builder.LoadDataFromRegionInfo( parentRegionInfo );
        }

        builder.Parent = parentCultureInfo;
        var descriptiveSuffix = " " + childDescriptiveSuffix;
        builder.CultureEnglishName += descriptiveSuffix;
        builder.CultureNativeName += descriptiveSuffix;
        if ( parentRegionInfo != null ) {
            builder.RegionEnglishName += descriptiveSuffix;
            builder.RegionNativeName += descriptiveSuffix;
        }

        return builder;
    }
}
1

There are 1 answers

0
Darryl On

It turns out that the custom neutral culture is indeed shown in Visual Studio, but it is in Japanese, not English, and so was not where I was looking for it. Instead, it was at the bottom of the list:

enter image description here

Visual Studio is showing the CultureInfo's DisplayName property, and the DisplayName of my custom neutral culture is in Japanese. Why?

I found my answer here. This is the key sentence:

Consequently, the DisplayName of a supplemental custom culture is the same as the native name.

The native name is still missing the "(Acme)" suffix, so I may still not be creating the custom neutral culture quite correctly, but this clears up part of the mystery.