Adding (all) locales to your Windows Embedded Compact 7 OS
This article explains how you can add all of the locales to your OS. You can find a brief description on the National/Regional Language Support (NLS) Catalog Items and Sysgen Variables page.
Although everything in this article relates to Windows Embedded Compact 7 (WEC7), the same is applicable to Windows Embedded Compact 2013 (WEC2013/CE8).
When I was porting a BSP and OSDesign from Windows CE 6.0 to Windows Embedded Compact 7, I ran into some issues regarding localization that I would like to share with you today.
Upgrading your OS from Windows CE 6.0 to Windows Embedded Compact 7
When you are in the process of upgrading or porting Windows CE 6.0 to Windows Embedded Compact 7 or Windows Embedded Compact 2013, you might face some hurdles to get it all working. Once you manage to overcome all hurdles and the operation system is running you're almost done. All you need to do now is adding some missing locales to the OSDesign. That can't be that hard, can it?
In the good old days of Windows CE 6.0 this was easy. You just had to select the locales you wanted to support in your OS in the properties page of your OSDesign. Simply right click on your OSDesign in the solution explorer, select properties and navigate to the locale tab. That tab page allows you to select the locales you want to support in your OS, then do a rebuild, and that's it.
Unfortunately, with Windows CE 7 this is all not so easy anymore. I have no idea why on earth this functionality was 'streamlined', but there are more decisions made around Windows CE that escape any sane reasoning I guess....
To get it all to work in Windows Embedded Compact 7 or 2013 you need to perform some extra steps, and that's exactly what this blogpost will explain. I'll also show you that it is not possible to add ALL, seemingly supported, locales to your OSDesign. To all those people living in Friesland (part of The Netherlands) that speak Frisian or those from Inuktitut (Canada) that use syllabics and some others; sorry, you're out of luck when it comes to Windows Embedded Compact!
In short you need to:
- Add SYSGEN_NLS_XXX variables to the OSDesign
- Manually add locales to nlscfg.inf to include all the locales needed for the .NET CF
To show what locales the OS running on your device supports, I created a little test program that enumerates over the available locales and will try to set the culture info and compare information associated with the locale. When you run the application you will see, unless you configured a different default locale, that only one locale "English (United States)" is listed. When you try to use a locale not supported by the OS, for example
CultureInfo.CreateCulture("nl"), a PlatformNotSupportedException will be thrown by the managed application. This is reasonable because the locale was not supported in the first place.
The LocaleInfo test program looks like:
List<CultureInfo> supportedLocale = new List<CultureInfo>();
foreach (CultureInfo ci in CultureInfoHelper.GetCultures())
CultureInfo cultureInfo = CultureInfo.CreateSpecificCulture(ci.Name);
CompareInfo compareInfo = cultureInfo.CompareInfo;
// print out LCID
StringBuilder localeInfo = new StringBuilder();
foreach (CultureInfo locale in missingLocale)
localeInfo.Append(locale.LCID.ToString("X4") + " ");
As you can see, the program enumerates the available locales and the Language Identifier (LCID) is stored (and printed), which we will use later. The test application (LocaleInfo.zip) is attached to this blogpost (in full source code). The test application will create a file (locale_info.txt) containing the locale information for the OS it is running on.
Here's what we need to do to add locale support to your OS:
Selecting the right SYSGEN_NLS_XXX variables
The easiest way to add components (sysgen variables) to your OS is to select the sysgen variables in the Catalog: open your OSDesign and locate the catalog window. Navigate to "International" and select the country of the locale you want to add. Let's take Africa as example. Expand "Afrikaans", just like in the screenshot below. Now if you want to add the locale "Afrikaans", make sure you select both variables, otherwise it will not work. So; add SYSGEN_NLS_AF and SYSGEN_NLS_AF_ZA. Note that in order to support one single language you need to select two sysgen variables!
If you only want to support a few locales than going through the list and manually selecting the locales is not such a big problem. Just make sure that you select both variables per language/locale. Again an example; for the dutch language you'd need both SYSGEN_NLS_NL and SYSGEN_NLS_NL_NL.
In total, there are 197 locales available and if you want to add all those locales you will most likely end up with some form of RSI (Repetitive Strain Injury). To prevent this I created a little batch file that will set all locales that are supported in the catalog. I simply took the list of supported locales from <WINCEROOT>\public\CEBase\oak\misc\winceos.bat. If you're interested in that batch file please contact me and I'll send it to you.
Now that you have selected the locales you want and thus added sysgen variabls, you need to do a rebuild of the OS, so click Rebuild Solution (to understand what to build when read this blogpost).
If you select all available locales, rebuild the entire solution and run the test program again you will see, by examining locale_info.txt, that the application still detects unsupported locales. How is this possible? You've just added them all, didn't you?
Mysteries.. Apparently we need to add the missing locales manually to the OS:
Add locales to nlscfg.inf to support all locales needed for the .NET CF
Apparently adding the sysgen variables is not enough for some locales so we need to do a bit more, but first a little background information:
The .NET Compact framework depends on a 'list' of locales and this list is called the NLS Table. The NLS table describes the locale identifiers (LCIDs) available in your OS. For more information about the NLS Table and the nlscfg.inf, read this page on MSDN: Configuring the NLS Table. In short; the nlscfg.inf contains a list of LCIDs which should be in sync with the locales you enabled via the NLS sysgen variables. You can find the default nlscfg.inf in <WINCEROOT>\public\COMMON\oak\files.
When you run the test application LocaleInfo.exe, it will create a file containing locale information. A snippet from this generated locale_info.txt file:
Missing locale LCIDs
045E 3801 3C01 1401 0C01 0801 2C01 3401 3001 1001 1801 2001 4001 0401 2801 1C01
2401 047A 044D 082C 042C 046D 0423 0402 0845 0445 0451 047E 141A 0483 0405 0452
0465 0408 540A 0425 0429 0464 0462 083C 0484 0447 0468 040D 0439 101A 041A 042E
040E 042B 0470 0478 045D 0411 0437 043F 046F 0453 044B 0412 0457 0440 046E 0454
0427 0426 0481 042F 044C 0450 0850 047C 044E 043A 0461 046C 0482 0448 0446 0415
048C 0463 0486 046B 086B 0C6B 0417 0418 0419 0487 044F 0485 043B 045B 041B 0424
041C 1C1A 0C1A 301A 281A 181A 081A 2C1A 045A 0449 044A 0428 041E 0442 0432 041F
0444 085F 0480 0422 0420 0843 0443 042A 0488 0434 046A 0804 0C04 1404 1004 0404
The next step is to clone nlscfg.inf located in <WINCEROOT>\public\COMMON\oak\files to <WINCEROOT>\PLATFORM\<YOURBSP>\FILES and then add the list of missing LCIDs listed in locale_info.txt. The contents of the <WINCEROOT>\PLATFORM\<YOURBSP>\FILES folder are copied during the buildrel build phase and after that the makeimg phase will process and include all the locales listed in nlscfg.inf. If you click "Copy files to release directory" followed by a "Make Image", you will see that the makeimg build phase will exit with an error. The makeimg process will fail with error "The cenlscmp tool has exited with error code 1". If you examine the <WINCEROOT>\build.log, it will provide you with some additional information:
error MSB3073: The command "cenlscmp <WINCEROOT>\<OSDesign>\..\RelDir\Shipbuild\postproc\nlssrc.txt
<WINCEROOT>\<OSDesign>\..\RelDir\Shipbuild\nlscpg.txt" exited with code 1.
The first line "CeNlsCmp: Did not find locale 047a in locale file" informs you that apparently information is missing for LCID 047a somewhere. I have unfortunately not been able to track down the missing information, so either there is still something missing or there is a bug in the tooling.
I have gone through the process of removing all LCIDs that cause the cenlscmp to break and provide you with a list of all 'supported locales' that can be enabled, just in case you want it 'all'. Attached to this blogpost you'll find the zipped nlscfg.inf file.
In the locale_info.txt (also attached to this blogpost), you'll find a summary of supported and non-supported locales:
Total locales installed:197
Total locales supported:146
Total locales not supported:51
I hope that this information will save someone somewhere some time! ;-)