I wrote the following code to get the translated string from Resource Manager. The method GetTranslatedString
is called more than 50 times in my project.
public static string GetTranslatedString(string input, string culture)
{
if (string.IsNullOrEmpty(input)) return input;
string retInput = input;
CultureInfo cultureInfo = new CultureInfo(culture);
ResourceManager rm = new ResourceManager("Globalization.XYZ", Assembly.GetExecutingAssembly());
var entry = rm.GetResourceSet(cultureInfo, true, true)
.OfType<DictionaryEntry>()
.FirstOrDefault(e => e.Key.ToString().Equals(input, StringComparison.InvariantCultureIgnoreCase));
if (entry.Value == null) return retInput;
return entry.Value.ToString();
}
But I feel it's not perfect code because the ResourceManager
class gets new instances many times and since I'm calling GetTranslatedString
many times I am sure it will impact on performance.
Second major problem is, I am using reflection inside this code. and it's a costly operation.
It would helpful if I could get review on this.
-
\$\begingroup\$ updated the post, if there is no translation I am returning the input back. \$\endgroup\$kudlatiger– kudlatiger2015年10月09日 15:52:02 +00:00Commented Oct 9, 2015 at 15:52
1 Answer 1
public static string GetTranslatedString(string input, string culture) { if (string.IsNullOrEmpty(input)) return input; string retInput = input; CultureInfo cultureInfo = new CultureInfo(culture); ResourceManager rm = new ResourceManager("Tesla.TSS.Globalization.SchedulingSystem", Assembly.GetExecutingAssembly()); var entry = rm.GetResourceSet(cultureInfo, true, true) .OfType<DictionaryEntry>() .FirstOrDefault(e => e.Key.ToString().Equals(input, StringComparison.InvariantCultureIgnoreCase)); if (entry.Value == null) return retInput; return entry.Value.ToString(); }
Because the resources of your application won't change during runtime, the easiest way would be to once get the whole items and store them in a dictionary. Then your application can use the dictionary to retrieve the translated strings.
I would like to suggest to make this a little bit more flexible, so you could use it in other projects too.
At first the method which will retrieve the Dictionary<string,string>
from the ResourceManager
public static Dictionary<string, string> GetTranslations(CultureInfo cultureInfo, string baseName, Assembly assembly)
{
ResourceManager rm = new ResourceManager(baseName, assembly);
using (ResourceSet rs = rm.GetResourceSet(cultureInfo, true, true))
{
return rs.OfType<DictionaryEntry>()
.ToDictionary(r => r.Key.ToString(),
r => r.Value.ToString());
}
}
as you can see, this can be called independent from your current project.
Now let us add an overloaded method which takes the culture as a string like so
public static Dictionary<string, string> GetTranslations(string culture, string baseName, Assembly assembly)
{
CultureInfo cultureInfo = new CultureInfo(culture);
return GetTranslations(cultureInfo, baseName, assembly);
}
In your project you can call it now like
Dictionary<string,string> translations = GetTranslations(culture, "Tesla.TSS.Globalization.SchedulingSystem", Assembly.GetExecutingAssembly());
and you could query this to get the translated strings.
You could have a method ChangeLanguage(string culture)
like so
private string currentCultureName = "en-Us";
private void ChangeLanguage(string culture)
{
if (string.IsNullOrWhiteSpace(culture))
{
currentCultureName = CultureInfo.CurrentUICulture.Name;
}
else
{
currentCultureName = culture;
}
translations = GetTranslations(culture, "Tesla.TSS.Globalization.SchedulingSystem", Assembly.GetExecutingAssembly());
}
to change the current dictionary.
Your former GetTranslatedString()
method should then live as a class method (not static) inside your project and should look like so
public string GetTranslatedString(string input, string culture)
{
if (input == null) { throw new ArgumentNullException("input"); }
if (string.IsNullOrWhiteSpace(input)) { return input; }
if (currentCultureName != culture)
{
ChangeLanguage(culture);
}
string translation;
if (translations.TryGetValue(input, out translation))
{
return translation;
}
return input;
}
As you can see I have change quite a few things like
adding braces
{}
although they are optional for single lineif
statements, but they will make the code less error prone.for a passed in
input
which isnull
this will throw anArgumentNullException
which is much better than just returning thenull
.for the passed in
culture
I didn't add anull
check, because if theChangeLanguage()
method will be called with anull
value the name of theCurrentUICulture
will be used.
-
\$\begingroup\$ Thank you. I am implementing it. sounds good. keep you posted \$\endgroup\$kudlatiger– kudlatiger2015年10月09日 19:10:11 +00:00Commented Oct 9, 2015 at 19:10
-
\$\begingroup\$ I am just doing sample project for my school academic. your way of reviewing helped a lot, we all students learned a lot in this answer. Thank you with respect Heslacher. \$\endgroup\$kudlatiger– kudlatiger2015年10月09日 19:53:08 +00:00Commented Oct 9, 2015 at 19:53