Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

This is a place to discuss how to adapt mojoPortal to the needs of different cultures. Before asking questions here please first review the localization documentation.

This thread is closed to new posts. You must sign in to post in the forums.
1/4/2010 12:47:30 AM
Gravatar
Total Posts 31
There are 10 kinds of people in the world, those who know binary, and those who don't

Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

This question is half translation-related and half-developer related but I am posting it on Localization anyway.

I am aware of the following:
1. Resource files can be used to translate code (which is very necessary since we are using multiple custom-built modules developed in-house)
2. Multi-sites can be used to translate data of module instances (e.g. the HTML content differs so we can read and modify different content)

This is all well and useful. But the provision of translation (culture) switching is exclusively controlled either by two settings:

1. By the default culture setting for all sites, e.g. the globalization tag in web.config -- http://lucasnovae.blogspot.com/2009/03/tutorial-multilingual-mojoportal.html
2. By overrides for a specific site, e.g. site X uses culture Y -- http://www.mojoportal.com/localization.aspx

These features all depend on users having to set their default culture in the browser.
http://www.mojoportal.com/settingbrowserlanguagepreferences.aspx

Although this is "quite" conventional and one can argue it is a standard browser feature, there are some problems:
1. Some users may not have permissions to modify IE/browser settings (due to security policies)
2. Some browsers may be stripped down (e.g. web kiosks)
3. Most users do not dare to change configuration settings (they are not experts or the computer is not theirs)
4. Most users do not know what "browser configuration" is (this is a big one)

There is in fact another convention established which is far more accepted and used globally: on the web site, there are entry links for each languages, and there are language links on every page to switch language. Then, the language will be remembered for this user. And even better, specific users can be greeted in their own language when they return once they have created their own profile. In Hong Kong, for example, it is very conventional for official sites to have cross-links links to three languages: English, Traditional Chinese and Simplified Chinese. That can be done with multiple sites. But as soon as users can create profiles, the system will not remember the culture and they have to click again.

Since we do not want to depend on users having to set some specific bookmark (to adhere to multi-site) or user persistent cookies (there are privacy concerns), the server should be expected to remember and handle everything -- once the users have sign in. Thus, every user profile should remember their culture setting after login, and then redirect to the correct site.

So, what I would like to do is, to first create a custom profile property, which is the culture:
http://www.mojoportal.com/userprofileconfiguration.aspx

Then, I need to somehow hook up to, at least the sign-in event, but also any event that changes the profile (e.g. reconfig) and then override the culture of the current thread automatically so that it uses the profile. Or alternatively, at every single page load, the system must check whether the user has a culture setting (perhaps it can be cached) and then override the thread's culture setting.
(User profile customization reference: http://www.mojoportal.com/userprofileconfiguration.aspx)

Thus,
1. If a user has a custom culture defined, it is used as the first preference
2. If a user does not have a custom profile, it defaults to the culture of the site
3. If the site does not have a profile, it uses the web application's setting

Level 2 and 3 exist but level 1 is missing.

Seems there is no extension point in the system. Would you suggest a custom hack/patch of checking for a custom property in the user profile at page load? This is my first thought, it seems to fit quite properly into the architecture but could also be a nice general feature.

1/4/2010 6:30:11 AM
Gravatar
Total Posts 18439

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

These features all depend on users having to set their default culture in the browser.
http://www.mojoportal.com/settingbrowserlanguagepreferences.aspx

That is not correct. When you configure a site to force a specific culture it no longer has any dependency on the user browser settings. It uses the forced culture settings for all requests.

If you don't configure a specific culture for the site, only then does it use the default behavior where browser settings of the user determine the culture used.

Hope it helps,

Joe

1/4/2010 7:31:22 PM
Gravatar
Total Posts 31
There are 10 kinds of people in the world, those who know binary, and those who don't

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

Ok, agree. My question is: how to force a language/culture based on a user's custom profile setting (the MojoPortal profile)?

1/5/2010 1:43:31 PM
Gravatar
Total Posts 18439

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

It is not currently implemented to support users manually choosing the culture which the executing thread runs as. To me that would seem a strange use case.

When not forcing a specific culture the default behaviour is to use the language preference detected from the browser. However, this is really not much benefit, only labels and buttons get translated, not site content. If it does adjust automatically to the browser I think it is nice and the user will notice it that the site tried a little to accommodate them, but if you give the user a language dropdown and they choose manually a language and the only thing that changes is the buttons and labels they will be disappointed. To me it makes no sense to present the user a language dropdown unless its taking them to language specific content.

You could implement a custom solution with a custom http module you could plugin via web.config you could check a custom profile property for authenticated users and set the culture of the executing thread accordingly and this would make it use the resource files for the executing culture. 

Best,

Joe

1/6/2010 8:59:31 PM
Gravatar
Total Posts 31
There are 10 kinds of people in the world, those who know binary, and those who don't

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

Sorry but I politely wish to disagree. Please be aware that I am looking on this problem from a developer perspective. It is easy to tell end users with no development skills to create multiple sites and type a lot of text, but as a developer I hate to repeat myself in terms of re-specifying the same layout which is over-redundant when the only thing I want to change is string resources. The problem is aggravated the more cultures you add (you are effectively advocating an expotential growth of "sites" that are spawned for localization purposes the more "fundamental" sites there are) and the less non-string differences there are. In our case, users would be happy with no change in layout or style whatsoever.

Why wouldn't it be nice to let the web site remember the language and culture profile of a user?

There are many use cases I experienced myself, e.g. using web kiosks, using hotel PCs, using a friend's PC, all cases where the browser and OS language is different from the USER. Millions of people are in these situations. Think of logging in to your e-mail account from a hotel PC in France. The browser/OS is French, but you want it to display in English, right? And surely they blocked the browser control panel. There is so much culture-dependant code that must work based on who the user is, e.g. date formatting, time formatting, when listing e-mail messages.

Ultimately the problem is an impedance mismatch between the three models of localization:

1. Database-based (e.g. "sites", "pages" etc)
2. Resource-based (resx)
3. Framework-based (e.g. formatting, currencies)

Even with a good effort, we always end up with half-baked solutions, e.g. an English site displaying French dates or vice versa when these models mix together.

Fundamentally the best solution would be to be able to use resource files in the pages themselves. I really want to fork out a simple hack to the source code to enable this. Specifically, every time there is an opportunity to enter something which becomes HTML, e.g. a page title, or HTML control content, the system should automatically interpret and inject thread culture-aware resource tags which comes from RESX, as in standard .NET practice. The standard tag is: <%$ Resources:MyResource, MyResourceKey%>.

So instead of typing "Home", "News", "Forum", etc. at the header and then copying the whole site, I gradually migrate by replacing english terms with resource tags. There could also be a feature to auto-migrate all static strings to a resource file to get started easily, which could give nice keys, e.g. Page_Control_CamelCaseAbbreviation or something.

OR: alternatively, for every "string" field, you allow culturally sensitive options to be specified, in the database level. E.g. instead of directly storing a string, you store a resource key. Thus, the site needs to have a resource manager.

Then, there would be a hierarchy of preference overrides on the thread culture, e.g. by-profile (not avilable!), by-browser (OK now), by-site (OK now by forced web.config override), or even by-page.

From a coding viewpoint, the portal system should make thread culture the primary way to translate a site and move away from the data-centric orientation on some specific tables. It is the only reliable and fully framework-supported way to ensure that translation is nested down to any level of call depth in any controls. I would consider the database-based approach as a "draft" of a web site before globalizing it. I have tonnes of re-used DLL assemblies across various controls on the page, visited by multiple threads of multiple users. The thread culture is really my only friend in ensuring the correct behavior.

 

1/7/2010 5:11:58 AM
Gravatar
Total Posts 18439

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

Hi,

Changing only the labels and buttons when a user chooses a language from a dropdown list is exactly a half baked solution which is exactly why it does not interest me. If it interests you, you can implement it as a custom feature. Create a dropdown that sets a cookie to the chosen culture and create a custom http module that detects the cookie and sets the thread to execute on that culture.

Note that the resources used and the formating of dates and currency etc are all controlled by what culture the thread executes as except in a few places where we make sure formating is done according to the site default culture. For example if we sell products in dollars we do not want the formatting to show euros just because the user chose a culture which uses euro.

Trying to make the menu or other content that comes from the db be replaced by content from .resx files - a complex and convoluted solution, not going to happen in mojoPortal.  If you only want to do it from a menu you could remove the mojoportal menus from the skin and use some custom menu you build yourself.

If you don't want to actually make sites with specific language content you can use the google translate widget as I have on this site in the top banner image. If the user chooses a different language the whole page is translated. The translation may not be perfect but its is certainly better than any solution I can come up with and certainly better than just changing buttons and labels.

Best,

Joe

1/7/2010 9:01:08 AM
Gravatar
Total Posts 31
There are 10 kinds of people in the world, those who know binary, and those who don't

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

Hello Joe,

Thank you for all suggestions.

Surely we would not accept only translating buttons and labels. The translation should cover all resources of all types and their integration. We are also amending some of the supplied language resource files in mojoPortal for this purpose, if we come up with something useful we may share it. 

The reason why thread culture is quite important is because we use mojoPortal as a "WinForms for ASP.NET", with all of the basics for building a web application, supplemented with advanced web controls, actually, it is a highly unorthodox use of a CMS system but it does save tonnes of time. For text-heavy content, I would agree completely with the approach to split sites (publishing-oriented, documentation-oriented usage) as most of the work is to actually create the content, but in our case, each page on the whole site only contains one single instance of a custom control. Within these controls, everything is resource-file based and carefully crafted for handling any language generically -- far more than "buttons and labels" -- just as in a standard localized WinForms application. So, a mojoPortal page is mainly a metaphor for a "Form" or "Application Window" in WinForms.

Your suggestion to write a custom menu bar is excellent, it would be ideal if it could be populated through some API or specified by means of a general tree editor. The only feature that can build trees now in the mojoPortal system is the page creation, which allows a hierarchy, which is why it is an ideal data source for a menu bar structure. Then, our users can amend the menu themselves in the "application", like participative programming. One could have a skin with menu bars that are generated from the database or so. But it is redundant to store the structure more than once since only the text changes. In the case of this structure, the translation is only about text, really. There is no point in changing the menu structure for any language, no serious application vendor does this anyway (just look at Windows and Office, the localization never changes the structure, only resources, e.g. strings, and their appearance, e.g. right-left, etc), the position of elements is the same in all cultures.

In our case it would seem best to create one site per-language and then force the thread culture for each site.

Your suggestion to use a dropdown list to select a culture based on a cookie would not meet the requirement to remember a user since it will not remember the culture if the user logs in from another machine or the cookie is deleted. The setting should be stored on the server, persistent, per-user, like a roaming profile. Surely if only the thread culture changes and the page content does not, it is half baked, no doubt. But if the dropdown list ensures that, upon re-logon or changed setting, the site can redirect to the start page of another site with the correct culture of the db content, and as long as the site has the correct forced culture setting, all will be well and we can reach 100% localization. So the dropdown list component would have to update the custom profile property and redirect upon change.

For developers who have special requests, you could provide convenient event hooks in the framework, e.g. in the page cycle and data layer, and let developers attach to these. For example, there can be an event hook that reports any string coming from the db "about to be rendered". If any extension registers for it, it can implement anything it wants, like my suggested resource injection, and then return the processed string.

 

 

1/7/2010 9:11:31 AM
Gravatar
Total Posts 18439

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

See, it is not my goal to meet all unorthodox needs out of the box. I can give you more advice about a custom solution though.

Ok, create a custom menu (even copy code and modify the existing menu(s). Bind to the same hierarchal SiteMapDateSource like we do now and in your custom version modify the item databound event to lookup a resource name from a custom resource file passing in the menu item text as the key (you should not modify existing mojoportal resx files) and if the resource is found for the language you can replace the menu item text with the resource text.

Instead of a cookie, create a custom user profile property implemented as ISettingControl where you can populate a list oif languages in a dropdown and authenticated users can specify their preference. Then in your custom http module you can check the user property and set the culture. If Request.IsAuthenticated is false just return and do nothing.

Hope it helps,

Joe

1/7/2010 9:41:28 AM
Gravatar
Total Posts 31
There are 10 kinds of people in the world, those who know binary, and those who don't

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

Yes, this helps, the menu bar binding should do the trick. I get the idea of why we need a separate resource file for this. My point about the MojoPortal resources is that we are plugging gaps of missing strings in the official translations of the out-of-box features so it might be of general use.

We already implemented the custom user profile property using the method you stated, works fine. The next challenge is to create a custom HTTP module.  Do you have any general links, tutorials or guidelines or ideally some empty sample template to recommend for doing this in the mojoPortal environment?

1/7/2010 11:04:14 AM
Gravatar
Total Posts 18439

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

You can see an example of a custom HttpModule in the mojoPortal source code, we use one to set the culture based on the config settings. Look in Web/Components/CultureHelperHttpModule.cs

You compile yours into your own dll and configure it from the modules sections of Web.config. Note that they execute in the order they are listed in Web.config so if you want unauthenticated users to see the default site culture then yours should be plugged in after our existing one.

Hope it helps,

Joe

1/7/2010 9:37:17 PM
Gravatar
Total Posts 31
There are 10 kinds of people in the world, those who know binary, and those who don't

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

Thanks a lot

7/22/2011 5:39:28 AM
Gravatar
Total Posts 5

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

Since I needed this also, here is an implementation:

Custom profile setting:

<add name="Language"
    type="System.String"
    allowMarkup="false"
    resourceFile="CountryISOCode2Resources"
    labelResourceKey="LanguageLabel"
    lazyLoad="false"
    requiredForRegistration="false"
    showOnRegistration="false"
    allowAnonymous="false"
    visibleToAnonymous="false"
    visibleToAuthenticated="true"
    visibleToUser="true"
    editableByUser="true"
    regexValidationExpression=""
    regexValidationErrorResourceKey=""
    onlyAvailableForRoles=""
    onlyVisibleForRoles=""
    defaultValue="vi-VN"
    includeHelpLink="false"
    >
   <OptionList>
    <Option value="vi-VN" TextResourceKey="CountryLabelVietNam"></Option>
    <Option value="en-US" TextResourceKey="CountryLabelUnitedStates"></Option>
   </OptionList>
  </add>

and IHTTPHandler:

using System;
using System.Globalization;
using System.Threading;
using System.Web;
using mojoPortal.Business;
using mojoPortal.Web;

namespace CustomCultureForUser
{
   public class UserSettingCultureHelperHttpModule : IHttpModule
   {
      public void Init(HttpApplication application)
      {
         application.PostAuthorizeRequest += DetermineCulture;
      }

      public void Dispose() { }

      protected void DetermineCulture(object sender, EventArgs e)
      {
         HttpApplication app = (HttpApplication) sender;
         if (!app.Request.IsAuthenticated) return;
         try
         {
            SiteUser siteUser = SiteUtils.GetCurrentSiteUser();
            string langsetting = siteUser.GetCustomPropertyAsString("Language");
            if (!string.IsNullOrEmpty(langsetting))
            {
               CultureInfo ci = new CultureInfo(langsetting);
               Thread.CurrentThread.CurrentCulture = ci;
               Thread.CurrentThread.CurrentUICulture = ci;
               return;
            }
         }
// ReSharper disable EmptyGeneralCatchClause
         catch
// ReSharper restore EmptyGeneralCatchClause
         {
           //Ignore errors. Nothing we can do anyway
         }
      }
   }
}

I had to add LanguageLabel to CountryISOCode2Resources.resx

<data name="LanguageLabel" xml:space="preserve">
    <value>Language</value>
  </data>

7/22/2011 5:44:05 AM
Gravatar
Total Posts 5

Re: Forcing/defaulting to a specific language (culture) per-user based on custom profile setting

<add name="UserSettingCultureHelperHttpModule" type="CustomCultureForUser.UserSettingCultureHelperHttpModule, CustomCultureForUser" preCondition="managedHandler" />

I forgot the config for the handler. It has to added in ADDITION to the existing culture handler (not replace the existing)

Thus,
1. If a user has a custom culture defined, it is used as the first preference
2. If a user does not have a custom profile, it defaults to the culture of the site
3. If the site does not have a profile, it uses the web application's setting

Technically, it will first determine the culture in 3. Then it will invoke the mojoportal ihttphandler, which will do 2, thereby possibly overwriting the culture. And then it will run my ihttphandler, possibly overwriting the culture if the user has a setting for it. So in various stages of the request, it may end up with 3 different cultures. In reality this approach just makes the implementation simpler and works perfectly.

 

You must sign in to post in the forums. This thread is closed to new posts.