如何使用 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;
    }

}