Openxml Sdk Having Borders for Cell

How do I change the culture of a WinForms application at runtime

This worked:

private void button1_Click(object sender, EventArgs e)
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("fr-BE");
ComponentResourceManager resources = new ComponentResourceManager(typeof(Form1));
resources.ApplyResources(this, "$this");
applyResources(resources, this.Controls);
}

private void applyResources(ComponentResourceManager resources, Control.ControlCollection ctls)
{
foreach (Control ctl in ctls)
{
resources.ApplyResources(ctl, ctl.Name);
applyResources(resources, ctl.Controls);
}
}

Be careful to avoid adding whistles like this that nobody will ever use. It at best is a demo feature, in practice users don't change their native language on-the-fly.

Changing Application Culture at Runtime Failure

Maybe on your production machines the sattelite assembly of the new culture cannot be loaded for some reason and hence your application falls back to the neutral culture.

Check with Microsoft sysinternals Process Monitor tool for unsuccessfull satellite assembly file accesses.

You an also check with .NET fuslog tool http://msdn.microsoft.com/en-us/library/e74a18c4.aspx

Proper way to change language at runtime

I believe the solution shown in Hans Passant's comment might be the only (general) solution.

Personally, I use this base class for all forms that need to be localized:

public class LocalizedForm : Form
{
/// <summary>
/// Occurs when current UI culture is changed
/// </summary>
[Browsable(true)]
[Description("Occurs when current UI culture is changed")]
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Category("Property Changed")]
public event EventHandler CultureChanged;

protected CultureInfo culture;
protected ComponentResourceManager resManager;

/// <summary>
/// Current culture of this form
/// </summary>
[Browsable(false)]
[Description("Current culture of this form")]
[EditorBrowsable(EditorBrowsableState.Never)]
public CultureInfo Culture
{
get { return this.culture; }
set
{
if (this.culture != value)
{
this.ApplyResources(this, value);

this.culture = value;
this.OnCultureChanged();
}
}
}

public LocalizedForm()
{
this.resManager = new ComponentResourceManager(this.GetType());
this.culture = CultureInfo.CurrentUICulture;
}

private void ApplyResources(Control parent, CultureInfo culture)
{
this.resManager.ApplyResources(parent, parent.Name, culture);

foreach (Control ctl in parent.Controls)
{
this.ApplyResources(ctl, culture);
}
}

protected void OnCultureChanged()
{
var temp = this.CultureChanged;
if (temp != null)
temp(this, EventArgs.Empty);
}
}

Then instead of directly changing Thread.CurrentThread.CurrentUICulture, I use this property in static manager class to change UI culture:

public static CultureInfo GlobalUICulture
{
get { return Thread.CurrentThread.CurrentUICulture; }
set
{
if (GlobalUICulture.Equals(value) == false)
{
foreach (var form in Application.OpenForms.OfType<LocalizedForm>())
{
form.Culture = value;
}

Thread.CurrentThread.CurrentUICulture = value;
}
}
}

Change language at runtime in C# winform

 ComponentResourceManager resources = new ComponentResourceManager(typeof(Type));

The argument to the constructor is wrong, you are telling it to find the resources for System.Type. Which is why it is complaining that it can't find "System.Type.resources". It will never find those.

You need to pass the type of the form that you actually want to localize. Use this.GetType() instead. Albeit that this probably will just localize your Options form and not the rest of the windows in your app. You could iterate Application.OpenForms() instead. It is also necessary to apply the localization to all the controls. Not just the ones on the form, also the ones that are located inside containers like panels. Thus:

    private static void ChangeLanguage(string lang) {
Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang);
foreach (Form frm in Application.OpenForms) {
localizeForm(frm);
}
}

private static void localizeForm(Form frm) {
var manager = new ComponentResourceManager(frm.GetType());
manager.ApplyResources(frm, "$this");
applyResources(manager, frm.Controls);
}

private static void applyResources(ComponentResourceManager manager, Control.ControlCollection ctls) {
foreach (Control ctl in ctls) {
manager.ApplyResources(ctl, ctl.Name);
applyResources(manager, ctl.Controls);
}
}

Be careful with wiz-bang features like this. Nobody actually changes their native language while they are using your program.

Changing CurrentUICulture at runtime in a Localizable Form in WinForms

After some tries, I have realized that several things are failing.

I have to say also that all the given help in this question is greatly appreciated, and also that the LocalizedForm snippet is very useful.

The first issue is that I have realized is that the controls that are under a level of more than 1 in the child hierarchy with this solution doesn't work.

And iterating over all the controls is a expensive task. Maybe mine is worst but has less iterations (because I only seach for Controls with Text)

    /// <summary>
/// Current culture of this form
/// </summary>
[Browsable(false)]
[Description("Current culture of this form")]
[EditorBrowsable(EditorBrowsableState.Never)]
public CultureInfo Culture
{
get { return this.culture; }
set
{
if (this.culture != value)
{
ResourceSet resourceSet = new ComponentResourceManager(GetType()).GetResourceSet(value, true, true);
IEnumerable<DictionaryEntry> entries = resourceSet
.Cast<DictionaryEntry>()
.Where(x => x.Key.ToString().Contains(".Text"))
.Select(x => { x.Key = x.Key.ToString().Replace(">", "").Split('.')[0]; return x; });

foreach (DictionaryEntry entry in entries)
{
if (!entry.Value.GetType().Equals(typeof(string))) return;

string Key = entry.Key.ToString(),
Value = (string) entry.Value;

try
{
Control c = Controls.Find(Key, true).SingleOrDefault();
c.Text = Value;
}
catch
{
Console.WriteLine("Control {0} is null in form {1}!", Key, GetType().Name);
}
}

this.culture = value;
this.OnCultureChanged();
}
}
}

What I do is the following, first, I search for the ResourceManager, take care! Because here is the second issue and is that if you use CultureInfo.CreateSpecificCulture instead CultureInfo.GetCultureInfo in some cases a new culture will be created and default values will be returned (Form1.resx values instead of Form1.es.resx values (for example)).

Once we have loaded all the value from the resx file, we iterate over all of them, and we delete the double >> (it appears in some cases) and we get the name of those Controls that only have declared the Text attribute.

The next step is find the Control and replace its Text...

Well, I have a little mess with the derived classes, that's why I created a try-catch system, because, Controls.Find search in all the Derived Classes I would prefer to be a little bit more specific but I don't know how... (That's why I created this question)

With this we haven't to save any object because we won't clear and recreate them.

The main problem here wasn't the way I was doing this, because it was correct.
The problem is that Assemblies merged do weird things when you call for example this:

ResourceSet resourceSet = new ComponentResourceManager(GetType()).GetResourceSet(value, true, true);

The value will be the default... Something like that this Culture doesn't exist, and is because, the merged Assembly can't find the resx file.

So, I will try AppDomain.CurrentDomain.AssemblyResolve that @ScottChamberlain has suggested to me. Or ILRepack maybe.

Any help for optimization or ideas (in comments) of why this doesn't work will be appreciated!

How to change CurrentCulture at runtime?

Changing the current UI culture:

System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("he-IL");

or better, retrieve a cached read-only instance of the he-IL culture:

System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("he-IL");

At run time, ASP.NET uses the resource file that is the best match for the setting of the CurrentUICulture property. The UI culture for the thread is set according to the UI culture of the page. For example, if the current UI culture is Spanish, ASP.NET uses the compiled version of the WebResources.es.resx file. If there is no match for the current UI culture, ASP.NET uses resource fallback. It starts by searching for resources for a specific culture. If those are not available, it searches for the resources for a neutral culture. If these are not found, ASP.NET loads the default resource file. In this example, the default resource file is WebResource.resx.

Windows Forms Localize resx without changing Culture

The built resources file has a property ResourceManager that's used to return the desired content. This has an overload with a CultureInfo parameter. You can use it to request resources in individual languages:

var desiredCulture = new CultureInfo("en-us");
var text = MyStrings.ResourceManager.GetString(nameof(Resources.ExitMessage), desiredCulture);

If you want to set the culture globally for your resource file, you could also set it through the corresponding property:

var desiredCulture = new CultureInfo("en-us");
MyStrings.Culture = desiredCulture;

var text = MyStrings.ExitMessage;

How to implement runtime localization on Windows Form without control resetting?

Well, had to manage that myself; I found this interesting piece of code:

Instantly Changing Language in the Form

All you have to do is to remove/comment a few lines in ReloadControlCommonProperties (around l.120) to prevent it to reset specific properties of your controls - for me, it looks like:

protected virtual void ReloadControlCommonProperties(System.Windows.Forms.Control control, System.Resources.ResourceManager resources)
{
SetProperty(control, "AccessibleDescription", resources);
SetProperty(control, "AccessibleName", resources);
SetProperty(control, "BackgroundImage", resources);
SetProperty(control, "Font", resources);
SetProperty(control, "ImeMode", resources);
SetProperty(control, "RightToLeft", resources);
//SetProperty(control, "Size", resources);
// following properties are not changed for the form
if (!(control is System.Windows.Forms.Form))
{
SetProperty(control, "Anchor", resources);
SetProperty(control, "Dock", resources);
//SetProperty(control, "Enabled", resources);
//SetProperty(control, "Location", resources);
SetProperty(control, "TabIndex", resources);
//SetProperty(control, "Visible", resources);
}
if (control is System.Windows.Forms.ScrollableControl)
{
ReloadScrollableControlProperties((System.Windows.Forms.ScrollableControl)control, resources);
if (control is System.Windows.Forms.Form)
{
ReloadFormProperties((System.Windows.Forms.Form)control, resources);
}
}
}


Related Topics



Leave a reply



Submit