Change Language in C# - c#

I am developing a multilingual program in C# on Windows
How to change Windows writing language on certain actions...
e.g. to change from English to Arabic on focus event.
Thanks

To select a whole new culture, set the CurrentThread.CurrentCulture to a new culture, e.g. to set to French:
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("fr-FR");
System.Threading.Thread.CurrentThread.CurrentCulture = ci;
You can find a list of the predefined CultureInfo names here and here.
If you want to change certain aspects of the default culture, you can grab the current thread's culture, use it it's name to create a new CultureInfo instance and set the thread's new culture with some changes, e.g. to change the current culture to use the 'Euro' symbol:
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo( System.Threading.Thread.CurrentThread.CurrentCulture.Name);
ci.NumberFormat.CurrencySymbol = "€";
System.Threading.Thread.CurrentThread.CurrentCulture = ci;

Thread.CurrentThread.CurrentCulture = yournewculture;
Also see the CurrentUICulture property.

In load Event insert the code below:
InputLanguage.CurrentInputLanguage =
InputLanguage.FromCulture(new System.Globalization.CultureInfo("fa-IR"));

In addition, if you want to refresh all the controls' resources at runtime, you will need to use something like this:
private void RefreshResources(Control ctrl, ComponentResourceManager res)
{
ctrl.SuspendLayout();
res.ApplyResources(ctrl, ctrl.Name, CurrentLocale);
foreach (Control control in ctrl.Controls)
RefreshResources(control, res); // recursion
ctrl.ResumeLayout(false);
}
If you want a better example check my blog.

This statements were helpful for me:
string myLanguage = "HE-IL";
InputLanguage.CurrentInputLanguage =
InputLanguage.FromCulture(new System.Globalization.CultureInfo(myLanguage));

Related

Instance is read-only Exception while changing culture in asp.net

I try to implement multicultural application where users able to change language, date format and etc. I wrote core but it returns Exception:
System.InvalidOperationException: Instance is read-only.
switch (culture)
{
case SystemCulture.English:
Thread.CurrentThread.CurrentCulture = new CultureInfo(CultureCodes.English);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(CultureCodes.English);
break;
//another cultures here
}
switch (cultureFormat)
{
case SystemDateFormat.European:
var europeanDateFormat = CultureInfo.GetCultureInfo(CultureCodes.Italian).DateTimeFormat;
Thread.CurrentThread.CurrentCulture.DateTimeFormat = europeanDateFormat;
Thread.CurrentThread.CurrentUICulture.DateTimeFormat = europeanDateFormat;
break;
//another cultures here
}
I found some information on internet and i have to use new instance object of my culture, i changed my code just adding:
CultureInfo myCulture;
switch (culture)
{
case SystemCulture.English:
myCulture= new CultureInfo(CultureCodes.English);
break;
}
and bellow, out of switch :
Thread.CurrentThread.CurrentCulture = cultureInfo;
I'm not familiar with Threads and i'm not sure if i used is correctly.
Could you please suggest me how to do this it right way ?
You get the Instance is read-only error because you are trying to alter a property on a a read-only culture, via the code below.
Thread.CurrentThread.CurrentCulture.DateTimeFormat = europeanDateFormat;
You can check whether a culture is readonly via its IsReadOnly property; the built-in ones are.
Instead, you must make a clone/copy of the currently active culture, apply any changes on that clone and assign that one to the CurrentCulture and/or CurrentUICulture of the current thread.
var clone = Thread.CurrentThread.CurrentCulture.Clone() as CultureInfo;
clone.DateTimeFormat = CultureInfo.GetCultureInfo("it").DateTimeFormat;
Thread.CurrentThread.CurrentCulture = clone;
Thread.CurrentThread.CurrentUICulture = clone;

Double ToString("C") culture specific

I know that this works (source):
double x = 9.7;
x.ToString("C", CultureInfo.CreateSpecificCulture("nl-NL"));
But I have this code in my code behind:
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
and in my aspx webform, I'd like to use double.tostring("C") so no cultureinfo there. Because it is set on the current thread. But the local machine is nl-NL. The CurrentThread is set to en-GB in the code behind, but the valutasign is still a euro sign instead of pound.
Am I missing something? Or is using the overload of tostring with the cultureinfo required? In other words, do I have to rewrite all double tostrings to use cultureinfo?
Make sure you initialize the culture soon enough in the page life cycle. In fact, there's even a method for you to override specially for this purpose: Page.InitializeCulture.
Example based on a cookie:
protected override void InitializeCulture()
{
var cookie = Request.Cookies[WebConfigurationManager.AppSettings["LocaleCookieName"]];
if (cookie != null)
Culture = UICulture = cookie.Value;
}
No need to call the base method, see the documentation for more information.

DateTimeFormat exception while creating a culture info in C# .Net Compact Framework

I am getting an exception when I try to initialize CultureInfo in my application.
Following is the code I am using:
public void SetLanguage(string cultureCode)
{
if (string.IsNullOrEmpty(cultureCode))
{
_cultureInfo = new CultureInfo("en");
}
else
{
_cultureInfo = new CultureInfo(cultureCode);
}
}
I am trying to create culture info for "no" culture code but I get exception PlateformNotSupported as it can not create CompareCulture and DateTimeFormat followings are the exceptions:
System.Globalization.CultureInfo.Check Neutral(CultureInfo culture) System.Globalization.CultureInfo.get_DateTimeFormat()
What is missing here , any idea will be appriciated ?
MSDN suggests to get a list of supported cultures and try to get required culture from that list. Otherwise use default culture.

How to get language without country from CultureInfo

Does anyone know in ASP.Net how to get the language of the currentculture without it's countryname?
I know this invariant culture's don't have this problem, but I don't know how to create them without specifying an explicit language. I want to display the active language and in nl-nl this is Dutch (Netherlands).
This is how I set the currentCulture:
private void Application_BeginRequest(Object source, EventArgs e)
{
string[] languages = HttpContext.Current.Request.UserLanguages;
string language = languages[0].ToLowerInvariant().Trim();
if (!string.IsNullOrEmpty(language))
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(language);
}
}
In my case, the culture is "nl-nl". Problem is that what is shown on the site when using CurrentCulture.EnglishName is "Dutch (Netherlands)".
I only want to see Dutch!
Thanks!
Simple:
CultureInfo ci = CultureInfo.GetCultureInfo ("nl-nl");
if( ci.IsNeutralCulture )
{
Console.WriteLine (ci.EnglishName);
Console.WriteLine (ci.NativeName);
}
else
{
Console.WriteLine (ci.Parent.EnglishName);
Console.WriteLine (ci.Parent.NativeName);
}
CultureInfo object contains property called Parent - if it's set then then there is CultureInfo with desired EnglishName = Dutch
You can use the HTTP_ACCEPT_LANGUAGE object.

Is there a way of setting culture for a whole application? All current threads and new threads?

Is there a way of setting culture for a whole application? All current threads and new threads?
We have the name of the culture stored in a database, and when our application starts, we do
CultureInfo ci = new CultureInfo(theCultureString);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
But, of course, this gets "lost" when we want to do something in a new thread. Is there a way of setting that CurrentCulture and CurrentUICulture for the whole application? So that new threads also gets that culture? Or is it some event fired whenever a new thread is created that I can hook up to?
In .NET 4.5, you can use the CultureInfo.DefaultThreadCurrentCulture property to change the culture of an AppDomain.
For versions prior to 4.5 you have to use reflection to manipulate the culture of an AppDomain. There is a private static field on CultureInfo (m_userDefaultCulture in .NET 2.0 mscorlib, s_userDefaultCulture in .NET 4.0 mscorlib) that controls what CurrentCulture returns if a thread has not set that property on itself.
This does not change the native thread locale and it is probably not a good idea to ship code that changes the culture this way. It may be useful for testing though.
This gets asked a lot. Basically, no there isn't, not for .NET 4.0. You have to do it manually at the start of each new thread (or ThreadPool function). You could perhaps store the culture name (or just the culture object) in a static field to save having to hit the DB, but that's about it.
If you are using resources, you can manually force it by:
Resource1.Culture = new System.Globalization.CultureInfo("fr");
In the resource manager, there is an auto generated code that is as follows:
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
Now every time you refer to your individual string within this resource, it overrides the culture (thread or process) with the specified resourceCulture.
You can either specify language as in "fr", "de" etc. or put the language code as in 0x0409 for en-US or 0x0410 for it-IT. For a full list of language codes please refer to: Language Identifiers and Locales
For .NET 4.5 and higher, you should use:
var culture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
Actually you can set the default thread culture and UI culture, but only with Framework 4.5+
I put in this static constructor
static MainWindow()
{
CultureInfo culture = CultureInfo
.CreateSpecificCulture(CultureInfo.CurrentCulture.Name);
var dtf = culture.DateTimeFormat;
dtf.ShortTimePattern = (string)Microsoft.Win32.Registry.GetValue(
"HKEY_CURRENT_USER\\Control Panel\\International", "sShortTime", "hh:mm tt");
CultureInfo.DefaultThreadCurrentUICulture = culture;
}
and put a breakpoint in the Convert method of a ValueConverter to see what arrived at the other end. CultureInfo.CurrentUICulture ceased to be en-US and became instead en-AU complete with my little hack to make it respect regional settings for ShortTimePattern.
Hurrah, all is well in the world! Or not. The culture parameter passed to the Convert method is still en-US. Erm, WTF?! But it's a start. At least this way
you can fix the UI culture once when your app loads
it's always accessible from CultureInfo.CurrentUICulture
string.Format("{0}", DateTime.Now) will use your customised regional settings
If you can't use version 4.5 of the framework then give up on setting CurrentUICulture as a static property of CultureInfo and set it as a static property of one of your own classes. This won't fix default behaviour of string.Format or make StringFormat work properly in bindings then walk your app's logical tree to recreate all the bindings in your app and set their converter culture.
This answer is a bit of expansion for #rastating's great answer. You can use the following code for all versions of .NET without any worries:
public static void SetDefaultCulture(CultureInfo culture)
{
Type type = typeof (CultureInfo);
try
{
// Class "ReflectionContext" exists from .NET 4.5 onwards.
if (Type.GetType("System.Reflection.ReflectionContext", false) != null)
{
type.GetProperty("DefaultThreadCurrentCulture")
.SetValue(System.Threading.Thread.CurrentThread.CurrentCulture,
culture, null);
type.GetProperty("DefaultThreadCurrentUICulture")
.SetValue(System.Threading.Thread.CurrentThread.CurrentCulture,
culture, null);
}
else //.NET 4 and lower
{
type.InvokeMember("s_userDefaultCulture",
BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
null,
culture,
new object[] {culture});
type.InvokeMember("s_userDefaultUICulture",
BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
null,
culture,
new object[] {culture});
type.InvokeMember("m_userDefaultCulture",
BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
null,
culture,
new object[] {culture});
type.InvokeMember("m_userDefaultUICulture",
BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
null,
culture,
new object[] {culture});
}
}
catch
{
// ignored
}
}
}
DefaultThreadCurrentCulture and DefaultThreadCurrentUICulture are present in Framework 4.0 too, but they are Private. Using Reflection you can easily set them. This will affect all threads where CurrentCulture is not explicitly set (running threads too).
Public Sub SetDefaultThreadCurrentCulture(paCulture As CultureInfo)
Thread.CurrentThread.CurrentCulture.GetType().GetProperty("DefaultThreadCurrentCulture").SetValue(Thread.CurrentThread.CurrentCulture, paCulture, Nothing)
Thread.CurrentThread.CurrentCulture.GetType().GetProperty("DefaultThreadCurrentUICulture").SetValue(Thread.CurrentThread.CurrentCulture, paCulture, Nothing)
End Sub
Working solution to set CultureInfo for all threads and windows.
Open App.xaml file and add a new "Startup" attribute to assign startup event handler for the app:
<Application ........
Startup="Application_Startup"
>
Open App.xaml.cs file and add this code to created startup handler (Application_Startup in this case). The class App will look like this:
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-US");
System.Globalization.CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
}
}
For ASP.NET5, i.e. ASPNETCORE, you can do the following in configure:
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(new CultureInfo("en-gb")),
SupportedCultures = new List<CultureInfo>
{
new CultureInfo("en-gb")
},
SupportedUICultures = new List<CultureInfo>
{
new CultureInfo("en-gb")
}
});
Here's a series of blog posts that gives more information:
How ASP.NET 5 determines the culture settings for localization
Allowing user to set culture settings in ASP.NET 5:
Part 1
Part 2
Here is the solution for c# MVC:
First : Create a custom attribute and override method like this:
public class CultureAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Retreive culture from GET
string currentCulture = filterContext.HttpContext.Request.QueryString["culture"];
// Also, you can retreive culture from Cookie like this :
//string currentCulture = filterContext.HttpContext.Request.Cookies["cookie"].Value;
// Set culture
Thread.CurrentThread.CurrentCulture = new CultureInfo(currentCulture);
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(currentCulture);
}
}
Second : In App_Start, find FilterConfig.cs, add this attribute. (this works for WHOLE application)
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// Add custom attribute here
filters.Add(new CultureAttribute());
}
}
That's it !
If you want to define culture for each controller/action in stead of whole application, you can use this attribute like this:
[Culture]
public class StudentsController : Controller
{
}
Or:
[Culture]
public ActionResult Index()
{
return View();
}

Categories

Resources