Texts in multi-language

Texts in multi-language using C#:


<?xml version="1.0" encoding="utf-8" ?>
<Test>
  <MSG Code="0">
    <en>Success.</en>
    <zh>成功.</zh>
  </MSG>
  <MSG Code="100001">
    <en>Some error.</en>
    <zh>錯誤.</zh>
  </MSG>
</Test>

 


public enum TestErrorCode
{
  [Description("Success")] Succ = 0,
  [Description("Some error")] SomeError = 100001
}

public enum TestLang
{
  [Description("english")] en = 0,
  [Description("中文")] zh = 1
}

public class LangSer
{
  public class Book
  {
    /// <summary>
    /// Dictionary<Error code, msg>
    /// </summary>
    public Dictionary<string, string> Errors { get; set; }
  }

  /// <summary>
  /// Dictionary<Language type, book>
  /// </summary>
  public Dictionary<string, Book> Books { get; set; }

  public bool HasData()
  {
    return Books != null && Books.Count > 0;
  }

  public bool TryGetText(TestErrorCode error, TestLang specLang, TestLang defaultLang, out string result)
  {
    result = string.Empty;

    //### Get by input language.
    string errorCode = ((int)error).ToString();
    string langText;
    if (TryGetText(errorCode, specLang, out langText))
    {
      result = langText;
      return true;
    }

    //### Get by default language.
    string defaultLangText;
    if (specLang != defaultLang
      && TryGetText(errorCode, defaultLang, out defaultLangText))
    {
      result = defaultLangText;
      return false;
    }

    //### Get error desc.
    result = Enums.GetEnumDesc(error);
    return false;
  }

  private bool TryGetText(string errorCode, TestLang lang, out string text)
  {
    text = string.Empty;

    Book langBook;
    string langType = lang.ToString();
    if (!TryGetValue(Books, langType, out langBook)
      || !TryGetValue(langBook.Errors, errorCode, out text))
    {
      return false;
    }

    return true;
  }

  private bool TryGetValue(Dictionary<string, Book> dict, string key, out Book val)
  {
    return dict.TryGetValue(key, out val) && val != null && val.Errors != null && val.Errors.Count > 0;
  }

  private bool TryGetValue(Dictionary<string, string> dict, string key, out string val)
  {
    return dict.TryGetValue(key, out val) && !string.IsNullOrWhiteSpace(val);
  }
}

public sealed class Test
{
  private readonly string _resPath = AppDomain.CurrentDomain.BaseDirectory + "Settings/TestError.xml";
  private readonly TestLang _defaultLang = TestLang.en;
  private readonly string _cacheKey = "TestError";
  private readonly Logger _logger = LogManager.GetLogger("TestLogger");
  private static readonly Lazy<Test> _instanceHolder = new Lazy<Test>(() => new Test());
  private LangSer _res = null;

  public static Test RES
  {
    get
    {
      return _instanceHolder.Value;
    }
  }

  public TestLang ParseLang(string langType)
  {
    if (!string.IsNullOrWhiteSpace(langType))
    {
      langType = langType.Trim();

      foreach (TestLang lang in (TestLang[])Enum.GetValues(typeof(TestLang)))
      {
        if (lang.ToString().Equals(langType, StringComparison.CurrentCultureIgnoreCase))
        {
          return lang;
        }
      }
    }

    LogInfo(string.Format("Fail to Parse TestLang. Input language:{0}", langType));

    return _defaultLang;
  }

  public string GetText(TestErrorCode error, TestLang lang)
  {
    //### Initialize cache data.
    string exMsg;
    if (!TryInitCache(out exMsg))
    {
      LogInfo(string.Format("Fail to Initialize Test cache data: {0} File path: {1} , CacheKey:{2}", exMsg, _resPath, _cacheKey));
      return Enums.GetEnumDesc(error);
    }

    //### Get Error text by Error code and Language type.
    string result;
    if (!_res.TryGetText(error, lang, _defaultLang, out result))
    {
      LogInfo(string.Format("Fail to Get Test message by ErrorCode {0} in {1} language. Result:{2}, Default language:{3}, File path: {4}", (int)error, lang.ToString(), result, _defaultLang.ToString(), _resPath));
    }

    return result;
  }

  private Test()
  {
  }

  private bool TryInitCache(out string exceptionMsg)
  {
    exceptionMsg = string.Empty;

    if (HttpRuntime.Cache[_cacheKey] == null)
    {
      try
      {
        HttpRuntime.Cache.Insert(
          _cacheKey,
          ReadResFile(),
          new CacheDependency(_resPath));

        _res = HttpRuntime.Cache[_cacheKey] as LangSer;

      }
      catch (Exception ex)
      {
        exceptionMsg = ex.Message;
        return false;
      }
    }

    return (_res != null && _res.HasData()) ? true : false;
  }

  private LangSer ReadResFile()
  {
    XmlDocument doc = new XmlDocument();

    try
    {
      doc.Load(_resPath);
    }
    catch
    {
      throw;
    }

    XmlNodeList msgList = doc.SelectNodes("/Test/MSG");
    if (msgList == null || msgList.Count == 0)
    {
      throw new Exception("<MSG> tag is void.");
    }

    LangSer res = new LangSer();
    res.Books = new Dictionary<string, LangSer.Book>();

    string[] langTypes = Enum.GetNames(typeof(TestLang));
    foreach (string lang in langTypes)
    {
      TryAdd(res.Books, lang, new LangSer.Book() { Errors = new Dictionary<string, string>() });
    }

    foreach (XmlNode msg in msgList)
    {
      //### Check MSG Code.
      XmlAttribute codeAttr = msg.Attributes["Code"];
      if (codeAttr == null
        || string.IsNullOrWhiteSpace(codeAttr.Value))
      {
        continue;
      }

      //### Check language types.
      string code = codeAttr.Value.Trim();
      foreach (string lang in langTypes)
      {
        XmlNode node = msg.SelectSingleNode(lang);
        if (node != null && !string.IsNullOrWhiteSpace(node.InnerText))
        {
          TryAdd(res.Books[lang].Errors, code, node.InnerText.Trim());
        }
      }
    }

    return res;
  }

  private void TryAdd<T, U>(Dictionary<T, U> dict, T key, U value)
  {
    U got;
    if (!dict.TryGetValue(key, out got))
    {   //If the key does not exist.
      dict.Add(key, value);
    }

    return;
  }

  private void LogInfo(string msg)
  {
    MethodBase method = MethodBase.GetCurrentMethod();
    _logger.Info(string.Format("[{0}][{1}] {2}", MethodBase.GetCurrentMethod().ReflectedType.FullName, MethodBase.GetCurrentMethod().Name, msg));
  }
}

 

 

Send mail using C#

Send mail using C#:


using System.Net.Mail;


public class MailInfo
{
  public MailInfo()
  {
    IsBodyHtml = true;
    Port = 25;
    Timeout = 3000;
  }

  public string MailHost { get; set; }
  public string Subject { get; set; }
  public string Body { get; set; }
  public string From { get; set; }
  public List<string> To { get; set; }
  public List<string> CC { get; set; }
  public List<string> BCC { get; set; }
  public bool IsBodyHtml { get; set; }
  public int Port { get; set; }
  public int Timeout { get; set; }
}

public class Mail
{
  /// <summary>
  /// Default logger
  /// </summary>
  private static readonly Logger _defaultLogger = LogManager.GetLogger("MailLogger");

  /// <summary>
  /// Send mail sync
  /// </summary>
  public static void Send(MailInfo mail, Logger logger = null)
  {
    if (mail == null)
    {
      Log(MethodBase.GetCurrentMethod(), "Mail info is void.", string.Empty, mail, logger);
      return;
    }

    if (string.IsNullOrWhiteSpace(mail.MailHost))
    {
      Log(MethodBase.GetCurrentMethod(), "Mail host is void.", string.Empty, mail, logger);
      return;
    }

    if (string.IsNullOrWhiteSpace(mail.From))
    {
      Log(MethodBase.GetCurrentMethod(), "Sender is void.", string.Empty, mail, logger);
      return;
    }

    if (mail.To == null || mail.To.Count == 0)
    {
      Log(MethodBase.GetCurrentMethod(), "Recipient is void.", string.Empty, mail, logger);
      return;
    }

    MailMessage msg = new MailMessage(mail.From, mail.To[0]);
    msg.Subject = mail.Subject;
    msg.Body = mail.Body;
    msg.IsBodyHtml = mail.IsBodyHtml;
    mail.To.ForEach(addr => msg.To.Add(addr));

    if (mail.CC != null && mail.CC.Count > 0)
    {
      mail.CC.ForEach(addr => msg.CC.Add(addr));
    }

    if (mail.BCC != null && mail.BCC.Count > 0)
    {
      mail.BCC.ForEach(addr => msg.Bcc.Add(addr));
    }

    try
    {
      using (SmtpClient client = new SmtpClient(mail.MailHost, mail.Port))
      {
        client.Timeout = mail.Timeout;
        client.Send(msg);
      }
    }
    catch (Exception ex)
    {
      Log(MethodBase.GetCurrentMethod(), ex.Message, ex.StackTrace, mail, logger);
    }
  }

  /// <summary>
  /// Send mail async
  /// </summary>
  public static void SendAsync(MailInfo mail, Logger logger = null)
  {
    Task.Run(() =>
      {
        try
        {
          Mail.Send(mail, logger);
        }
        catch (Exception ex)
        {
          Log(MethodBase.GetCurrentMethod(), ex.Message, ex.StackTrace, mail, logger);
        }
      }
    );
  }

  /// <summary>
  /// Log error
  /// </summary>
  private static void Log(MethodBase currentMethod, string errorMsg, string stackTrace, MailInfo mail, Logger logger = null)
  {
    if (logger == null)
    {
      logger = _defaultLogger;
    }

    logger.Error(string.Format(
      "[{0}].[{1}] Fail to send mail. {2} - {3}"
      + "; MailHost: {4}, Port: {5}, From: {6}, To: {7}"
      + ", CC: {8}, BCC: {9}, Timeout: {10}, Subject: {11}"
      + ", IsBodyHtml: {12}, Body:{13}",
      currentMethod.ReflectedType.FullName, currentMethod.Name, errorMsg, stackTrace
      , mail.MailHost, mail.Port, mail.From, JsonConvert.SerializeObject(mail.To)
      , JsonConvert.SerializeObject(mail.CC), JsonConvert.SerializeObject(mail.BCC), mail.Timeout, mail.Subject
      , mail.IsBodyHtml ? "True" : "False", mail.Body));
  }
}