Link to home
Start Free TrialLog in
Avatar of swgdesign
swgdesignFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Change Globalisation resource using session variable ?

I am currently developing an application that can be accessed via numerous domains name and in numerous languages (EN, DE, ES, FR, IT etc), so am using Globalisation for langaueg variations. The thing is due to branding and company names I need to use 1 base resource file for each domain name e.g.

Domain1.resx
Domain1.de-DE.resx
Domain2.resx
Domain2.de-DE.resx

and so on.

In the code below you can see I have set the resource to use Domain1.resx but if the users enter the site via domain2.com etc I need to use the resource Domain2.resx

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If InStr(Request.Url.AbsoluteUri, "domain1") Then
            Session("GlobStrings") = "Domain1"
        ElseIf InStr(Request.Url.AbsoluteUri, "domain2") Then
            Session("GlobStrings") = "Domain2"
        End If
    End Sub

    Protected Overrides Sub InitializeCulture()
        If Request.Form("DropDownList1") IsNot Nothing Then
            Dim selectedLanguage As String = Request.Form("DropDownList1")
            UICulture = Request.Form("DropDownList1")
            Culture = Request.Form("DropDownList1")
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(selectedLanguage)
            Thread.CurrentThread.CurrentUICulture = New CultureInfo(selectedLanguage)
        End If
        MyBase.InitializeCulture()
    End Sub



<asp:Label ID="Label1" runat="server" Text='<%$ Resources: Domain1, Home_Text1 %>'></asp:Label><br />
        <br />
        <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true">
            <asp:ListItem Value="en-GB">English</asp:ListItem>
            <asp:ListItem Value="de-DE">Deutsch</asp:ListItem>
            <asp:ListItem Value="es-ES">Espanol</asp:ListItem>
        </asp:DropDownList>

Open in new window


Is there a way to use the value of Session("GlobStrings") to get the correct resource strings?

OR

Can I use some sort of REPLACE on the string being returned by the resources call?

<asp:Label ID="Label1" runat="server" Text='<%$ Resources: Session("GlobStrings"), Home_Text1 %>'>

Open in new window


The above does not work!
Avatar of Rouchie
Rouchie
Flag of United Kingdom of Great Britain and Northern Ireland image

This is not a good approach because you need to assume that English UK users might access the German site.

Globalization automatically provides the correct language based on the user's computer settings (browser setting to be exact).  Therefore, you should check for that, and get ASP to do the rest.

In Global.asax you should have something like this to check for the existence of a cookie/session etc value that sets the page culture:

	Protected Sub Application_PreRequestHandlerExecute(ByVal sender As Object, ByVal e As System.EventArgs)
		If HttpContext.Current.Session("myValue") IsNot Nothing Then	' cookie exists
			Dim cc As String = HttpContext.Current.Session("myValue").Value
			If cc <> String.Empty Then ' user preference has been set, so use to create culture
				System.Threading.Thread.CurrentThread.CurrentUICulture = New System.Globalization.CultureInfo(cc)
				System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(cc)
			End If
		End If
	End Sub

Open in new window


Your application will then be smarter because it will detect language regardless of domain name.
Avatar of swgdesign

ASKER

Thanks for your input BUT our application is designed so users can select their language themselves, we do not want to base it on browser language specifically. :)
Yes, so you would store their choice in a Cookie or Session value (my example uses a Session).  Cookies are better because Sessions can be terminated easily, so replace

HttpContext.Current.Session(...

with

HttpContext.Current.Request.Cookies(...

So they visit the site, global.asax checks if they have a preference already, then loads the page in that preference automatically using my code.  This automatically works for every domain you are running.

If they have not got a preference, they get the site default language until they make a preference.  This is handled in your code to set the cookie value when the language choice is made.  The cookie value should be an ISO culture code, e.g. en-US or en-GB

I run a multi-lingual web app so have actually used this logic.
The dropdown in my code works, it switches between languages already, this is not the issue.

My issue is that the SAME set of aspx files are used for 2 domains with identical functionality; www.somecompany.com and www.othercompany.com. The English(starting language) website text for the 2 domains is slightly different and so I need 2 foundation resx files; somecompany.resx and othercompany.resx.

In my code above I have set the label as follows;
<asp:Label ID="Label1" runat="server" Text='<%$ Resources: SomeCompany, Home_Text1 %>'></asp:Label><br />

Open in new window


Which is fine if they happen to enter the website using www.somecompany.com, but what if they enter the website via www.othercompany.com? The label will show the wrong text because it is looking at the wrong resource file!

The label code should be as follows if they enter via www.othercompany.com;

<asp:Label ID="Label1" runat="server" Text='<%$ Resources: OtherCompany, Home_Text1 %>'></asp:Label><br />

Open in new window



My question is I guess; how do I switch the starting resource (SomeComapny / OtherCompany) used based on the domain the user enters through?
Could I cheat the system and use a globalisation value that I do not need such as 'Swahili'.

So, othercompany.resx would become somecompany.sw.resx?

Could your code be altered to check the domain name and then load either somecompany.resx or somecompany.sw.resx????
The RESX files you are referring to here are global resource files then, not local resource files?

In that case, I don't think you can do it all inline, but will have to use code-behind.  Something like this to store the RESX file name in Session (or cookies would also work):

Dim companyName As String = "OtherCompany"
Dim label1 As New Label
Session("companyName") = companyName

label1.Text = Me.GetGlobalResourceObject(Session("companyName"), "Home_Text1").ToString

Open in new window

Globalization is not designed to do what you are asking.  RESX files alone will, but using Globalization will only be a hack.  Instead, try the approach above.
Avatar of Easwaran Paramasivam
You can metion the language as Culture and UICulture in web.config file as given below

<globalization uiCulture="es" culture="es-MX" />

If you dont want to hardcode then update it programatically as you need. Please do refer the article http://www.dotnetcurry.com/ShowArticle.aspx?ID=102
Rouchie: As my question says this is about Globalisation, not localisation :)

So, the only I can do what I need to is to set a session to SomeCompany based on the value of the domain name(www.somecompany.com). Then use this session in the code behind to populate the labels I have passing in the session value as the resource file to look at.

The thing is what happens when my users change the language say to es-ES? Will the code still work as long as I have as SomeCompany.es-ES.resx global resource file?
Yes.Whatever you set in Current thread's Culture and UICulure it would take the value from respective resource file. Your first approach would work.
So which route should I take???

I need to is to set a session to SomeCompany based on the value of the domain name(www.somecompany.com). Then use this session in the code behind to populate the labels I have passing in the session value as the resource file to look at.

The thing is what happens when my users change the language say to es-ES? Will the code still work as long as I have as SomeCompany.es-ES.resx global resource file?


Could I cheat the system and use a globalisation value that I do not need such as 'Swahili' for the OtherCompany.com resource file. So, othercompany.resx would become somecompany.sw.resx?
>> The thing is what happens when my users change the language say to es-ES? Will the code still work as long as I have as SomeCompany.es-ES.resx global resource file?

This should work as you say, although I haven't tried it personally.

>> Could I cheat the system and use a globalisation value that I do not need such as 'Swahili' for the OtherCompany.com resource file. So, othercompany.resx would become somecompany.sw.resx?

I really would not try this idea.  This approach will no doubt cause a headache further down the line and you will have to 'undo' your work.  The first option is definitely best and works with the design of RESX files.
So I should use this methodthen?

I need to is to set a session to SomeCompany based on the value of the domain name(www.somecompany.com). Then use this session in the code behind to populate the labels I have passing in the session value as the resource file to look at.
In the global.ascx event Session_Start method could be used to set session based on the request URL.

Please do refer http://forums.asp.net/p/1139639/1830141.aspx and http://www.dotnetcurry.com/ShowArticle.aspx?ID=126 for more information.
>> In the global.ascx event Session_Start method could be used to set session based on the request URL.

Agreed!
So, I finally got round to trying to implement this at the weekend and some of it works some of it doesn't...

When I replace the literals in my Master Page it works perfectly and the string s are swapped depending on which domain name I test on.

Generic.Master
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        lblCopyrightYear.Text = Year(Now())
        Dim sURL As String = Request.Url.AbsoluteUri

        If InStr(sURL, "mrmc") Then
            Session("Store_Brand") = "mrmc"
        ElseIf InStr(sURL, "mtmc")  Then
            Session("Store_Brand") = "mtmc"
        End If

ltWebsiteTitle.Text = Me.GetGlobalResourceObject(Session("Store_Brand"), "WebTitle").ToString

End Sub

Open in new window


When I try and replace the literals in my default.aspx page I get the following errors occur, although I do not see why they work in my master page and not in a standard web form;

Default.aspx
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        ltBreadcrumbs_Home.Text = GetGlobalResourceObject(Session("Store_Brand"), "Breadcrumbs_Home").ToString
End Sub

<asp:Content ID="Content6" ContentPlaceHolderID="Breadcrumbs" Runat="Server">
    <ul>
        <li class="active"><asp:literal ID="ltBreadcrumbs_Home" runat="server"></asp:literal></li>
    </ul>
</asp:Content>

Open in new window


ERROR

Could not find any resources appropriate for the specified culture or the neutral culture.  Make sure "Resources..resources" was correctly embedded or linked into assembly "App_GlobalResources.s1xeyevf" at compile time, or that all the satellite assemblies required are loadable and fully signed.

Line 9:          ltBreadcrumbs_Home.Text = GetGlobalResourceObject(Session("Store_Brand"), "Breadcrumbs_Home").ToString
What are the names/locations of your web page/resource file?
My resource files are located in "App_GlobalResources" and my files are called;

mtmc.resx
mrmc.resx

Also, changing the language via the dropdown I spoke about earlier, updates the Session("Store_Brand") but the language strings do not update...I am guessing it is not updating the resource file to use?
For each language you should have seperate resouce files. Resource-Culture.resx is the format that you have to follow.
At the moment I have the following Resource files;

mrmc.resx
mtmc.resx
mtmc-de.resx
mtmc-es.resx

The foreign language resource files have nothing to do with the error I reported above as we are only switching between mrmc.resx and mtmc.resx by using the session variable. It also does not explain why the resource replacements work in a master page but not in my web forms...?
mtmc-de.resx should be mtmc.de.resx if you need to apply the DE language logic
I've created a test project that checks the value of a dropdownlist, saves that choice in Session then reads the appropriate global RESX file.  Is this close to what you need?
Test.zip
I understand this and it is named accordingly. Although this still doesn't have any relation to my issue of the resource working in my master page but not in a standard web form :(
I managed to recreate your error.  This is caused when you incorrectly refer to the resource file name (the actual RESX file).  Check the name you've used and it should find it okay.
Hi Rouchie,

I have something similar working perfectly with the 4 resource files I mentioned above and the 2 different domain names =) BUT I cannot get it working with my main web forms.

I just don't understand why Me.GetGlobalResourceObject works in my master page but NOT in my default.aspx page :(


Partial Class globalisation
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If InStr(Request.Url.AbsoluteUri, "mrmc") Then
            Session("Store_Brand") = "mrmc"
        ElseIf InStr(Request.Url.AbsoluteUri, "mtmc") Then
            Session("Store_Brand") = "mtmc"
        End If
        Label1.text = Me.GetGlobalResourceObject(Session("Store_Brand"), "Company").ToString
    End Sub

    Protected Overrides Sub InitializeCulture()
        If Request.Form("DropDownList1") IsNot Nothing Then
            Dim selectedLanguage As String = Request.Form("DropDownList1")
            UICulture = Request.Form("DropDownList1")
            Culture = Request.Form("DropDownList1")
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(selectedLanguage)
            Thread.CurrentThread.CurrentUICulture = New CultureInfo(selectedLanguage)
        End If
        MyBase.InitializeCulture()
    End Sub

End Class

Open in new window


<%@ Page Language="VB" AutoEventWireup="false" CodeFile="globalisation.aspx.vb" Inherits="globalisation" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server"></asp:Label><br />
        <br />
        <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true">
            <asp:ListItem Value="en-GB">English</asp:ListItem>
            <asp:ListItem Value="de-DE">Deutsch</asp:ListItem>
            <asp:ListItem Value="es-ES">Espanol</asp:ListItem>
        </asp:DropDownList>
        <%= Session("GlobStrings")%>
    </div>
    </form>
</body>
</html>

Open in new window

What is the value of Request.Form("DropDownList1") that is passed to UICulture when you debug a live page load?
Or more importantly, which line throws the error?
Rouchie: the code above works flawlessly no matter if I enter on domain1.com or domain2.com. I also have it working depending if they enter the website using a german or spanish domain extension (.de/.es) it changes the resource.file used accordingly.

I actually can't debug it as I am using a dll that won't allow me to, it will only work when I run the app on the internal domains I have setup for this site/app.

I can tell you the results of different domains and the resources loaded;

store.mrmc/                        mrmc.resx
store.mtmc                         mtmc.resx
de.store.mtmc                    mtmc.de-DE.rex
es.store.mtmc                    mtmc.es-ES.rex


I think I might have to drop my master page file(apparently because it is a class itself it can not contain my Protected Overrides Sub InitializeCulture) and set up some user controls to do what I require rather OR create an ineritable class for all my pages where I set the culture from the dropdownlist?
Why don't you use Global.asax as in my earlier example?
Because...

a) I do not quite understand how it is generally different from the code I have in my masterpage, which does not work properly, anyways. Can you please explain why it will work?

b) The code in my globalisation.aspx file works seamlessly without errors and so I should really try and use this somewhere.

Maybe I am missing the point?
Its really because global.asax is a more centralised location that will apply to your entire app.  So, if you ever create a new master page, all the logic will automatically be applied into it.
That I understand - thanks, but it doesn't help with the issue I have with the function below not being able to be used in a masterpage. It only seems to work

 Protected Overrides Sub InitializeCulture()
        If Request.Form("DropDownList1") IsNot Nothing Then
            Dim selectedLanguage As String = Request.Form("DropDownList1")
            UICulture = Request.Form("DropDownList1")
            Culture = Request.Form("DropDownList1")
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(selectedLanguage)
            Thread.CurrentThread.CurrentUICulture = New CultureInfo(selectedLanguage)
        End If
        MyBase.InitializeCulture()
    End Sub

Open in new window


If I place it in a usercontrol me.usercontrol.findcontrol doesn't work and doesn't pull back the dropdownlist value :(

I have never written an inherited class from scratch to apply to all pages ANd I don't see how it would work with my situation either

Losing hope :(
I thought I would upload my webform code incase anyone can offer a Master Page solution to my issue which is what I require...
workingglobalisation.zip
Working solution is attached.  The error was that you reference the Global resx file using only the file name "mtmc" and ASP.NET takes care of the rest.
BTW I moved your culture logic into global.asax as that's where it should really be anyway.  Stupid EE uploader won't allow global.asax files so I renamed it to global.txt
workingglobalisation.zip
Thanks for altering my code but it was working fine here, no mistakes or build errors; it changed the string correctly when the drop down was changed.

What I was asking for in my previous post was if anyone could complete the solution by actually getting it to work with the dropdownlist being in a master page and the label control being in a webform...

AFAIK; I think I need to use a base class that all my pages inherit from,the base class will contain the Sub InitializeCulture sub and in my master page will be the dropdownlist. The literal/label will be in the .aspx page.
Okay no problem .  Attached uses Master page to hold the drop down with list in child page.
No problems using Global.asax...! :-)
workingglobalisation.zip
Again, THANKS for your effort Rouchie, but it's not quite right, maybe I haven't explained everything well enough?

Session("MRMCStore_Brand") should NOT be changed when the drop down changes, it is only changed in relation to the contents of the actual domain name.

Locally on my development machine I am using the following local host headers for testing;

store.mtmc
de.store.mtmc
es.store.mtmc
store.mrmc

Session("MRMCStore_Brand") = 'mrmc' or 'mtmc' if the word appears (INSTR) in the domain name/host header.

The dropdown should only change the culture as per the selectedvalue.

I have attached a zip of the files I am using:

globalisation.aspx inherits from App_Code/BaseClass.vb WITHOUT a masterpage. This page WORKS perfectly - no code adjustments required!

globalisation2.aspx inherits from App_Code/BaseClass.vb and uses a master page (Globalisation.master) BUT it does not seem to be getting the dropdownlist value?

If it was getting the value my issue would be solved I feel...
MasterPageGlobalisation-20032012.zip
ASKER CERTIFIED SOLUTION
Avatar of Rouchie
Rouchie
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Further to the above, I didn't create a RESX file for the second domain so some don't change when you select particular cultures
Thanks Rouchie for all your help on this troubling issue, it is very much appreciated. I hope this solution helps out many more people with similar development projects! If you ever require help nwith anything on here, I hope I can be of some service! :)

I have 1 problem though! :(

I have updated your code (for now) to use querystrings, testing for "mrmc" and "mtmc" and I set Session("MRMCStore_brand") appropriately.

http://localhost:55275/globalisation/Default.aspx?site=mtmc
http://localhost:55275/globalisation/Default.aspx?site=mrmc

The only issue I am experiencing is that on first load of default.aspx it errors becaus of this line

Literal1.Text = Me.GetGlobalResourceObject(Session("MRMCStore_Brand"), "CompanyName").ToString

Open in new window


Until I change the line to read:

Literal1.Text = Me.GetGlobalResourceObject("mrmc", "CompanyName").ToString

Open in new window


If I then change the code back to using the session variable and reload the page it works fine. It's like it doesn't know the session exists or that it tries to load the resx string before the session is iniated and assigned a value. I have tired physically setting the session value to "mrmc" and "mtmc" in the masterpage, but it still errors on first load.

So, what I have done is added the following line to global.asax and it works but I am not sure if this is correct or not;

If Not Request.QueryString("site") Is Nothing Then
            HttpContext.Current.Session("MRMCStore_Brand") = Request.QueryString("site")
        End If

Open in new window

Your solution is exactly right.  Your identification of the problem is exactly what's happening.  Because the querystring won't exist on first load, there is no suitable Session value that is set, which in turn errors out when ASP.NET attempts to locate the RESX value.

Therefore, as you have done, on first load, check if the querystring exists.  This logic obviously won't apply if you use domain names to identify the site because the domain name always exists.
Great, thanks. I thought I was going down the right path, but sometimes you question your knowledge!

Again thanks for all your help Rouchie! =)

Points being awarded now!
Rouchie is one of the best EE members I have ever had the oppertunity to work with through an exhausting problem. Great help and patience!
Haha thanks for the compliments.  Best of luck with the rest of your project! :-)
Notice in the blog the code logic is in slighly different places.  As explained, depending on how your store the session values, Session itself is not always available, so sometimes cookies work better.  It's up to you though.