Laden...

[ungelöst] Einfacher Sprachumschalter mit ComboBox oder kompatibel gesucht

Erstellt von Padman vor 8 Jahren Letzter Beitrag vor 8 Jahren 2.518 Views
P
Padman Themenstarter:in
52 Beiträge seit 2015
vor 8 Jahren
[ungelöst] Einfacher Sprachumschalter mit ComboBox oder kompatibel gesucht

Hallo,
ich bin zwar immer noch Anfänger in Sachen C#, dennoch suche ich eine einfache Möglichkeit, ein Formular zwischen verschiedenen Sprachen umzuschalten. Ich hatte zwar einen uralten Code welches einfache Steuerelemente umschalten konnte, aber keine TabControls und andere Elemente umschaltet.

Damit das Komplette Formular in der ausgewählten Sprache erscheint, müsste oberhalb von InitializeComponent(); CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); stehen. Auch damit hatte ich schon experimentiert, aber ich konnte keinen Umschalter bauen, der auch den jeweiligen Wert der CultureInfo.GetCultureInfo geben könnte X(

Es wäre erst einmal egal, ob das Programm neu gestartet werden müsste, schöner wäre es in Live.

Momentan wird das MetroFramework und nicht das aus .NET direkt, verwendet.

Über eine Lösung wäre ich sehr dankbar, da die Sprachdateien existieren 🙂 nur der passende Umschalter nicht, und der Code (Teilstück)

foreach (Control c in Controls)
{
ComponentResourceManager resources = new ComponentResourceManager(typeof(Form1));
resources.ApplyResources(c, c.Name, new CultureInfo(lang));
}

nicht auf Tabs, Menü's (.NET + MetroFramework) reagiert X(

Vielen Dank.

Hinweis: Form1 wird hier nur als Beispiel genannt.

Gruß Padman
2.298 Beiträge seit 2010
vor 8 Jahren

Hallo,

bezüglich der Anwendung sei gesagt, dass du alle Controls rekursiv durchlaufen musst. Möglicherweise in einer Methode ähnlich dieser:


private void SetCultureInfo(Control parent, CultureInfo cui)
{
     foreach (Control c in parent.Controls)
     {
          ComponentResourceManager resources = new ComponentResourceManager(typeof(Form1));
          resources.ApplyResources(c, c.Name, cui);

          if(c.Controls.Count > 0)
               this.SetCultureInfo(c, cui);
     }
}

Die Methode ist ungetestet. Für etwaigie Fehler übernehme ich keine Haftung. 😁

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

I
45 Beiträge seit 2012
vor 8 Jahren

Und weiterhin wäre zu sagen, daß die Menüs in der Control-Collection nicht beachtet werden.
Ich habe aus stackoverflow eine Methode gekupfert, wie auch Menüs und Menüitems rekursiv durchmustert.
Die mußt du zusätzlich zur normalen Controlcollection durchlaufen.

T
62 Beiträge seit 2012
vor 8 Jahren

Zwischenfrage:
Wo ist der Vorteil alle Controls in einer schleife rekursiv zu durchlaufen anstatt das jedes Control auf einen Event reagiert?

2.298 Beiträge seit 2010
vor 8 Jahren

Zwischenfrage:
Wo ist der Vorteil alle Controls in einer schleife rekursiv zu durchlaufen anstatt das jedes Control auf einen Event reagiert?

Angefangen dabei, dass es sich um Standard-Controls handelt und keine eigenen? Um die einzelnen Controls auf das Event reagieren zu lassen, müsste Padman jedes Control manuell überschreiben und das Event abonieren.

Welcher Weg erscheint dir jetzt weniger Aufwending?!

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

P
Padman Themenstarter:in
52 Beiträge seit 2015
vor 8 Jahren

Vielen Dank inflames2k, aber leider bin ich unwissend dein Beispiel Einzupflegen, wobei ich einiges ausprobiert hatte X(

Hier ein Standard-Beispielcode ohne MetroFramework, wobei die Umsetzung auch damit später im anderen Projekt klappen sollte 🙂

Selbst hierbei verhält sich das Formular nicht anders als im MetroFramework, einige Elemente bleiben in der Sprache des Betriebssystem. Wenn aber z.B. Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR"); verwendet wird, dann wird das komplette Formular in der eingegebenen Sprache angewandt. Den Code an sich habe ich etwas bearbeitet.

using System;
using System.ComponentModel;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
using sprachoberflaeche1.Properties;
using static System.Windows.Forms.Application;

namespace sprachoberflaeche1
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            //Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");
            //Thread.CurrentThread.CurrentUICulture = new CultureInfo(SetCultureInfo);
            InitializeComponent();
            LabelResource.Text = Resources.HelloText;
        }

        //private ResourceManager rm = new ResourceManager("sprachoberflaeche1.MainForm", typeof(MainForm).Assembly);

        private void buttonHelloWorld_Click(object sender, EventArgs e)
        {
            Exit();
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            comboBoxLanguage.Items.Add("English");
            comboBoxLanguage.Items.Add("Deutsch");
            comboBoxLanguage.Items.Add("Français");
            //comboBoxLanguage.SelectedIndex = 0;
            comboBoxLanguage.SelectedItem = comboBoxLanguage;

            // Languages
            //comboBoxLanguage.SelectedIndex = Settings.Default.Language;
            comboBoxLanguage.SelectedItem = Settings.Default.Language;
        }

        private void comboBoxLanguage_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (comboBoxLanguage.SelectedItem.ToString())
            {
                case "English":
                    ChangeLanguage("en-US");
                    break;
                case "Deutsch":
                    ChangeLanguage("de-DE");
                    break;
                case "Français":
                    ChangeLanguage("fr-FR");
                    break;
                default:
                    goto case "English";
            }
        }

        private void englishToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ChangeLanguage("en-US");
            //comboBoxLanguage.SelectedIndex = 0;
            comboBoxLanguage.SelectedItem = "English";
        }

        private void deutschToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ChangeLanguage("de-DE");
            //comboBoxLanguage.SelectedIndex = 1;
            comboBoxLanguage.SelectedItem = "Deutsch";
        }

        private void françaisToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ChangeLanguage("fr-FR");
            //comboBoxLanguage.SelectedIndex = 2;
            comboBoxLanguage.SelectedItem = "Français";
        }

        private void FormWelcome_FormClosing(object sender, FormClosingEventArgs e)
        {
            // Language
            //Settings.Default.Language = comboBoxLanguage.SelectedIndex;
            Settings.Default.Language = comboBoxLanguage.SelectedItem.ToString();

            // Save settings
            Settings.Default.Save();
        }

        private void ChangeLanguage(string lang)
        {
            foreach (Control c in Controls)
            {
                var resources = new ComponentResourceManager(typeof(MainForm));
                resources.ApplyResources(c, c.Name, new CultureInfo(lang));
            }
        }

        private void SetCultureInfo(Control parent, CultureInfo cui)
        {
            foreach (Control c in parent.Controls)
            {
                ComponentResourceManager resources = new ComponentResourceManager(typeof(MainForm));
                resources.ApplyResources(c, c.Name, cui);

                if (c.Controls.Count > 0)
                    this.SetCultureInfo(c, cui);
            }
        }

    }
}

Naja, das Ganze könnte natürlich etwas vereinfacht werden, gerade was die Wiederholung der Sprachtexte wie Deutsch betrifft.

Im Anhang ein Beispielprojekt (VS 2015)

Gruß Padman
T
314 Beiträge seit 2013
vor 8 Jahren

Da wird dir schon das Snippet gepostet und Du verwendest es nicht !?

2.298 Beiträge seit 2010
vor 8 Jahren

Hallo t0ms3n,

das es garnicht verwendet wird stimmt ja so nicht. Zumindest hat er es in seinen Code übernommen. 8)

Hallo Padman,

tausche deinen Aufruf der ChangeLanguage-Methode am besten direkt gegen den Aufruf der Methode SetCultureInfo.

Der Aufruf erfolgt dann wie folgt:


private void englishToolStripMenuItem_Click(object sender, EventArgs e)
{
     CultureInfo cui = new CultureInfo("en-US");
     this.SetCultureInfo(this, cui);
}

Am besten fährst du übrigens, wenn du direkt eine List<CultureInfo> für alle gültigen Sprachen an deine Combobox hängst und nur mit dieser arbeitest statt der String-Zuweisung und String-Prüfung.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

P
Padman Themenstarter:in
52 Beiträge seit 2015
vor 8 Jahren

Vielen Dank für deine Hilfe 🙂 An sich funktioniert es jetzt, aber leider werden immer noch nicht alle Elemente in der Zielsprache übernommen, wie Überschrift der Form, ToolTip, menuStrip und das leere Test-Label welches den Text aus der Resources.resx bezieht.

Am besten fährst du übrigens, wenn du direkt eine List<CultureInfo> für alle gültigen Sprachen an deine Combobox hängst und nur mit dieser arbeitest statt der String-Zuweisung und String-Prüfung.

Schaue mich diesbezüglich im Netz schon um, gibt dort auch wieder etliche verschiedene Beispiele. Nehmen wir an, wenn eine Liste mit allen gültigen Sprachen erstellt wird, werden nur die Sprachen in der Liste angezeigt, wo die passende Ressourcen-Datei existiert? Mit dem Menü war nur ein Test.

Edit
Im Netz bin ich über folgenden Code gestolpert, der das komplette Formular samt Steuerelementen umkrempelt:

private void mnuCultureEnglish_Click( object sender, EventArgs e ) {
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo( "en-US" );
Controls.Clear();
InitializeComponent();
}

private void mnuCultureGerman_Click( object sender, EventArgs e ) {
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo( "de-DE" );
Controls.Clear();
InitializeComponent();
}

Quelle: stackoverflow.com/questions/6661661/how-to-update-window-form-ui-after-setting-currentuiculture/30239583#30239583

Es wäre dennoch schön, wenn es auch mit dem ursprünglichen Schnippsel funktionieren würde 🙂 da das Beispiel für den Einsatz unbrauchbar ist, bezüglich der Settings-Datei.

Gruß Padman
2.298 Beiträge seit 2010
vor 8 Jahren

Hallo Padman,

warum sollte der von dir genannte Code von StackOverflow unbrauchbar sein? Wenn du dich ein wenig mit der Programmierung beschäftigst solltest du es eigentlich auf die Reihe bekommen deine Einstellungen geeignet anzufügen.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

P
Padman Themenstarter:in
52 Beiträge seit 2015
vor 8 Jahren

warum sollte der von dir genannte Code von StackOverflow unbrauchbar sein?

OK, unbrauchbar vielleicht nicht, aber nicht ganz elegant oder so.

Wenn du dich ein wenig mit der Programmierung beschäftigst solltest du es eigentlich auf die Reihe bekommen deine Einstellungen geeignet anzufügen.

Ich werde es mal versuchen. Dein Schnippsel war an sich schon besser, aber ich verstehe noch nicht, warum diese nicht auf alle Elemente gegriffen hat. Liegt es wirklich daran, dass die Elemente neu geladen werden müssen?

OK, für das MetroFramework verwende ich kein Menü oder ToolTip, dennoch wäre es interessant gewesen, wenn dein Beispiel auf alle Elemente greifen würde, da es mit dem Schnippsel aus StackOverflow Probleme mit der ComboBox gibt.

Gruß Padman
2.298 Beiträge seit 2010
vor 8 Jahren

Auf welche Elemente greift es denn nicht? Wenn ich es richtig sehe handelt es sich dabei nur um Menü's und Toolbars.

Bei diesen ist das Grundsätzliche Problem, dass die einzelnen Items keine "Controls" sind bzw. keine Objekte die von "Control" erben und es eben auch keine Controls-Collection gibt sondern nur eine "Items"-Collection.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

P
Padman Themenstarter:in
52 Beiträge seit 2015
vor 8 Jahren

Auf welche Elemente greift es denn nicht? Wenn ich es richtig sehe handelt es sich dabei nur um Menü's und Toolbars.

Auf den ersten Blick scheint dies so zu sein.

Bei diesen ist das Grundsätzliche Problem, dass die einzelnen Items keine "Controls" sind bzw. keine Objekte die von "Control" erben und es eben auch keine Controls-Collection gibt sondern nur eine "Items"-Collection.

Also zwei Paar Schuhe?

Könnte dies ebenfalls umgesetzt werden wie es bei Controls wäre?
Ich experimentiere herum, aber leider klappt nichts.

Ich habe deinen Code in mein Projekt eingepflegt, ein Problem gibt es noch, wenn die ComboBox umgeschaltet wird, wird aus der aktuellen Sprache des Betriebssystem die Daten geladen. Beispiel:

BS-Sprache: DE
Resources.resx (Englisch)
Resources.de-DE.resx (Deutsch)

Da die Sprache des Betriebssystem deutsch ist, werden auch die Daten aus Resources.de-DE.resx geladen, wird aber im Programm die Sprache Englisch gewählt, werden aber die Daten aus Resources.resx nicht geladen.

Kurzfassung: die Daten aus den Resources.resx-Dateien werden nur in der Sprache des Betriebssystem geladen und nicht wie in der ComboBox.

Beispiel wäre wenn ein String für einen Button geladen werden würde, englisch: Dark/Light, deutsch: Hell/Dunkel. Die Umschaltfunktion sähe so aus (aus dem Quelltext MetroFramework übernommen, desses Button eher metroTile enthielt keinen Text):

msmMain.Theme = msmMain.Theme == MetroThemeStyle.Light ? MetroThemeStyle.Dark : MetroThemeStyle.Light;
Gruß Padman
P
Padman Themenstarter:in
52 Beiträge seit 2015
vor 8 Jahren

Hallo,
ich möchte nicht unhöflich sein, aber das Problem konnte noch nicht behoben werden.

Die Werte aus der generierten Form1 werden per Sprachschalter geladen, aber in den übersetzen Resources.resx (Resources.<lang>-<LANG>.resx) werden einfach nicht geladen 🙁

Gibt es einen Grund warum die Werte aus den Sprachdateien Form1 geladen werden und nur die von Resources.<lang>-<LANG>.resx nicht?

Vielen Dank.

Gruß Padman