tags:

views:

384

answers:

2

Hi, I have my target language in Session["lang"], which is either "en" or "it". I have added this to the Site.master:

<script runat="server">
  void Page_Load(object sender, EventArgs e) {
    string lang = Session["lang"].ToString();
    System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(lang);
    System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.CreateSpecificCulture(lang);
  }
</script>

Then I'd like to invoke a resource string like this:

<asp:Label ID="Label1" runat="server" Text="<%$ Resources:Global, test %>"></asp:Label>

I have two files in the App_GlobalResources, named Global.resx and Global.en.resx.

The problems is that no matter what is in the lang variable, I always get the results from the main Global.resx, and I never get the english version from Global.en.resx

I am doing this wrong entirely??

I tried putting the System.Threading... part in the Application_PreRequestHandlerExecute method in Global.asax.cs but the result was the same.

Thanks

PS: I am asking about a way to make this work in a simple way. If I was to use the complicate way, I'd go with this: http://helios.ca/2009/05/27/aspnet-mvc-and-localization/

+2  A: 

I bet this one is a duplicate.
Anyway - all you need is here (assuming that you are using webforms viewengine (might work with others too, haven't investigated)).

Oh well... here goes my 'summary':

Helpers are just a part. You need to do some modifications with your default view engine too . On createview/createpartialview it should return localizationwebformview which adds a path key to viewdata which is used by htmlhelper to find resourceexpressionsfields and pass them to localizationhelpers class which retrieves desired value.

Little bonus=>

This might be handy if you don't want to recreate resource folders for view subfolders
(in case you modify viewengine.view/partialviewlocationformats):

 private static string ReformatVirtualPath(string virtualPath)
        {
            //This allows NOT to duplicate App_localResources directory
            // ~/Views/Shared/Partial/Some/BulltihS/_View.ascx
            // turns into =>
            // ~/Views/Shared/_View.ascx
            var start = @"(~(/?\w*/?){2})";
            var end = @"(\w*.as(c|p)x)";

            start = Regex.Match(virtualPath, start).Value;
            end = Regex.Match(virtualPath, end).Value;

            return start + end;
        }

usage:

 internal static ResourceExpressionFields GetResourceFields
            (string expression, string virtualPath)
        {
            virtualPath = ReformatVirtualPath(virtualPath);

            var context = new ExpressionBuilderContext(virtualPath);
            var builder = new ResourceExpressionBuilder();
            return (ResourceExpressionFields)
                   builder.ParseExpression(expression, typeof(string), context);
        }

EDIT:
but it might be a good idea to avoid App_GlobalResources and App_LocalResources as K. Scott Allen suggests (check Konstantinos answer).

Arnis L.
I would upvote this if you included a summary of the information on the site.
tvanfosson
Tried that already, it is linked everywhere, but it does not tell the entire story. It just provides helpers to get things out from resources file. I have a bug in my setup, and therefore that approach would not work anyway (check the first two paragraphs, the <asp:Label> call should work anyway, then the article is about moving away from that syntax to make thinks more MVC style).
Palantir
This is a link to zip with source code you should investigate => http://www.eworldui.net/files/LocalizationHelpers.zip
Arnis L.
+2  A: 

i had the same dilema(how to implement localization) in my asp.net mvc app.

I followed the instructions posted here and it works like a charm.

So i created a folder named Localization under Content and then i create Resources resx files for each language i want to translate. Keep in mind that there is a convention for the resx file names. ie

Resources.resx is the default fall back for everything.

Resources.en-GB.resx is for english GB

Resources.en-US.resx is for english US

etc.

Just make sure you follow the instructions posted in the link to embed and make the Resources available in all places in your app (views, controllers etc)

Edit:

I want to add that i ommited this line from web.config since i wanted to manually set the local from my app.

<globalization uiCulture="auto" culture="auto"/>

Instead i have created the following class:

    public class SmartController : Controller
{
    public SmartController()
    {
        System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
        System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
    }
}

All controllers inherit from this class.

Since this is an administrative set of the locale i have to set it from my apps settings. You could read it from Cookies and set it, or otherwise. This is imo the simplest solution for localization that i have encountered so far.

Once implemented you can refer to any string you add by the following simple line of code, no extra code needed.

<%= Resources.Strings.TranslatedTerm %>
Konstantinos
Not helpful either, sorry: all it says is that "If you need to set the culture up according to a user’s preference, or a URL parameter, then the best bet is to write a custom HTTP module or action filter".Maybe then there is no way to do it this way?
Palantir
of course there is a way to set the culture.. if it's user preference by YOUR site then you store it in a cookie and you create a controller that when instantiated ( constructor ) you read the cookie and set the CultureUI/Culture. Then all your controllers should inhereit from that controller.
Konstantinos
by the time you read your locale and want to set it you do it like that: System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US"); System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Konstantinos
Follow the instructions posted on the link i posted and here. otherwise it won't work.
Konstantinos
Good, I got it to work thanks to your code :) I added the SmartController, took out the resources from the App_GlobalResources folder up to the base folder and changed their properties according to the article, finally changed en to en-US... that was a long trip!
Palantir
A typo in your code: it should be en-GB for UK english, not en-UK
Palantir
well, glad it was helpful :)
Konstantinos
editing the typo thx Palantir
Konstantinos
A note about this: if the information about language is kept in the Session object, then this will not work, as the Session object is always null in Controllers constructors. The solution is to do create the SmartController as above, but instead of using the constructor you should override OnActionExecuting, where the Session is available.
Palantir