如何使用 KeyValuePair 从 List 中获取 ListDictionary 来翻译一些字符串?
How to get ListDictionary from List with KeyValuePair to translate some string?
我需要翻译以编程方式更改的标签文本。
因此,我建立了一个带有翻译的列表。列表概念如下所示:
translation["de"]["label1"] = "german text";
translation["en"]["label1"] = "english text";
这是我构建列表的实际代码:
public List<KeyValuePair<string, ListDictionary>> translations = new List<KeyValuePair<string, ListDictionary>>();
ListDictionary tDE = new ListDictionary();
ListDictionary tEN = new ListDictionary();
tDE.Add("label1", "german text");
tEN.Add("label1", "english text");
translations.Add(new KeyValuePair<string, ListDictionary>("de", tDE));
translations.Add(new KeyValuePair<string, ListDictionary>("en", tEN));
我现在如何获得翻译的价值?
我的做法是这样的:
public string getLocStr(string lang, string key)
{
string str = "";
foreach (var trans in translations)
{
// how to get a List<string,string> to retrieve the $value from by $key?
// eg: str = trans[$lang][$key]
}
return str;
}
有这样一个枚举:
public enum Language
{
None,
EN,
FR
}
使用:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.Serialization;
using System.Text;
using EnumsNET;
并拥有那本词典:
[Serializable]
class TranslationsDictionary : NullSafeOfStringDictionary<Language>
{
public TranslationsDictionary() : base()
{
}
protected TranslationsDictionary(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
来自这个:
[Serializable]
public class NullSafeOfStringDictionary<T> : Dictionary<T, string>
{
public NullSafeOfStringDictionary()
{
}
public NullSafeOfStringDictionary(int capacity) : base(capacity)
{
}
public NullSafeOfStringDictionary(IEqualityComparer<T> comparer) : base(comparer)
{
}
public NullSafeOfStringDictionary(IDictionary<T, string> dictionary) : base(dictionary)
{
}
public NullSafeOfStringDictionary(int capacity, IEqualityComparer<T> comparer) : base(capacity, comparer)
{
}
public NullSafeOfStringDictionary(IDictionary<T, string> dictionary, IEqualityComparer<T> comparer) : base(dictionary, comparer)
{
}
protected NullSafeOfStringDictionary(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
public new string this[T key]
{
get
{
return ContainsKey(key) ? base[key] : null;
}
set
{
if ( ContainsKey(key) )
base[key] = value;
else
Add(key, value);
}
}
}
你可以使用这个 class:
static class Localizer
{
private const string ERR = "<Not translated>";
/// <summary>
/// Get the string translation.
/// </summary>
/// <param name="values">The dictionary containing lang>translation.</param>
static public string GetLang(this TranslationsDictionary values)
{
return values?[Languages.Current] ?? values?[Languages.Default] ?? ERR;
}
/// <summary>
/// Get the string translation.
/// </summary>
/// <param name="values">The dictionary containing lang>translation.</param>
/// <param name="parameters">Parameters for the translated string.</param>
static public string GetLang(this TranslationsDictionary values, params object[] parameters)
{
return string.Format(values?.GetLang(), parameters) ?? ERR + " " + string.Join(",", parameters);
}
/// <summary>
/// Get the string translation.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <param name="values">The dictionary containing value>lang>translation.</param>
/// <param name="value">The value to translate.</param>
/// <param name="forceEnglish">True to force get in english.</param>
static public string GetLang<T>(this NullSafeDictionary<T, TranslationsDictionary> values, T value, bool forceEnglish = false)
{
var lang = forceEnglish ? Language.EN : Languages.Current;
return values?[value]?[lang] ?? values?[value]?[Languages.Default] ?? ERR;
}
/// <summary>
/// Get the list translation.
/// </summary>
/// <param name="values">The dictionary containing lang>list.</param>
static public NullSafeStringList GetLang(this NullSafeDictionary<Language, NullSafeStringList> values)
{
return values?[Languages.Current] ?? values?[Languages.Default] ?? new NullSafeStringList();
}
/// <summary>
/// Get the list translation.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <param name="values">The dictionary containing lang>list.</param>
static public NullSafeList<T> GetLang<T>(this NullSafeDictionary<Language, NullSafeList<T>> values)
where T : class
{
return values?[Languages.Current] ?? values?[Languages.Default] ?? new NullSafeList<T>();
}
/// <summary>
/// Get the string list translation.
/// </summary>
/// <param name="values">The dictionary containing lang>translations.</param>
static public string[] GetLang(this NullSafeDictionary<Language, string[]> values)
{
return values?[Languages.Current] ?? values?[Languages.Default] ?? new string[1] { ERR };
}
/// <summary>
/// Get the string translation.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <param name="values">The dictionary containing lang>value>translation.</param>
/// <param name="value">The value to translate.</param>
static public string GetLang<T>(this NullSafeDictionary<Language, NullSafeOfStringDictionary<T>> values, T value)
where T : Enum
{
return values?[Languages.Current]?[value] ?? values?[Languages.Default]?[value] ?? ERR;
}
/// <summary>
/// Remove diacritics signs.
/// </summary>
public static string RemoveDiacritics(this string str)
{
if ( str.IsNullOrEmpty() ) return str;
var normalized = str.Normalize(NormalizationForm.FormD);
var builder = new StringBuilder();
foreach ( var c in normalized )
if ( CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark )
builder.Append(c);
return builder.ToString().Normalize(NormalizationForm.FormC);
}
}
还有:
[Serializable]
public class NullSafeList<T> : List<T>
where T : class
{
public NullSafeList()
{
}
public NullSafeList(int capacity) : base(capacity)
{
}
public NullSafeList(IEnumerable<T> collection) : base(collection)
{
}
public new T this[int index]
{
get
{
CheckIndex(index);
return index < Count ? base[index] : null;
}
set
{
CheckIndex(index);
if ( index < Count )
base[index] = value;
else
CreateOutOfRange(index, value);
}
}
private void CheckIndex(int index)
{
if ( index >= 0 ) return;
throw new IndexOutOfRangeException(SysTranslations.IndexCantBeNegative.GetLang(nameof(NullSafeStringList), index));
}
private void CreateOutOfRange(int index, T value)
{
Capacity = index + 1;
int count = index + 1 - Count;
for ( int i = 0; i < count; i++ )
Add(null);
base[index] = value;
}
}
以及以下 class:
static class Languages
{
/// <summary>
/// Indicate language codes.
/// </summary>
static public readonly NullSafeOfEnumDictionary<string, Language> Values;
/// <summary>
/// Indicate language codes.
/// </summary>
static public readonly NullSafeOfStringDictionary<Language> Codes;
/// <summary>
/// Indicate managed languages.
/// </summary>
static public readonly Language[] Managed;
/// <summary>
/// Indicate default language.
/// </summary>
static public readonly Language Default = Language.EN;
/// <summary>
/// Indicate current language code.
/// </summary>
static public string CurrentCode => Codes[Current];
/// <summary>
/// Indicate current language.
/// </summary>
static public Language Current
{
get
{
string lang = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
var result = Values[lang];
if ( !Managed.Contains(result) ) result = Default;
return result;
}
}
/// <summary>
/// Static constructor.
/// </summary>
static Languages()
{
try
{
Managed = Enums.GetValues<Language>().Skip(1).ToArray();
Codes = new NullSafeOfStringDictionary<Language>(Managed.ToDictionary(v => v, v => v.ToString().ToLower()));
Values = new NullSafeOfEnumDictionary<string, Language>(Codes.ToDictionary(v => v.Value, v => v.Key));
}
catch ( Exception ex )
{
MessageBox.Show(ex.message);
}
}
}
您可以简化并删除不需要的所有内容。
[Serializable]
public class NullSafeOfEnumDictionary<TKey, TValue> : Dictionary<TKey, TValue>
where TValue : Enum
{
public NullSafeOfEnumDictionary()
{
}
public NullSafeOfEnumDictionary(int capacity) : base(capacity)
{
}
public NullSafeOfEnumDictionary(IEqualityComparer<TKey> comparer) : base(comparer)
{
}
public NullSafeOfEnumDictionary(IDictionary<TKey, TValue> dictionary) : base(dictionary)
{
}
public NullSafeOfEnumDictionary(int capacity, IEqualityComparer<TKey> comparer) : base(capacity, comparer)
{
}
public NullSafeOfEnumDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) : base(dictionary, comparer)
{
}
protected NullSafeOfEnumDictionary(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
public new TValue this[TKey key]
{
get
{
return ContainsKey(key) ? base[key] : default;
}
set
{
if ( ContainsKey(key) )
base[key] = value;
else
Add(key, value);
}
}
}
用法:
static class SysTranslations
{
static public readonly TranslationsDictionary NotImplemented
= new TranslationsDictionary
{
[Language.EN] = "Not implemented: {0}",
[Language.FR] = "Non implémenté : {0}",
};
}
string msg = SysTranslations.NotImplemented.GetLang("...");
Load/Write
static class NullSafeOfStringDictionaryHelper
{
static public bool LoadKeyValuePairs(this NullSafeOfStringDictionary<string> list,
string filePath,
string separator,
bool showError = true)
{
try
{
list.Clear();
foreach ( string line in File.ReadAllLines(filePath) )
if ( !line.StartsWith(";") && !line.StartsWith("//") )
{
var parts = line.SplitNoEmptyLines(separator);
if ( parts.Length == 1 )
list.Add(parts[0].Trim(), string.Empty);
else
if ( parts.Length == 2 )
list.Add(parts[0].Trim(), parts[1].Trim());
else
if ( parts.Length > 2 )
list.Add(parts[0].Trim(), string.Join(separator, parts.Skip(1)));
}
return true;
}
catch ( Exception ex )
{
if ( showError )
MessageBox.Show(SysTranslations.LoadFileError.GetLang(filePath, ex.Message),
Globals.AssemblyTitle,
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return false;
}
}
static public bool SaveKeyValuePairs(this NullSafeOfStringDictionary<string> list,
string filePath,
string separator,
bool showError = true)
{
using ( var stream = File.CreateText(filePath) )
try
{
foreach ( var item in list )
if ( !item.Key.StartsWith(";") && !item.Key.StartsWith("//") )
stream.WriteLine(item.Key + separator + item.Value);
else
stream.WriteLine(item.Key);
stream.Close();
return true;
}
catch ( Exception ex )
{
if ( showError )
MessageBox.Show(SysTranslations.LoadFileError.GetLang(filePath, ex.Message),
Globals.AssemblyTitle,
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return false;
}
}
}
最后这个比上面的更粗略。
使用此示例并使用 linq 来执行此操作:
class Program
{
public static List<Dictionary<string, Dictionary<string, string>>> translations = new List<Dictionary<string, Dictionary<string, string>>>();
public static Dictionary<string, Dictionary<string, string>> dic = new Dictionary<string, Dictionary<string, string>>();
static void Main(string[] args)
{
Dictionary<string,string> tDE = new Dictionary<string, string>();
Dictionary<string, string> tEN = new Dictionary<string, string>();
tEN.Add("label1", "english text");
tDE.Add("label1", "german text");
dic.Add("en", tEN);
dic.Add("de", tDE);
translations.Add(dic);
Console.WriteLine(getLocStr("de", "label1"));
Console.Read();
}
public static string getLocStr(string lang, string key)
{
string str = "";
foreach (var trans in translations)
{
var langDic = trans.FirstOrDefault(c => c.Key == lang);
if(langDic.Value!=null)
{
str = langDic.Value.FirstOrDefault(c => c.Key == key).Value;
}
// how to get a List<string,string> to retrieve the $value from by $key?
// eg: str = trans[$lang][$key]
}
return str;
}
}
我需要翻译以编程方式更改的标签文本。 因此,我建立了一个带有翻译的列表。列表概念如下所示:
translation["de"]["label1"] = "german text";
translation["en"]["label1"] = "english text";
这是我构建列表的实际代码:
public List<KeyValuePair<string, ListDictionary>> translations = new List<KeyValuePair<string, ListDictionary>>();
ListDictionary tDE = new ListDictionary();
ListDictionary tEN = new ListDictionary();
tDE.Add("label1", "german text");
tEN.Add("label1", "english text");
translations.Add(new KeyValuePair<string, ListDictionary>("de", tDE));
translations.Add(new KeyValuePair<string, ListDictionary>("en", tEN));
我现在如何获得翻译的价值?
我的做法是这样的:
public string getLocStr(string lang, string key)
{
string str = "";
foreach (var trans in translations)
{
// how to get a List<string,string> to retrieve the $value from by $key?
// eg: str = trans[$lang][$key]
}
return str;
}
有这样一个枚举:
public enum Language
{
None,
EN,
FR
}
使用:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.Serialization;
using System.Text;
using EnumsNET;
并拥有那本词典:
[Serializable]
class TranslationsDictionary : NullSafeOfStringDictionary<Language>
{
public TranslationsDictionary() : base()
{
}
protected TranslationsDictionary(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
来自这个:
[Serializable]
public class NullSafeOfStringDictionary<T> : Dictionary<T, string>
{
public NullSafeOfStringDictionary()
{
}
public NullSafeOfStringDictionary(int capacity) : base(capacity)
{
}
public NullSafeOfStringDictionary(IEqualityComparer<T> comparer) : base(comparer)
{
}
public NullSafeOfStringDictionary(IDictionary<T, string> dictionary) : base(dictionary)
{
}
public NullSafeOfStringDictionary(int capacity, IEqualityComparer<T> comparer) : base(capacity, comparer)
{
}
public NullSafeOfStringDictionary(IDictionary<T, string> dictionary, IEqualityComparer<T> comparer) : base(dictionary, comparer)
{
}
protected NullSafeOfStringDictionary(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
public new string this[T key]
{
get
{
return ContainsKey(key) ? base[key] : null;
}
set
{
if ( ContainsKey(key) )
base[key] = value;
else
Add(key, value);
}
}
}
你可以使用这个 class:
static class Localizer
{
private const string ERR = "<Not translated>";
/// <summary>
/// Get the string translation.
/// </summary>
/// <param name="values">The dictionary containing lang>translation.</param>
static public string GetLang(this TranslationsDictionary values)
{
return values?[Languages.Current] ?? values?[Languages.Default] ?? ERR;
}
/// <summary>
/// Get the string translation.
/// </summary>
/// <param name="values">The dictionary containing lang>translation.</param>
/// <param name="parameters">Parameters for the translated string.</param>
static public string GetLang(this TranslationsDictionary values, params object[] parameters)
{
return string.Format(values?.GetLang(), parameters) ?? ERR + " " + string.Join(",", parameters);
}
/// <summary>
/// Get the string translation.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <param name="values">The dictionary containing value>lang>translation.</param>
/// <param name="value">The value to translate.</param>
/// <param name="forceEnglish">True to force get in english.</param>
static public string GetLang<T>(this NullSafeDictionary<T, TranslationsDictionary> values, T value, bool forceEnglish = false)
{
var lang = forceEnglish ? Language.EN : Languages.Current;
return values?[value]?[lang] ?? values?[value]?[Languages.Default] ?? ERR;
}
/// <summary>
/// Get the list translation.
/// </summary>
/// <param name="values">The dictionary containing lang>list.</param>
static public NullSafeStringList GetLang(this NullSafeDictionary<Language, NullSafeStringList> values)
{
return values?[Languages.Current] ?? values?[Languages.Default] ?? new NullSafeStringList();
}
/// <summary>
/// Get the list translation.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <param name="values">The dictionary containing lang>list.</param>
static public NullSafeList<T> GetLang<T>(this NullSafeDictionary<Language, NullSafeList<T>> values)
where T : class
{
return values?[Languages.Current] ?? values?[Languages.Default] ?? new NullSafeList<T>();
}
/// <summary>
/// Get the string list translation.
/// </summary>
/// <param name="values">The dictionary containing lang>translations.</param>
static public string[] GetLang(this NullSafeDictionary<Language, string[]> values)
{
return values?[Languages.Current] ?? values?[Languages.Default] ?? new string[1] { ERR };
}
/// <summary>
/// Get the string translation.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <param name="values">The dictionary containing lang>value>translation.</param>
/// <param name="value">The value to translate.</param>
static public string GetLang<T>(this NullSafeDictionary<Language, NullSafeOfStringDictionary<T>> values, T value)
where T : Enum
{
return values?[Languages.Current]?[value] ?? values?[Languages.Default]?[value] ?? ERR;
}
/// <summary>
/// Remove diacritics signs.
/// </summary>
public static string RemoveDiacritics(this string str)
{
if ( str.IsNullOrEmpty() ) return str;
var normalized = str.Normalize(NormalizationForm.FormD);
var builder = new StringBuilder();
foreach ( var c in normalized )
if ( CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark )
builder.Append(c);
return builder.ToString().Normalize(NormalizationForm.FormC);
}
}
还有:
[Serializable]
public class NullSafeList<T> : List<T>
where T : class
{
public NullSafeList()
{
}
public NullSafeList(int capacity) : base(capacity)
{
}
public NullSafeList(IEnumerable<T> collection) : base(collection)
{
}
public new T this[int index]
{
get
{
CheckIndex(index);
return index < Count ? base[index] : null;
}
set
{
CheckIndex(index);
if ( index < Count )
base[index] = value;
else
CreateOutOfRange(index, value);
}
}
private void CheckIndex(int index)
{
if ( index >= 0 ) return;
throw new IndexOutOfRangeException(SysTranslations.IndexCantBeNegative.GetLang(nameof(NullSafeStringList), index));
}
private void CreateOutOfRange(int index, T value)
{
Capacity = index + 1;
int count = index + 1 - Count;
for ( int i = 0; i < count; i++ )
Add(null);
base[index] = value;
}
}
以及以下 class:
static class Languages
{
/// <summary>
/// Indicate language codes.
/// </summary>
static public readonly NullSafeOfEnumDictionary<string, Language> Values;
/// <summary>
/// Indicate language codes.
/// </summary>
static public readonly NullSafeOfStringDictionary<Language> Codes;
/// <summary>
/// Indicate managed languages.
/// </summary>
static public readonly Language[] Managed;
/// <summary>
/// Indicate default language.
/// </summary>
static public readonly Language Default = Language.EN;
/// <summary>
/// Indicate current language code.
/// </summary>
static public string CurrentCode => Codes[Current];
/// <summary>
/// Indicate current language.
/// </summary>
static public Language Current
{
get
{
string lang = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
var result = Values[lang];
if ( !Managed.Contains(result) ) result = Default;
return result;
}
}
/// <summary>
/// Static constructor.
/// </summary>
static Languages()
{
try
{
Managed = Enums.GetValues<Language>().Skip(1).ToArray();
Codes = new NullSafeOfStringDictionary<Language>(Managed.ToDictionary(v => v, v => v.ToString().ToLower()));
Values = new NullSafeOfEnumDictionary<string, Language>(Codes.ToDictionary(v => v.Value, v => v.Key));
}
catch ( Exception ex )
{
MessageBox.Show(ex.message);
}
}
}
您可以简化并删除不需要的所有内容。
[Serializable]
public class NullSafeOfEnumDictionary<TKey, TValue> : Dictionary<TKey, TValue>
where TValue : Enum
{
public NullSafeOfEnumDictionary()
{
}
public NullSafeOfEnumDictionary(int capacity) : base(capacity)
{
}
public NullSafeOfEnumDictionary(IEqualityComparer<TKey> comparer) : base(comparer)
{
}
public NullSafeOfEnumDictionary(IDictionary<TKey, TValue> dictionary) : base(dictionary)
{
}
public NullSafeOfEnumDictionary(int capacity, IEqualityComparer<TKey> comparer) : base(capacity, comparer)
{
}
public NullSafeOfEnumDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) : base(dictionary, comparer)
{
}
protected NullSafeOfEnumDictionary(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
public new TValue this[TKey key]
{
get
{
return ContainsKey(key) ? base[key] : default;
}
set
{
if ( ContainsKey(key) )
base[key] = value;
else
Add(key, value);
}
}
}
用法:
static class SysTranslations
{
static public readonly TranslationsDictionary NotImplemented
= new TranslationsDictionary
{
[Language.EN] = "Not implemented: {0}",
[Language.FR] = "Non implémenté : {0}",
};
}
string msg = SysTranslations.NotImplemented.GetLang("...");
Load/Write
static class NullSafeOfStringDictionaryHelper
{
static public bool LoadKeyValuePairs(this NullSafeOfStringDictionary<string> list,
string filePath,
string separator,
bool showError = true)
{
try
{
list.Clear();
foreach ( string line in File.ReadAllLines(filePath) )
if ( !line.StartsWith(";") && !line.StartsWith("//") )
{
var parts = line.SplitNoEmptyLines(separator);
if ( parts.Length == 1 )
list.Add(parts[0].Trim(), string.Empty);
else
if ( parts.Length == 2 )
list.Add(parts[0].Trim(), parts[1].Trim());
else
if ( parts.Length > 2 )
list.Add(parts[0].Trim(), string.Join(separator, parts.Skip(1)));
}
return true;
}
catch ( Exception ex )
{
if ( showError )
MessageBox.Show(SysTranslations.LoadFileError.GetLang(filePath, ex.Message),
Globals.AssemblyTitle,
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return false;
}
}
static public bool SaveKeyValuePairs(this NullSafeOfStringDictionary<string> list,
string filePath,
string separator,
bool showError = true)
{
using ( var stream = File.CreateText(filePath) )
try
{
foreach ( var item in list )
if ( !item.Key.StartsWith(";") && !item.Key.StartsWith("//") )
stream.WriteLine(item.Key + separator + item.Value);
else
stream.WriteLine(item.Key);
stream.Close();
return true;
}
catch ( Exception ex )
{
if ( showError )
MessageBox.Show(SysTranslations.LoadFileError.GetLang(filePath, ex.Message),
Globals.AssemblyTitle,
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return false;
}
}
}
最后这个比上面的更粗略。
使用此示例并使用 linq 来执行此操作:
class Program
{
public static List<Dictionary<string, Dictionary<string, string>>> translations = new List<Dictionary<string, Dictionary<string, string>>>();
public static Dictionary<string, Dictionary<string, string>> dic = new Dictionary<string, Dictionary<string, string>>();
static void Main(string[] args)
{
Dictionary<string,string> tDE = new Dictionary<string, string>();
Dictionary<string, string> tEN = new Dictionary<string, string>();
tEN.Add("label1", "english text");
tDE.Add("label1", "german text");
dic.Add("en", tEN);
dic.Add("de", tDE);
translations.Add(dic);
Console.WriteLine(getLocStr("de", "label1"));
Console.Read();
}
public static string getLocStr(string lang, string key)
{
string str = "";
foreach (var trans in translations)
{
var langDic = trans.FirstOrDefault(c => c.Key == lang);
if(langDic.Value!=null)
{
str = langDic.Value.FirstOrDefault(c => c.Key == key).Value;
}
// how to get a List<string,string> to retrieve the $value from by $key?
// eg: str = trans[$lang][$key]
}
return str;
}
}