Przejdź do treści

DevStyle - Strona Główna
Ustawianie kultury aplikacji na podstawie preferencji przeglądarki

Ustawianie kultury aplikacji na podstawie preferencji przeglądarki

Maciej Aniserowicz

16 maja 2011

Frontend

Wielojęzyczność aplikacji www można rozwiązać na kilka sposobów. Jedne strony mają rysuneczki flag symbolizujących język, w jakim chcemy widzieć teksty (i nie tylko) i pamiętają to w cookie. Inne pozwalają to ustawić w profilu użytkownika i pamiętają ustawienie w bazie.

Ostatnio pisałem rozwiązanie, które ustawia odpowiednią kulturę aplikacji na podstawie informacji wysyłanych przez przeglądarkę podczas żądania. Sam szkielet rozwiązania jest banalny:

  1:  public static class CultureUtils
  2:  {
  3:      public static void SetCurrentThreadCultureToBrowserPreferences()
  4:      {
  5:          var langs = HttpContext.Current.Request.UserLanguages;
  6:  
  7:          CultureInfo userCulture = CultureInfo.GetCultureInfo(langs[0]);
  8:  
  9:          Thread.CurrentThread.CurrentCulture = userCulture;
 10:          Thread.CurrentThread.CurrentUICulture = userCulture;
 11:      }
 12:  }

Pobieramy język wybrany jako pierwszy w ustawieniach przeglądarki… i już.

Jednak podczas działania aplikacji raz po raz coś zaczęło się wywalać. Problemem okazał się POST wysyłany przez flashowy uploadify – takie żądanie nie wysyłało UserLanguages. Więc pierwsza modyfikacja…

  1:  public static void SetCurrentThreadCultureToBrowserPreferences()
  2:  {
  3:      var langs = HttpContext.Current.Request.UserLanguages;
  4:  
  5:      if (langs != null)
  6:      {
  7:          CultureInfo userCulture = CultureInfo.GetCultureInfo(langs[0]);
  8:  
  9:          //....

Nie trwało jednak długo, zanim znalazłem kolejny problem. Otóż w przeglądarce użytkownik może przecież wybrać tzw “neutral culture”, czyli kulturę nie określającą regionu, do którego się odnosi (więcej info w MSDN). Przy próbie ustawienia takiej kultury jako UICulture dostajemy wyjątek:

Culture ‘en’ is a neutral culture. It cannot be used in formatting and parsing and therefore cannot be set as the thread’s current culture

I słusznie…

Niektóre aplikacje mogłyby sobie pozwolić na wyświetlenie w tym momencie komunikatu “wybierz w przeglądarce ‘specific’ culture”. Jest jedno ALE… nie we wszystkich przeglądarkach da się to zrobić! Na przykład domyślnie w FF 4.0 nie ma kultury “pl-PL”, jest tylko “pl”. Wymaganie od użytkownika żeby sam definiował nową kulturę na poziomie przeglądarki to trochę przegięcie.

Wystarczyło jednak kilka chwil zastanowienia i taką sytuację rozwiązałem w następujący sposób:

  1:  public static class CultureUtils
  2:  {
  3:      private static readonly CultureInfo[] _allCultures = CultureInfo.GetCultures(CultureTypes.FrameworkCultures);
  4:  
  5:      public static void SetCurrentThreadCultureToBrowserPreferences()
  6:      {
  7:          var langs = HttpContext.Current.Request.UserLanguages;
  8:  
  9:          if (langs != null)
 10:          {
 11:              CultureInfo userCulture = CultureInfo.GetCultureInfo(langs[0]);
 12:              if (userCulture.IsNeutralCulture)
 13:              {
 14:                  // browser sent neutral culture that cannot be used for parsing and formatting
 15:                  // using first non-neutral culture inheriting from this culture
 16:                  userCulture = _allCultures.Where(x => x.Parent.LCID == userCulture.LCID)
 17:                      .First();
 18:              }
 19:              Thread.CurrentThread.CurrentCulture = userCulture;
 20:              Thread.CurrentThread.CurrentUICulture = userCulture;
 21:          }
 22:      }
 23:  }

Po prostu w przypadku otrzymania neutralnej kultury wyszukuję pierwszą lepszą kulturę specific będącą jej dzieckiem. A że nie znalazłem innego sposobu niż ten przedstawiony wyżej, to zostawiam go tu ku pamięci.

Zobacz również