C# Mehrsprachige GUI Entwickeln...

roker002

Commander
Registriert
Dez. 2007
Beiträge
2.077
Ich habe für ein Programm entwickelt, dass in 3 Sprachen laufen. Die GUI in 3 Sprache zu erstellen ist kein Problem.
Was eigentlich bei Mehrsprachigen Programmieren nicht gewährleistet wird, sind die Meldungen, die man auch in Mehreren Sprachen implementieren muss.
Für jedes Formular gibt es ja auch eigene resx Dateien für jeweilige Sprache. Diese sollte man aber nicht bearbeiten, da diese resx Dateien Überschrieben werden, wenn man was beim Projekt ändert (nach der selbe Methode wie "InitializeComponent"... dort wird alles überschrieben, falls meine irgend eine Änderung gemacht hat).

Meine Frage ist, kann man dieses Problem irgendwie umgehen. Wenn ich in den Property Ordner eine neue resx einfüge, dann kann ich dort nicht unter mehreren Sprachen unterscheiden. Ich bekomme einfach unter "Properties" Namespace einfach diese resx namentlich aufgelöst!

Klar kann man eine Property Var schreiben die eine entsprechende Sprache aussucht... und dann den Wert zurückgibt.
Gibt es hierzu noch eine andere Lösung!?

thx
 
Wenn es nur ein paar "Begriffe" sind, kannste diese im Array (mehrdimensional) hinterlegen.
Bei mittel vielen würde ich an deiner Stelle einfach eine extra Klasse names "Sprache" erstellen. (Meine bevorzugte Version, welche auch bei 6 Sprachen funktioniert, und jederzeit erweitert werden kann/könnte.)
Bei vielen gibt es den Ansatz der jeweiligen Sprachdateien (.txt, .rc, .xml, ...), wo alles drin steht und implementiert bzw. aufgerufen werden muss.

Beispielseite mit Infos.
 
Zuletzt bearbeitet: (Beispiel)
roker002 schrieb:
Wenn ich in den Property Ordner eine neue resx einfüge, dann kann ich dort nicht unter mehreren Sprachen unterscheiden.
Kannst du schon, du musst die resx-Dateien nur richtig benennen.
Sagen wir du nennst die Datei "MessageStrings.resx" dann ist darin die neutrale Sprache (Englisch empfiehlt sich, kann aber auch jede andere Sprache sein) enthalten, die verwendet wird wenn keine spezifischere Sprachversion vorhanden ist. Die anderen Sprachversionen heißen dann "MessageStrings.<CultureCode>.resx". <CultureCode> steht für die Culture, der entsprechenden Sprache (z. B. de-DE für Deutsch (Deutschland), de-AT für Deutsch (Österreich) oder auch nur "de" für Deutsch allgemein).
Sagen wir du brauchst eine Fehlermeldung, die du "ErrorMessage" nennst. In "MessageStrings.resx" legst du eine Ressource "ErrorMessage" mit dem z. B. englischen Text an. In der Datei "MessageStrings.de-DE.resx" eine Ressource mit dem gleichen Namen und dem deutschen Text an. Zugreifen kannst du dann einfach mit MessageStrings.ErrorMessage. Die richtige Sprache wird automatisch ausgewählt bzw. die neutrale Sprache verwendet wenn keine andere passt.
 
So das Problem wurde gelöst.
Offenbar kann man Resources.resx nicht wirklich aufspalten auf die Sprachen. Daher habe ich einfach Language.resx, Language.de-DE.resx und Language.ja.resx erstellt... und schon geht alles.
 

Anhänge

  • erklärung.jpg
    erklärung.jpg
    9,3 KB · Aufrufe: 578
Zuletzt bearbeitet:
So jetzt habe ich aber ganz andere Frage bezüglich "Localization". Ich will alle Sprachen, die ein Window.Form verwendet auflisten. Hab bis jetzt keine Lösung im Internet finden können.

Hab versucht mittels Reflection, aber da ich nicht weiß wonach ich genau suchen soll...


Danke
 
Zuletzt bearbeitet:
roker002 schrieb:
So jetzt habe ich aber ganz andere Frage bezüglich "Localization". Ich will alle Sprachen, die ein Window.Form verwendet auflisten. Hab bis jetzt keine Lösung im Internet finden können.

Hab versucht mittels Reflection, aber da ich nicht weiß wonach ich genau suchen soll...


Danke

Diese Ressourcen werden fest einkompiliert (embedded resource), vondaher sollte es über Reflection möglich sein.

Code:
Assembly assembly = Assembly.GetExecutingAssembly();
// Assembly otherAssembly = Assembly.Load( "My.Assembly.Namespace" );
string[] embeddedResourceNames = assembly.GetManifestResourceNames();
 
Das mit den Resourcenamen kannte ich schon, aber kann ja damit nichts anfangen. Es ist zu allgemein.

Ich habe bisschen herumgespielt und herausgefunden wie es gehen kann.
Hier ist die Lösung:

Code:
public static class Extender
{
    /// <summary>
    /// Culture information about the Default
    /// </summary>
    public static CultureInfo DefaultCulture;

    public static List<Cultures> GetCultures(Type t)
    {
        var result = new List<Cultures>();
        var a = t.Module.Assembly;
        foreach (var c in CultureInfo.GetCultures(CultureTypes.AllCultures))
        {
            try
            {
                if (a.GetSatelliteAssembly(c) != null)
                {
                    result.Add(new Cultures
                    {
                        Culture = c,
                        IsDefaultLanguage = false
                    });
                }
            }
            catch { }
        }
        if (DefaultCulture!= null)
            result.Add(new Cultures
            {
                Culture = DefaultCulture,
                IsDefaultLanguage = true
            });
        return result;
    }
    public static List<Cultures> GetCultures(this Form form)
    {
        return GetCultures(form.GetType());
    }
}

public class Cultures
{
    public CultureInfo Culture;
    public Boolean IsDefaultLanguage;

    public override string ToString()
    {
        return String.Concat(this.Culture.NativeName, " (", this.Culture.DisplayName, ")", this.IsDefaultLanguage ? " as Software default" : "");
    }
    public override int GetHashCode()
    {
        return this.Culture.GetHashCode();
    }
    public override bool Equals(object obj)
    {
        return (obj == null) ? false : obj.GetHashCode() == this.GetHashCode();
    }
}

Erklärung:

GetSatelliteAssembly liefert genau die Sprachassembly aus jeweiligen Typen. Habe für mich eine Extender Class geschrieben, die mir erlaubt auf Windows.Forms das ganze anzuwenden. An sich kann man einfach den Typen übergeben. Bei nichtexistierenden Assemblies wird die liste einfach mit Null Einträgen befüllt sein.

Wenn man eine Standard Culture hat, dann wird diese natürlich nicht in der Liste auftauchen. Will man diese Eintragen, so muss man es "per Hand" tun.


PS: Diese Methode ist sehr Langsam. Also, sollte man nicht zu oft aufrufen. Wer noch eine zusätzliche Schleife drüber hat wird lange warten müssen!
 
Zuletzt bearbeitet:
Zurück
Oben