row1
row1

Reputation: 5578

.NET Localization Project Structure subfolders for each language

I have created a new C# class library project which will contain the resource files for all translations. The examples I have seen have a flat structure with one giant resource file for each language like this:

But for this particular project it is preferred to split the resource files into logical groupings:

This will get messy when we add more resource files and more translations, so it would be more manageable to have sub-folders for each language e.g.

But doing this will add the language code to the namespace e.g. Translations.en-GB.SystemMessages.MyString and I assume because en-GB is now in the namespace that the resource manager will no longer be able to find the fr-FR translation.

How can I put the resources into sub-folders based on the language code?

Upvotes: 4

Views: 1371

Answers (1)

George Vovos
George Vovos

Reputation: 7618

Let's assume your project looks like this:

enter image description here

You could use different ResourceManager depending on the Thread Culture.
With a small T4 template you can make it strongly typed(iterate the resource file and create a property for each string)

using ConsoleApplication6.Translations.French;
using System;
using System.Resources;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(SystemMessagesManager.GetString("Title"));
            Console.ReadLine();
        }

       public static class SystemMessagesManager
       {
           static ResourceManager rsManager;
           static SystemMessagesManager()
           {
               //Get the current manager based on the current Culture
              if (Thread.CurrentThread.CurrentCulture.Name == "fr-FR")
                   rsManager = SystemMessagesFrench.ResourceManager;
              else if (Thread.CurrentThread.CurrentCulture.Name == "el-GR")
                   rsManager = SystemMessagesGreek.ResourceManager;
              else
                   rsManager = SystemMessagesEnglish.ResourceManager;
           }
           public static string GetString(string Key)
           {
              return rsManager.GetString(Key) ?? SystemMessagesEnglish.ResourceManager.GetString(Key);
           }
       }
   }
}

About the T4 template,check this :
How to use a resx resource file in a T4 template
Below you can see a sample code.
Let's say you have this in your project: enter image description here

Using the following template you can auto generate the class:

<#@ template debug="false" hostspecific="true" language="C#" #>

<#@ assembly name="System" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Linq" #>

<#@ output extension=".cs" #>
using System.Resources;
using System.Threading;

namespace YourNameSpace
{
    public static class SystemMessagesManager
    {       
        static ResourceManager rsManager;
        static SystemMessagesManager()
        {
               //Get the current manager based on the current Culture
              if (Thread.CurrentThread.CurrentCulture.Name == "fr-FR")
                    rsManager = SystemMessagesFrench.ResourceManager;
              else if (Thread.CurrentThread.CurrentCulture.Name == "el-GR")
                    rsManager = SystemMessagesGreek.ResourceManager;
              else
                    rsManager = SystemMessagesEnglish.ResourceManager;
         }
        private static string GetString(string Key)
        {
              return rsManager.GetString(Key) ?? SystemMessagesEnglish.ResourceManager.GetString(Key);
        }

        <# 
         XmlDocument xml = new XmlDocument();        
         xml.Load(Host.ResolvePath(@"ResourceStrings.resx"));

         foreach(string key in xml.SelectNodes("root/data").Cast<XmlNode>().Select(xn => xn.Attributes["name"].Value)){
         #>
public static string <#= key #> { get { return GetString("<#=key#>"); } }
        <# } #>                 
    }
}

Upvotes: 1

Related Questions