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.
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:
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;
}
}
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:
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:
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.