4
\$\begingroup\$

I created a multilingual site in MVC and I reached the current results, but I'm not sure it's the right way.

I have created a class named changeLanguage to change the language:

public ActionResult ChangeLanguage(String LanguageAbbrevation)
        {
            if (LanguageAbbrevation != null)
            {
                Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(LanguageAbbrevation);
                Thread.CurrentThread.CurrentUICulture = new CultureInfo(LanguageAbbrevation);

            }
            HttpCookie cookie = new HttpCookie("Language");
            cookie.Value = LanguageAbbrevation;
            Response.Cookies.Add(cookie);
            return RedirectToAction("Index","Home");

        }

Global.asax:

 protected void Application_BeginRequest(object sender, EventArgs e)
        {
            LanguageTB context = new LanguageTB();
            HttpCookie cookie = HttpContext.Current.Request.Cookies["Language"];
            if (cookie != null && cookie.Value != null)
            {
                System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cookie.Value);
                System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(cookie.Value);

            }

            else
            {
                System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en");
                System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en");

            }
        }

Controller:

 public ActionResult AboutUs()
 {
        HttpCookie cookie = HttpContext.Request.Cookies["Language"];
        var categoryList = context.SiteContents.Where(x => x.LanguageTB.CultureCode==cookie.Value)).ToList();
        return View(categoryList);
    }

I'm doing this again and again for every view:

 public ActionResult AllAttorney()
{
    HttpCookie cookie = HttpContext.Request.Cookies["Language"];
    var employeelist = context.Employees.Where(x => x.LanguageTB.CultureCode== mainLanguage.lb).ToList();
    return View(employeelist);
}

View:

<ul class="list-unstyled list-inline">
   <li> <a href="@Url.Action("ChangeLanguage","Language",new { LanguageAbbrevation = "en" })">en</a></li>
   <li> <a href="@Url.Action("ChangeLanguage","Language",new { LanguageAbbrevation = "az" })">az</a></li>
   <li> <a href="@Url.Action("ChangeLanguage","Language",new { LanguageAbbrevation = "ru" })">ru</a></li>                                 
       <li class="nav-item">
         <a href="@Url.Action("AllAttorney", "Home")">@RHome.MAttorney</a>
       </li>
       <li class="nav-item">
         <a href="@Url.Action("AboutUs", "Home")">@RHome.MAboutUs</a>                               
      </li>
       <li class="nav-item">
         <a href="@Url.Action("caseResult", "Home")">@RHome.MNews</a>                                            
      </li>
 </ul>

Language table:

  [Table("LanguageTB")]
public partial class LanguageTB
{
    public LanguageTB()
    {
        Articles = new HashSet<Article>();
        Employees = new HashSet<Employee>();
        SiteContents = new HashSet<SiteContent>();
    }

    [Key]
    public int LanguageId { get; set; }

    [StringLength(50)]
    public string CultureCode { get; set; }

    [StringLength(100)]
    public string CultureName { get; set; }

    public virtual ICollection<Article> Articles { get; set; }
    public virtual ICollection<Employee> Employees { get; set; }
    public virtual ICollection<SiteContent> SiteContents { get; set; }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ I need to ask you to undo/rollback the edit. It is not allowed now that you have received an answer.... otherwise me or someone else will need to do it :-] \$\endgroup\$ – t3chb0t Dec 10 '17 at 11:52
  • 1
    \$\begingroup\$ What should I do when someone answers my question?: Do not change the code in the question after receiving an answer. Incorporating advice from an answer into the question violates the question-and-answer nature of this site. \$\endgroup\$ – t3chb0t Dec 10 '17 at 11:53
  • 1
    \$\begingroup\$ I'm sorry I don't know that.I got it back. . \$\endgroup\$ – user9074708 Dec 10 '17 at 12:22
5
\$\begingroup\$

Too many Language Repetitions

You use the "Language" key a lot. What if you decide to rename it sometime? You'll need to search everywhere for this string. It'd be better if you encapsulated it or used a constant. I prefer extensions so it might look like this where you try to get the cookie and if it is not null ? then you get the value.

public static class HttpCookieCollectionExtensions
{
    public static string Language(this HttpCookieCollection cookies)
    {
        return cookies["Language"]?.Value
    }
}

Later in your application you can reuse it everywhere which would result in a nice short and clear code ba also getting rid of this ugly condition:

 if (cookie != null && cookie.Value != null) 

Bug 1

else
{
    System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en");
    System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en");

}

There is a bug in this else. Both lines are the same. Did you copy/paste them?


Setting culture

Another case for encapsulation are the four lines where you set the culture. Just write a new method and put two of them there:

public static void SetCulture(string name)
{
    System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(name);
    System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(name);
}

Default culture

Later you should also add a constant for the default cutlure

const string DefaultCulture = "en";

New event handler

Now put everything together and be happy with this pretty nice two-liner event handler:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    var language = HttpContext.Current.Request.Cookies.Language() ?? DefaultCulture;
    SetCulture(language);
}

Object initializer

You can also shorten the ChangeLanguage method by using an object initializer. This means that you replace this three lines

HttpCookie cookie = new HttpCookie("Language");
cookie.Value = LanguageAbbrevation;
Response.Cookies.Add(cookie);

with simply this

Response.Cookies.Add(new HttpCookie("Language")
{
    Value = LanguageAbbrevation
});

Bug 2

There is one more bug in your application. When you check for the LanguageAbbrevation here you don't set it to any default value if it's null. Consequently setting the cookie to nothing. Why don't you use en here or skip setting the cookie by putting it inside the if?

public ActionResult ChangeLanguage(String LanguageAbbrevation)
{
  if (LanguageAbbrevation != null)
  {
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(LanguageAbbrevation);
      Thread.CurrentThread.CurrentUICulture = new CultureInfo(LanguageAbbrevation);

  }
  Response.Cookies.Add(new HttpCookie("Language")
  {
      Value = LanguageAbbrevation
  });
  return RedirectToAction("Index", "Home");

}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.