We have an application based on ASP.NET MVC 5.2 and we're using localization with Resource files (resx), Localization.resx, Localization.de-DE.resx, Localization.de-AT.resx, Localization.en-US.resx, Localization.en-GB.resx... etc etc which produces satellite assemblies.
We determine the language first by cookie and then as fallback by browser header information. Works very well.
protected internal void Application_BeginRequest(object sender, EventArgs e)
{
HttpCookie cultureCookie = httpRequest.Cookies[CookieName.Culture];
string cultureName;
if (cultureCookie != null)
cultureName = cultureCookie.Value;
else
{
if (httpRequest.UserLanguages != null && httpRequest.UserLanguages.Length > 0)
cultureName = httpRequest.UserLanguages[0];
else
cultureName = null;
}
cultureName = CultureHelper.GetImplementedCulture(cultureName); // returns default on null
Thread.CurrentThread.CurrentCulture = new CultureInfo(cultureName);
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
}
We use the Localization.PropertyName directly in views like
<div class="text-right">#Localization.Header_TopMenu_Service</div>
This works fine so far but after around 60-80 minutes we have a problem on just one environment (productive): the localization does not work anymore.
It effects just these textes! The thread still has the correct culture!
Internally we still work with the Thread.CurrentThread.CurrentCulture values like for static texts, calculations of taxes... and this still works.
So some parts of the application are now in english (static stuff and logic stuff like calulcation of taxes) and all elements from the Localization resources are in german (default).
Why can this happen?
We thought there is something with race conditions but we've embedded some information to the output and everything is fine:
<!--
CurrentCulture == 'en-GB'
CurrentUICulture == 'en-GB'
ManagedThreadId == '25'
IsThreadPoolThread == 'True'
-->
Even if the language in this output is en-GB the localization outputs our default ,which is german.
When we restart or recycle the application, the localization works for again 60 minutes.
We also tried to set the language via Filter or in the Controller: same issue.
What can be the reason for this weird issue?
Wrong implementation? Something with satellite assemblies? IIS issue? system configuration?
Because everything works fine on the test stage and this effects just occur on the prod (no new build, just a copy) I think it is something with the system.
Problem is solved.
It was a race condition which set Localization.Culture (or in other implementations Resources.Culture) globally to a specific language.
The problem was, that this should be null in web applications. If this is null, ResourceManager.GetString() uses Thread.CurrentThread.CurrentUICulture for localization.
If Localization.Culture is not null the ResourceManager does not care about Thread.CurrentThread.CurrentUICulture.
Related
I am trying to create a multi-lingual navigation in an MVC 5 application.
What I've done:
Set System.Threading.Thread.CurrentThread.CurrentUICulture to either "en-US" or "es-ES" based on cookie value (defaults to English
unless user selects Spanish)
Created three resource files (this is my first time using them, so I'm not certain I fully understand the concept...) Index.resx, Resouce.en-US.resx, Resouce.es-ES.resx. Each resource file is in a folder called App_GlobalResources folder
Added a name/value combination to each .resx file, Home/Home for Index.resx and en-US.resx, and Home/Casa for es-ES.resx
Tried using #Resources.Index.Home in my layout file, thinking that when the value of CurrentUICulture changed from en-US to es-ES and visa-versa, the language would change based on the values in my resource files.
Could someone please let me know how I can get the Spanish text when the value CurrentUICultureis "es-ES", and the English text when it is "en-US"?
_Layout.cshtml
Resource.resx
EDIT
I should have stated - #Resources.Index.Home does render the text "Home" in the navigation. However, when I switch CurrentUICulture to "es-ES", it still renders "Home", not "Casa"
EDIT 2
Here is how I set CurrentUICulture is global.asax
public void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (Request.Cookies["lang"] == null)
{
HttpCookie lang = new HttpCookie("lang");
lang.Value = "english";
lang.Expires = DateTime.Now.AddDays(30d);
Response.Cookies.Add(lang);
}
else if (Request.Cookies["lang"] != null)
{
if (Request.Cookies["lang"].Value != null && Request.Cookies["lang"].Value == "english")
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us");
}
else if (Request.Cookies["lang"].Value != null && Request.Cookies["lang"].Value == "spanish")
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("es-es");
}
}
}
Just try to replace #Resources.Index.Home with #Resources.Home.
This is ur understanding about localization.
Every app with localization (say N cultures) must have N .resx-files with the same name but different suffixes. + Default culture can be used without suffixes.
So u have 2 cultures - u must use 2 .resx files, not more. So Index.resx is not needed at all.
This should work. If not, more fixes:
- Don't use App_GlobalResources folder. Just create .resx in common project-folders or in project root folder, just as in desktop .NET-apps.
This helped me, hope this will help u.
I've localized my App in two languages (English and German) with the MulitlingualAppToolkit 4.0. English is the base language, while german is a translation based on the english one.
The translations are stored as resw-file inside folder "strings.en" and "strings.de".
In App.xaml.cs App() I set the culture like this:
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = GetCurrentCulture();
CultureInfo.CurrentUICulture = GetCurrentCulture();
private CultureInfo GetCurrentCulture()
{
var cultureName = new DateTimeFormatter("longdate", new[] {"US"}).ResolvedLanguage;
return new CultureInfo(cultureName);
}
(I got this quiet weird way to the regional-culture in Windows 10 from this article https://www.pedrolamas.com/2015/11/02/cultureinfo-changes-in-uwp/ since I recognized that CultureInfo.CurrentCulture and CultureInfo.CurrentUICulture are always "en-EN" no matter what i configurate in my machines regional- and language-settings)
To check if PrimaryLanguageOverride works as expected, I added a TextBox by the name of tbTest on my first Page and a button linkt to this event:
private void Button_Click(object sender, RoutedEventArgs e)
{
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = tbTest.Text;
Frame.Navigate(this.GetType(), 0);
System.IO.File.AppendAllText(System.IO.Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "PrimaryLanguageOverride.txt"),
DateTime.Now + " - Actual PrimaryLanguageOverride:\n " + WIndows.Globalization.ApplicationLanguages.PrimaryLanguageOverride);
}
catch(Exception ex) { Helper.Log.LogUnhandledError(ex); }
}
Now comes the weird stuff:
When Debugging, or executing the App from my Development-Machine, everything works as expected, but when I make an appx-bundle and install it on another (Windows10-Desktop) device, the App does not recognize the its Language.
In my situation, the device is set to german, regional as well as its language. Also when using the test-procedure, it defenetively gets the string I set , as long as it's a valid culture-name, e.g.: "en-EN", "en-US", "de-DE", "de", "en" (all of these are working fine on my development machine) if it's an invalid string, I get an exception, with a log-entry in my unhandled-error-log. It refresh the Page, and even writes the new-set language in my PrimaryLanguageOverride-Log, but it doesn't change any text I did translate.
So my question is, is this a common Issue (since I recognized in UWP/Win10 the culture-system is a little messed up) or do I use the wrong procedure to override the App-Culture?
This is an issue with AppXBundling. When Installing bundles, it checks with the current OS for the installed Language packs and copies the relevant language resources from the bundle and omits the other language files. The objective of a single bundle is to copy necessary resources and build the application and therefore the languages which are not in the system are considered irrelevant. As a fix you could stop generating single bundles and create package for each CPU architecture. Check this for more info
When opening a (razor) page containing a number with decimal places (set at 4 in this case) the comma separator is interpreted as a thousands separator which expands the number by it's decimal places as seen in this picture:
This is happening in the administration panel of the NopCommerce 3.8 development tree and only on a remote server. I don't see this issue with my debug build locally so this has probably something to do with server settings or even with underlying database (Microsoft SQL-Server). I'm not sure this is a NopCommerce issue though so I'm not limiting it to that tag.
I know that NopCommerce is forcing the en culture in the Administration panel because of how Kendo Grid works. Again, I'm not sure this has anything to do with the actual issue.
This issue also materializes in the fact that the text box doesn't allow the ',' character. i can only use '.'. Trying to save a number like '0.20' is terminated with the message:
The value '0.2000' is not valid for ...
Update 1 (culture set in Global.asax.cs):
if (webHelper.GetThisPageUrl(false).StartsWith(string.Format("{0}admin", webHelper.GetStoreLocation()),
StringComparison.InvariantCultureIgnoreCase))
{
//admin area
//always set culture to 'en-US'
//we set culture of admin area to 'en-US' because current implementation of Telerik grid
//doesn't work well in other cultures
//e.g., editing decimal value in russian culture
CommonHelper.SetTelerikCulture();
}
else
{
//public store
var workContext = EngineContext.Current.Resolve<IWorkContext>();
var culture = new CultureInfo(workContext.WorkingLanguage.LanguageCulture);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
This does seem like an issue with the culture it is using. Try specifying which culture to use in the web.config:
<configuration>
<system.web>
<globalization uiCulture="en" culture="en-US" />
I'm working on a silverlight application where I'm checking the url to see if the user is trying to access the "Spanish" version. My methods work fine on Windows 7 and Windows Vista but I'm getting a crash throwing an Argument_InvalidCultureName exception when a user of Windows XP tries to load the application. Can someone look at the code below a give me perhaps an idea of what's going wrong and how to resolve it? Thanks in advance.
if (HtmlPage.Document.DocumentUri.Query.Contains("Spanish") || HtmlPage.Document.DocumentUri.Query.Contains("spanish") || HtmlPage.Document.DocumentUri.Query.Contains("Espanol"))
{
try
{
var culture = new CultureInfo("es-ES");
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
catch (Exception)
{
// Do Something
}
}
I changed the logic over to "es" instead of "es-ES" and this worked fine on the XP machines.
i have two Resources files in the Properties folder of a WPF-project (VS 2008):
Resources.resx
Resources.de-DE.resx
Selecting the culture "de-DE" does not work (no error, but always the strings from "Resources.resx" are used):
public App()
{
UntitledProject2.Properties.Resources.Culture = new CultureInfo("de-DE");
}
BUT: if I rename "Resources.de-DE.resx" to "Resources.fr-CA.resx" or "Resources.en-US.resx"
and then set it via
UntitledProject2.Properties.Resources.Culture = new CultureInfo("fr-CA");
it works!! But why!? Mysterious...
By default, WPF will always use "en-US"; at least it did the last time I checked (which was .net 3.5). If you want WPF to instead use the culture currently set by the system, you would execute this code block:
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(
XmlLanguage.GetLanguage(
CultureInfo.CurrentCulture.IetfLanguageTag)));
This will override the default value used for the FrameworkElement's Language dependency property, which, again, is "en-US" by default.
Execute this code once and early on in the lifetime of your application. AFter that, you shouldn't have to worry about it again, unless you expect your user to be switching the culture in the middle of program execution...