You need to take a completely different approach, one that is more flexible. This is high-level sample code but should give you an idea what you need to do. Rather than getting all possible language versions in your news object you should just get a news object that has the language the site is currently configured for. You can only show one language at a time so why get all the language content back? Also your way makes it harder to add or remove languages from your solution.
So there are two things here...handling what the current language is, and then handling how to get the news in that language. By separating the two it means you can re-use your language selection elsewhere, it's not tightly coupled to your news code.
I'm going to use one view for everything which is done for simplicity. So
/Index
will show "Article not found", but
/Index/1
will show news item 1 in the chosen language
We'll do the language handling first, and that will be stored in a cookie as it's the best solution for a website. So we'll define a service interface that satisfies our language selection and a concrete interface that implements it using cookies.
public interface ILanguageService
{
string GetLanguage();
void SetLanguage(string lang);
}
public class CookieLanguageService : ILanguageService
{
public string GetLanguage()
{
HttpCookie c = System.Web.HttpContext.Current.Request.Cookies["lang"];
string lang = c == null ? string.Empty : System.Web.HttpContext.Current.Request.Cookies["lang"].Value;
if (string.IsNullOrWhiteSpace(lang))
{
lang = "en-GB";
}
return lang;
}
public void SetLanguage(string lang)
{
HttpCookie c = new HttpCookie("lang", lang);
c.Expires = DateTime.Now.AddYears(1);
System.Web.HttpContext.Current.Response.Cookies.Add(c);
}
}
This kind of architecture means if you want to store your language elsewhere you can implement an ILanguageService for your given storage medium (eg you might want to use the Session, you might want to drive it from the settings of the logged-in user etc).
The model is like this (I'm only handling the Title, you'll need to add properties for the LongDescription, ID etc)
public class News
{
public string Title { get; set; }
}
Our controller is going to look like
public class HomeController : Controller
{
private ILanguageService languageService;
public HomeController()
: this(new CookieLanguageService())
{
}
public HomeController(ILanguageService languageService)
{
this.languageService = languageService;
}
[HttpGet]
public ActionResult Index(int? id)
{
News m = new News();
return View(m);
}
public ActionResult SetLanguage(string lang)
{
this.languageService.SetLanguage(lang);
return RedirectToAction("Index");
}
}
The view - here I am using links to select the language, you'll probably want to use a dropdown or something
@model MyProject.Models.News
<div>
@Html.ActionLink("English", "SetLanguage", "Home", new { lang = "en-GB" }, null) |
@Html.ActionLink("French", "SetLanguage", "Home", new { lang = "fr-FR" }, null)
</div>
<div>
<h1>@Model.Title</h1>
</div>
That handles the language selection. Now we need a news service that will get a given news article from your database based on the id of the article and the currently selected language. So the service definition
public interface INewsService
{
News GetNews(int id);
}
For the implementation I'm doing some hard-coding of the news title, you'll obviously get this from your database.
public class NewsService : INewsService
{
private ILanguageService languageService;
public NewsService(ILanguageService languageService)
{
this.languageService = languageService;
}
public News GetNews(int id)
{
string lang = this.languageService.GetLanguage();
News news = new News();
news.Title = string.Format("Article {0} in {1}", id.ToString(), lang);
return news;
}
}
Now we have implemented our language selection and our news service we can flesh out our controller action;
[HttpGet]
public ActionResult Index(int? id)
{
News m;
if (id.HasValue)
{
INewsService ns = new NewsService(this.languageService);
m = ns.GetNews(id.Value);
}
else
{
m = new News();
m.Title = "Article not found";
}
return View(m);
}
I have written the code such that it works as-is, but in a way that you normally leverage dependency injection for. I've added comments to show where DI will make the code a little simpler, if you're not using DI then I'd advise you look into it (it's a whole new topic on its own).
I'm using the language code to define language, but if your system uses ids or some other mechanism then change as necessary. As you can see, any service you then write can also use the injection of the given ILanguageService so that it can work out the current language.