{"id":116,"date":"2014-10-14T23:39:24","date_gmt":"2014-10-14T23:39:24","guid":{"rendered":"http:\/\/blog.electrongoo.com\/?p=116"},"modified":"2017-05-02T15:44:58","modified_gmt":"2017-05-02T15:44:58","slug":"localizing-windows-applications","status":"publish","type":"post","link":"http:\/\/blog.electrongoo.com\/index.php\/localizing-windows-applications\/","title":{"rendered":"Localizing Windows applications"},"content":{"rendered":"<h1>Background:<\/h1>\n<p>The amazing global economy opens many doors to your software product. Localizing your software in different languages will improve its success. While many people whose primary language is not English can probably trudge their way through your non-localized English software, a localized version of your software will always be a benefit; both to your customers and your product viability.<\/p>\n<p>The task of localizing software varies based on the platform (iOS, Android, Windows desktop, Linux, etc) as well as the language being used (Java, C#, C++, Objective C, etc). Many old-school software engineers might recall a time when localization was designed and coded in-house; typically once, and then that software code was re-used on other projects. Regardless, the process was typically tedious and prone to bugs and glitches. Fortunately, today, the major development platforms offer simple localization features built-into their developer stack. This post will discuss localization of Windows applications using C#. View this<a href=\"http:\/\/blog.electrongoo.com\/localizing-android-applications\/\"> other post regarding localization in Java on Android<\/a>.<\/p>\n<h1>The task:<\/h1>\n<p>Okay, so you just created a cool Windows application in C# and now you\u2019ve been tasked with localizing it into fourteen different languages. After staring at your non-localized application project in Visual Studio and searching the Internet you probably have some confusion about how difficult localizing your project actually is. I\u2019ve seen many people obfuscate the simplicity of the task. There are various methods, but if you follow some simple rules, the process can be very painless. Adding new languages to a localization-ready project at any time in the project cycle is a simple process too!<\/p>\n<h1>Step by step:<\/h1>\n<p>Open your project in Visual Studio. From the solution Explorer right-click on you project name and select Add | New Folder and name the folder Resources<\/p>\n<figure id=\"attachment_127\" aria-describedby=\"caption-attachment-127\" style=\"width: 474px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcefolder.png\"><img loading=\"lazy\" class=\"size-large wp-image-127\" src=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcefolder-1024x586.png\" alt=\"Create resource folder in Visual Studio\" width=\"474\" height=\"271\" srcset=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcefolder-1024x586.png 1024w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcefolder-300x171.png 300w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcefolder.png 1246w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><figcaption id=\"caption-attachment-127\" class=\"wp-caption-text\">Create resource folder in Visual Studio<\/figcaption><\/figure>\n<p>&nbsp;<\/p>\n<p>From the Installed Templates section, select Visual C# Items and then select Resource Files. This first resource file will contain your default native English resources strings. Name the file generically <strong>resources.resx<\/strong> to simplify the process.<\/p>\n<figure id=\"attachment_125\" aria-describedby=\"caption-attachment-125\" style=\"width: 955px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcedll-1.png\"><img loading=\"lazy\" class=\"size-full wp-image-125\" src=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcedll-1.png\" alt=\"Select Resource Dll to add to project\" width=\"474\" height=\"271\" \/><\/a><figcaption id=\"caption-attachment-125\" class=\"wp-caption-text\">Select Resource Dll to add to project<\/figcaption><\/figure>\n<p>A new resource file will be created and will be displayed in Visual Studio ready for you to add the resource strings.<\/p>\n<figure id=\"attachment_133\" aria-describedby=\"caption-attachment-133\" style=\"width: 474px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/newresourcefile.png\"><img loading=\"lazy\" class=\"size-large wp-image-133\" src=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/newresourcefile-1024x718.png\" alt=\"New native English resource file created\" width=\"474\" height=\"271\" \/><\/a><figcaption id=\"caption-attachment-133\" class=\"wp-caption-text\">New native English resource file created<\/figcaption><\/figure>\n<p>Enter each of the strings used in your project in the resx file.\u00a0\u00a0 In the <strong>Name<\/strong> column enter a unique name that you can reference the string from within your code. I recommend prefixing each of your string names with <strong>str_<\/strong> to make your source code easier to read. Enter the string as it will appear to the user in your software under the <strong>Value<\/strong> column. You will do this for each string in your project. Don\u2019t worry if you don\u2019t enter all of the strings at this time, you can always return and enter more strings.\u00a0\u00a0 The key to success here is to ensure that your first resource file is complete, and contains ALL strings, before you begin to create additional resource files. You can add new strings at any time but make sure you add each new string to ALL resx files you create.<\/p>\n<figure id=\"attachment_121\" aria-describedby=\"caption-attachment-121\" style=\"width: 474px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/adddefaultstrings.png\"><img loading=\"lazy\" class=\"size-large wp-image-121\" src=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/adddefaultstrings-1024x634.png\" alt=\"Native English resources added to resx file\" width=\"474\" height=\"293\" srcset=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/adddefaultstrings-1024x634.png 1024w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/adddefaultstrings-300x186.png 300w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/adddefaultstrings.png 1150w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><figcaption id=\"caption-attachment-121\" class=\"wp-caption-text\">Native English resources added to resx file<\/figcaption><\/figure>\n<p>From the Solution Explorer, open one of your dialog files. Note, you will obviously have multiple dialog files for a single project; you will need to process each file. In the Design layout window make sure the dialog is selected then go to the Properties page and select the Events button (this will appear as a lightning bolt).<\/p>\n<figure id=\"attachment_122\" aria-describedby=\"caption-attachment-122\" style=\"width: 474px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/addloadevent.png\"><img loading=\"lazy\" class=\"size-large wp-image-122\" src=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/addloadevent-1024x634.png\" alt=\"Add the Load() event handler to each dialog resource\" width=\"474\" height=\"293\" srcset=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/addloadevent-1024x634.png 1024w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/addloadevent-300x186.png 300w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/addloadevent.png 1150w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><figcaption id=\"caption-attachment-122\" class=\"wp-caption-text\">Add the Load() event handler to each dialog resource<\/figcaption><\/figure>\n<p>Scroll down to the \u201cLoad\u201d event and double-click. The wizard will automatically create a new Load function, if it does not exist, which will be called by the Windows framework when the dialog is loaded but before it is displayed to the user. This is the preferred Windows event to handle updating resources in dialog boxes.<\/p>\n<figure id=\"attachment_123\" aria-describedby=\"caption-attachment-123\" style=\"width: 474px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/addloadeventnewfunction.png\"><img loading=\"lazy\" class=\"size-large wp-image-123\" src=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/addloadeventnewfunction-1024x634.png\" alt=\"Event handler automatically added\" width=\"474\" height=\"293\" srcset=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/addloadeventnewfunction-1024x634.png 1024w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/addloadeventnewfunction-300x186.png 300w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/addloadeventnewfunction.png 1150w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><figcaption id=\"caption-attachment-123\" class=\"wp-caption-text\">Event handler automatically added<\/figcaption><\/figure>\n<p>Now, within the Load() event handler,\u00a0set the Text field for each of the controls within your dialog to a string you created in the resource file. You will use the <strong>Resources.Resource<\/strong> class to resolve each string<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprivate void Form_Login_Load(object sender, EventArgs e)\r\n{\r\n  label_userName.Text = Resources.Resource.str_user_name;\r\n  label_password.Text = Resources.Resource.str_password;\r\n  button_login.Text = Resources.Resource.str_login;\r\n}\r\n<\/pre>\n<p>Now, simply repeat the steps above for each dialog in your project. If you do this during initial development of your project it makes the task much easier. At this point, you have a fully ready to localize project.<\/p>\n<p>Now that you have all your dialogs using resources files and you have a base native English resource file, you can start creating new resources files; one for each language you want your project to support. The steps are similar to creating the base English resource file above. Right-click on the <strong>Resources<\/strong> folder and select <strong>Add<\/strong> | <strong>New Item<\/strong> then select <strong>Resources File<\/strong> and name the file based on the language being added. You must use the filename convention <strong>resources.XX.resx<\/strong> where <strong>XX<\/strong> is the two-letter language identifier. Doing so will greatly simply the localization process. For example, to create a German resource file create the file named <strong>Resource.de.resx<\/strong> and to create a French resource file create the file named <strong>Resource.fr.resx.<\/strong><\/p>\n<figure id=\"attachment_126\" aria-describedby=\"caption-attachment-126\" style=\"width: 955px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcedllforgerman.png\"><img loading=\"lazy\" class=\"size-full wp-image-126\" src=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcedllforgerman.png\" alt=\"Create a new resource file for localized text\" width=\"955\" height=\"660\" srcset=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcedllforgerman.png 955w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/createresourcedllforgerman-300x207.png 300w\" sizes=\"(max-width: 955px) 100vw, 955px\" \/><\/a><figcaption id=\"caption-attachment-126\" class=\"wp-caption-text\">Create a new resource file for localized text<\/figcaption><\/figure>\n<p>Now you have a new resource file to contain the strings for a new language.\u00a0\u00a0 Now return to the base native English <strong>Resource.resx<\/strong> file and click on the box in the upper-left corner (or press Control-A) to select all of the strings and press Control-C to copy the strings to the Windows clipboard. Return to the newly created <strong>Resouce.de.resx<\/strong> file and press Control-V to paste the strings from the Windows clipboard into the new resx file.<\/p>\n<figure id=\"attachment_130\" aria-describedby=\"caption-attachment-130\" style=\"width: 474px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/newgernamestringsinresx.png\"><img loading=\"lazy\" class=\"size-large wp-image-130\" src=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/newgernamestringsinresx-1024x745.png\" alt=\"Copy existing English resource strings into the new resource file\" width=\"474\" height=\"344\" srcset=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/newgernamestringsinresx-1024x745.png 1024w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/newgernamestringsinresx-300x218.png 300w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/newgernamestringsinresx.png 1150w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><figcaption id=\"caption-attachment-130\" class=\"wp-caption-text\">Copy existing English resource strings into the new resource file<\/figcaption><\/figure>\n<p>It\u2019s that simple! Now, you have a localization-ready project which supports two languages. You can easily add new languages by creating new resources files under the <strong>Resources<\/strong> folder at any time. The key is to use the naming convention <strong>Resource.XX.resx<\/strong> as discussed above.<\/p>\n<p>When you build your project, the resource files will automatically be created under subfolders named <strong>XX<\/strong>, where <strong>XX<\/strong> is the language code of the <strong>Resource.XX.resx<\/strong> file you created.<\/p>\n<figure id=\"attachment_129\" aria-describedby=\"caption-attachment-129\" style=\"width: 928px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/finalfolders.png\"><img loading=\"lazy\" class=\"size-full wp-image-129\" src=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/finalfolders.png\" alt=\"Language folders automatically created during Visual Studio build\" width=\"928\" height=\"434\" srcset=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/finalfolders.png 928w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/finalfolders-300x140.png 300w\" sizes=\"(max-width: 928px) 100vw, 928px\" \/><\/a><figcaption id=\"caption-attachment-129\" class=\"wp-caption-text\">Language folders automatically created during Visual Studio build<\/figcaption><\/figure>\n<p>Each subfolder will contain the resource strings for the specific language<\/p>\n<figure id=\"attachment_128\" aria-describedby=\"caption-attachment-128\" style=\"width: 928px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/finalfile.png\"><img loading=\"lazy\" class=\"size-full wp-image-128\" src=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/finalfile.png\" alt=\"Language dll located in its language folder\" width=\"928\" height=\"434\" srcset=\"http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/finalfile.png 928w, http:\/\/blog.electrongoo.com\/wp-content\/uploads\/2014\/10\/finalfile-300x140.png 300w\" sizes=\"(max-width: 928px) 100vw, 928px\" \/><\/a><figcaption id=\"caption-attachment-128\" class=\"wp-caption-text\">Language dll located in its language folder<\/figcaption><\/figure>\n<p>Finally, provide the <strong>Resource.XX.resx<\/strong> files you created to your localization provider such as <a href=\"http:\/\/www.inwhatlanguage.com\">inwhatlanguage.com<\/a> for localization. When the resx files are returned to you, simply drop them into your project overwriting the previous temporary English versions and rebuild your project.<\/p>\n<p>Make sure your project installer creates an identical folder structure under the folder containing your executable (this folder structure should look identical to the folder created by Visual Studio after a build).\u00a0\u00a0 When you project starts it will automatically search that folder structure for a supporting language id. If\u00a0the\u00a0resource dll for that language\u00a0exists then the resource file will be loaded. If it does not exist then the default native English resource file will be used.<\/p>\n<h1>Debugging:<\/h1>\n<p>Debugging new localization files is simple.\u00a0 Simply add the following lines of temporary code to\u00a0the primary\u00a0Load() event handler in your project<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nusing System.Globalization;\r\n\r\nprivate void Form_Login_Load(object sender, EventArgs e)\r\n{\r\n   Thread.CurrentThread.CurrentCulture = new CultureInfo(&quot;de-DE&quot;);        \/\/e.g. de-DE   zh-CN   ja-JP\r\n\r\n<\/pre>\n<p>Set the <strong>CultureInfo<\/strong> string\u00a0specified in the constructor\u00a0to the language-region code you wish to test.\u00a0 For example, to test German in Germany use &#8220;de-DE&#8221; and for Chinese in Hong Kong use &#8220;zh-HK.&#8221;\u00a0\u00a0 A full list of language and region codes can be <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ee825488(v=cs.20).aspx\">found here<\/a>.\u00a0 Rebuild and run your project and the strings from the specified locality will be displayed automatically.<\/p>\n<h1>Tips:<\/h1>\n<ul>\n<li>Even if you don\u2019t have current plans to support localization, always build new projects targeted for localization by moving your text strings into a resource file and use the <strong>Resources.resource<\/strong> class to update all your user visible components<\/li>\n<li>Always name resource files with the format <strong>Resource.XX.resx<\/strong> (where <strong>XX<\/strong> is the two-letter language id) to simplify the build process<\/li>\n<li>Make sure your first native English resource file contains all of the strings before creating localized resource files. Adding new (or forgotten) strings to each localized resource file can be a painful repetitious task prone to errors<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Background: The amazing global economy opens many doors to your software product. Localizing your software in different languages will improve its success. While many people whose primary language is not English can probably trudge their way through your non-localized English software, a localized version of your software will always be a benefit; both to your &hellip; <a href=\"http:\/\/blog.electrongoo.com\/index.php\/localizing-windows-applications\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Localizing Windows applications<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[],"_links":{"self":[{"href":"http:\/\/blog.electrongoo.com\/index.php\/wp-json\/wp\/v2\/posts\/116"}],"collection":[{"href":"http:\/\/blog.electrongoo.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.electrongoo.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.electrongoo.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.electrongoo.com\/index.php\/wp-json\/wp\/v2\/comments?post=116"}],"version-history":[{"count":4,"href":"http:\/\/blog.electrongoo.com\/index.php\/wp-json\/wp\/v2\/posts\/116\/revisions"}],"predecessor-version":[{"id":139,"href":"http:\/\/blog.electrongoo.com\/index.php\/wp-json\/wp\/v2\/posts\/116\/revisions\/139"}],"wp:attachment":[{"href":"http:\/\/blog.electrongoo.com\/index.php\/wp-json\/wp\/v2\/media?parent=116"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.electrongoo.com\/index.php\/wp-json\/wp\/v2\/categories?post=116"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.electrongoo.com\/index.php\/wp-json\/wp\/v2\/tags?post=116"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}