user1973285
user1973285

Reputation:

Multilanguage MVC 4 application

I am creating a new application right now and I want to make all right at the start so I can grow with it in the future.

I have looked on several guides descibing how to make a multilanguage supported application, but I can't figure out witch one to use.

Some tutorials are old and I don't know if they are out of date.

http://www.codeproject.com/Articles/352583/Localization-in-ASP-NET-MVC-with-Griffin-MvcContri http://geekswithblogs.net/shaunxu/archive/2012/09/04/localization-in-asp.net-mvc-ndash-upgraded.aspx http://www.hanselman.com/blog/GlobalizationInternationalizationAndLocalizationInASPNETMVC3JavaScriptAndJQueryPart1.aspx http://www.chambaud.com/2013/02/27/localization-in-asp-net-mvc-4/ https://github.com/turquoiseowl/i18n

I found that they are 2 ways of storing the language data, either in db or in resource files. What are the pro/cons? Is there another way that is prefered?

This is what I want:

  1. Easy to maintain (Add/Change/Remove)
  2. Full language support. (views, currency, time/date, jquery, annotations and so on..)
  3. Enable to change language.
  4. Auto detect language.
  5. Future safe.

What is the prefered way of doing this? got any good tutorial that is best practice for 2013?

Upvotes: 17

Views: 17490

Answers (4)

Dominic St-Pierre
Dominic St-Pierre

Reputation: 2469

I've written a blog post convering the following aspect of a multilingual asp.net mvc app:

Database: I split table in two parts, one containing non-translatable fields the other containing the fields that need translation.

Url Routes: I normally keep the culture in the URL that way you get a well indexed ML site.

routes.MapRoute(
  name: "ML",
  url: "{lang}/{controller}/{action}/{id}",
  defaults: new { lang = "en-CA", controller = "Home", action = "Index", id = UrlParameter.Optional }
);

From a base controller class you can make that {lang} parameters available to your Controller. See the blog post for all details.

Querying your data: You would simply pass the Culture to your repository or database context. The idea is to create a view model that merge the two table that you separated for translation.

public ActionResult Index(string id)
{
    var vm = pages.Get(id, Language); // Language is the {lang} from the route
    return View(vm);
}

Your Views: Use the .NET Resources file with the generic two-letter language code, ex: HomePage.en.resx, HomePage.fr.resx. The locale en**-US**, en**-CA** is useful for formatting currency, dates, numbers etc. Your Resources file will mostly likely be the same for English US, Canada, etc.

Images: Use a format like imagename-en.png, imagename-fr.png. From your Views make the {lang} route parameter available via an extension method and display your images like this:

<img src="/content/logos/[email protected]()" />

You may also have a complete separate folder for your language supported. Example: /content/en/imagename.png, /content/fr/imagename.png.

JavaScript:: I usually create a folder name LanguagePacks and JS files called Lang-en.js, Lang-fr.js. The idea is to create "static" class that you can use all over your other JS files:

// lang-en.js
var Lang = {
  globalDateFormat = 'mm-dd-yy';
  greeting: 'Hello'  
};

On your Views, you load the correct Language file

<script type="text/javascript" src="/content/js/languagepacks/lang-@(this.CurrentLanguage()).js"></script>

From a JavaScript module

// UI Module
var UI = function() {

  function notify() {
    alert(Lang.greeting);
  }
  return {
    notify: notify
  }
};

There's no one way to do a multilingual web app. Use the Resources to translate your text, they can be quickly swap at run-time. You have multiple editor that can open those that you can pass to translator etc.

You can check the blog post and get a detailed example on how I do this.

Upvotes: 13

Idra
Idra

Reputation: 5807

I kinda have a feeling that this question does not have a straight forward answer. For formatting and what not you should always be using the Culture and the UICulture i.e. stuff like 'en-GB' for British English and 'en-US' for US English (and yes, there is a difference). All of .Net is built around it and that way you can use local formatting without really thinking about it.

You should also check out the System.Globalization namespace for more details: http://msdn.microsoft.com/en-us/library/system.globalization%28v=vs.110%29.aspx

As for were the culture should come from, then at least in our company the policy has always without exception from the query string. The reason for that is that if you use IP localization for example, then if a Spanish user is looking at a Spanish site in Japan and then would be switched to the Japanese version, then not exactly wrong but can be annoying if you've told the client that it's a direct Spanish link or something. That said if the culture is undefined in the query string, then using the IP to get guess with language the user would like to have, would not be a bad idea, but really depends on your clients needs.

As for were to get the translations, then it really depends, both resource and DB have their ups and downs. So the major up-points for DB are that, its easy to share between applications and if you need to update a phrase for any reason, then you can update them all through one DB entry, but this can be a fault as well, because some phrases have dual meanings and can be translated completely differently in other languages although the same sentence is used in English. The other big problem with DB is that to a degree (but this depends on implementation) you loose intelligence in VS for the phrases.

Resources of course have proper intelligence, but they are fairly static to that web application you are using, you can't share resources across applications... well not exactly true, but more or less you can't. Though that static nature is also a plus, because all of the resources are contained within the application and you know that no outside effect can influence it.

In reality it really depends on the project in hand. you simply have to way your own pros and cons and decide for your self... sorry. But if it helps at all, I can tell you how things are in my company. We make several applications, that share the same phrases all across various web applications. We used to have it in DBs, but what happened was that the translations kept going array, meaning a client asked for a better translation in Spanish for one app, but that made no sense what so ever on others. That happened more than you might think. Then we moved to the resources, but what happened there was that when one app's translation was updated, then no-one remembered to update the other apps and it actually happened that 3 different apps translated the same term in 3 different ways. In the end we decided to go back to the DB, because the ability to change all of the translations at once meant more to us, then the fact no outside influence could effect it.

In general there are other pros and cons as well, but all that is fairly irrelevant compared to the above. You really need to ask how you are using the translations. As for general editing (excluding the above point), then aider approach works just as well, you can just as easily change and edit or extend translations with both approaches.

That said, if the DB and the DB calls are designed badly, then adding new languages can be easier with resources, simply copy the resource file, add the culture extension to the name and add the translations to the resource and you are done, but again, completely down to the DB design, so that is something to keep in mind when designing the DB and says fairly nothing about holding the translations in the DB.

By in large I would say that the resources are easier to use and very easy to maintain and extend (and they are already built into .NET) though DB has a clear advantage if you need to share translations. So if I would have to say I would say the recommended way is to use Resources, but DB does have it's place and it really depends on the project.

Upvotes: 1

M&#229;rten
M&#229;rten

Reputation: 349

I've been looking at the same sources as you for the same needs but as you say it is very hard to find one preferred solution.

But I decided to go with the solution by Michael Chambaud that you have linked in your question. Reasons for this was that it was easy to implement, gave me the url's I wanted and since I'm still not 100% certain... easy to replace in the future.

In additon to this I will use jquery globalize for client side formatting.

It would be really interesting to hear what solution you decided on?

Upvotes: 0

Amin Saqi
Amin Saqi

Reputation: 18977

I have an approach for myself based on db, however it may not be suitable for large scale apps.

I create a Translation table/entity for holding titles and texts which should be multilingual.

So, whenever I want to render a view, first I retrieve the appropriate translation from db and then pass it to the view as model:

var t = dbCtx.Translations.Find(langID);
// ...
return View(t);

And in view, I render the content like the following:

<tr>
    <td>@Html.DisplayFor(m => m.WelcomeMessage)</td>
    <td>@Url.Action(Model.EnterSite, "Index", "Home")</td>
</tr>

And about getting the appropriate answer, well you have several ways. You can use session:

Session["Lang"] = "en";
// ...
var lang = (string)Session["Lang"] ?? "en";

Or by passing it through query string, or combination of them.

For auto detecting language, you should decide of the following:

a) Detecting from the browser

b) Detecting from user IP and guessing geo location of him/her and setting the appropriate language for him/her

Upvotes: 1

Related Questions