Reputation: 5578
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
Reputation: 7618
Let's assume your project looks like this:
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:
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