Mehrsprachige Anwendung



  • Das ist egal ob es im Konstruktor oder "direkt" initialisiert wird. Was ich meinte ist du sollst mal nach den InnerException von der XamlParseException schauen, da steht vielleicht was drin was dir weiter hilft.



  • So habe jetzt die Exception:
    Error - D:\...\CAD\CAD\Language.xml: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.

    EDIT:
    Fehler gefunden. Ich hatte ja den XML-Code aus dem Beispiel übernommen. Hier hieß ein Unterpunkt z.B. MenuItemEdit. Dieses gabe es so natürlich nicht in meinem Code. Ich hätte auch nicht gedacht, dass das beim Einlesen der XML-Datei eine Rolle spielt. Ich dachte, die Namen sind beliebig wählbar.

    Allerdings bekomme ich jetzt schon wieder diese Fehlermeldung. Allerdings diesmal in Bezug auf diese Zeile:

    translatedDictionary.Add(keyNode.Attributes["key"].Value, Value);
    

    Genauergesagt verursacht

    keyNode.Attributes["key"].Value
    

    den Fehler. Was läuft hier falsch?



    arbeite besser mit GetElementByTagName - das is am ende eine liste - wenn es die child nodes gab sind die da drinn, wenn nicht ist die liste leer
    versuch schoen dynamisch zu bleiben

    key = variable
    "key" = string mit dem inhalt "key"
    nur so vorne weg
    dein code mit dem
    Key tempkey = keyNode.Attributes["key"].Value;
    translatedDictionary.Add(tempkey , Value);
    ist nicht gut
    das laeuft bei dir bei jedem child node durch, das bedeutet das jedes child node bei wir ein attribut namens "key" haben muss
    => "key" gibts in deinem xml beispie nicht
    => selbst wenn doch, geh nicht davon aus das es immer so ist
    du musst echt dynamischer werden

    ueberleg dir gut ob du alle uebersetzungen in einer datei haben willst
    => was ist wenn verschiedene personen es uebersetzen? dann muss jemand immer manuell zusammen mergen
    => es wird verdammt unuebersichtlich wenn du mehr sprachen hast
    => die datei kann verdammt gross werden
    => es macht kein sinn alles zu laden wenn man nur eine sprache braucht
    == erstelle eine original Strings.xml
    und uebersetze (oder lass uebersetzen) diese dann nach Strings-de-DE.xml
    (mit ein fallback system, wenn es ein string in der datei nicht gibt das es dann aus der original datei gelesen wird



  • Hi, du hast recht, meine XML Datei hat ja gar keine "keys" gehabt. Ich frage mich echt wer den Blog geschrieben hat. Naja, habe die XML-Datei jetzt folgendermaßen umgeändert:

    <?xml version="1.0" encoding="utf-8" ?>
    <LanguageFile>
      <Region name="MainMenu">
        <BearbeitenMenu key="BearbeitenMenu">
          <de-DE>Bearbeiten</de-DE>
          <en-US>Edit</en-US>
          <nl-NL>Bewerken</nl-NL>
          <fr-FR>Modifier</fr-FR>
        </BearbeitenMenu>
      </Region>
    </LanguageFile>
    

    Das Programm läuft nun, aber das "BearbeitenMenu" zeigt keinen Text an. Kann es sein, dass die Methode aus dem Blog über

    Header="{Binding Translation[BearbeitenMenu]}"
    

    auch nicht funktioniert? Oder muss ich das Fenster nochmal aktualisieren lassen oder ähnliches?

    Du hast recht, die Einlesemethode ist noch nicht optimal, aber mir geht es erstmal darum es überhaupt zum Laufen zu bekommen. Und ehrlich gesagt, finde ich dieses Schema schon sehr übersichtlich. Und wegen der Übersetzbarkeit habe ich gelesen man könne XML-Dateien ganz einfach in EXEL-Dateien konvertieren, so dass das Übersetzten dann kein Problem sein sollte. Die Datei wird sicher groß, wenn ich aber für jede Sprache eine eigene XML-Datei schreibe, habe ich halt mehrere kleinere, die aber durch den "Offset" des Formats insgesamt sogar noch mehr Speicherplatz verbrauchen. Darum finde ich die "EineDateiLösung" ganz gut. Evtl. nimmt eben das Einlesen mehr Zeit in Anspruch. Ich denke aber, dass es da bestimmt Möglichkeiten gibt, den Code abzuändern, dass nicht mehr alle Childnodes durchgegangen werden müssen.

    Das GetElementByTagName habe ich mir mal angeschaut, muss mir aber nochmal Gedanken machen, wie man das am besten umsetzen könnte.



  • stell dir mal vor - du hast eine applikation mit mehr als 1000 strings (mein tool auf arbeit hat derzeit 2500 strings) und alle sind von 5 bis 300 worten pro string

    das alles in einer xml datei ist ja wahnsinn

    aber weg davon - das aufteilen ist was fuer spaeter, eilt nicht

    was das lesen an geht, bleibt am generischer im aufbau der xml, benenne nodes nicht nach der culture, und auch nicht nach der kategorie, das erschwert nur unnoetig das lesen und die erweiterbarkeit (eine sprache mehr und du musst den code aenern)

    das ist besser find ich:

    <?xml version="1.0" encoding="utf-8" ?>
    <LanguageFile>
      <Region name="MainMenu">
        <Category key="BearbeitenMenu">
          <Language culture="de-DE">Bearbeiten</de-DE>
          <Language culture="en-US">Edit</en-US>
          <Language culture="nl-NL">Bewerken</nl-NL>
          <Language culture="fr-FR">Modifier</fr-FR>
        </BearbeitenMenu>
      </Region>
    </LanguageFile>
    

    ich wuerde es so versuchen: (hier im forum getippt)

    public class Region
    {
        public string Name { get; set; }
        public Category Category { get; set; }
    }
    
    public class Category
    {
        public Category()
        {
            Languages = new SortedList<CultureInfo, string>();
        }
        public string Key { get; set; }
        public SortedList<CultureInfo, string> Languages { get; set; }
    }
    
    var fileContent = new List<Region>();
    
    vardoc = XDocument.Load("file");
    var regionElements = doc.Descendants("Region");
    foreach (var regionElement in regionElements)
    {
        var region = new Region { Name = regionElement.Attribute("name").Value };
        var categoryElement = regionElement.Descendants("Category").FirstOrDefault();
        region.Category = new Category { Key = categoryElement.Attribute("key").Value };
        var languageElements = categoryElement.Descendants("language");
        foreach (var languageElement in languageElements)
            region.Category.Languages.Add(new CultureInfo(languageElement.Attribute("culture").Value), languageElement.Value);
    
        fileContent.Add(regionElement);
    }
    

    das lesen geht bestimmt auch deutlich schneller und kuerzer mit Linq, bin nur grad in eile und komm nicht dazu - morgen evtl



  • Super, danke dir für die Mühe, das mit dem Linq habe ich jetzt auch schon öfter gelesen. Bevor ich jetzt aber wieder alles umprogrammiere würde ich gerne noch wissen, woran die Ausgabe im Menü scheitert? Wenn ich die Strings über Dialoge ausgeben lasse klappt es ja.



  • das kann ich dir nicht sagen - da musst du selber buddeln - und evtl was eigenes schreiben
    dein problem wird spaeter dann auch sein, was ist wenn die sprache zur laufzeit umgestellt wird aber das fenster nicht neu geladen - dann bleibt der alte text noch bestehen

    ich finde die ganze manuelle handarbeit sehr fragwuerdig - warum nimmst du kein resourcedictionary ? das ist doch auch eine xml datei:

    1. du erstellst pro sprache ein resource dictionary:
    ENU

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:sys="clr-namespace:System;assembly=mscorlib"
              xml:space="preserve">
    
        <sys:String x:Key="MainMenu_Edit">Edit</sys:String>
    </ResourceDictionary>
    

    DEU

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:sys="clr-namespace:System;assembly=mscorlib"
              xml:space="preserve">
    
        <sys:String x:Key="MainMenu_Edit">Bearbeiten</sys:String>
    </ResourceDictionary>
    

    2. in xaml dateien benutzt du diese mit DynamicResource

    <MenuItem Header="{DynamicResource MainMenu_Edit}" />
    

    3. du fügst je nach sprache die resourcedictionary zu den mergedictionaries der applikation:
    this.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri("MyApplication;component\\Resources/Strings_de-DE.xaml", UriKind.Relative) });

    4. fertig
    => die strings werden automatisch geladen
    => die strings werden automatisch aktualisiert wenn sie sich aendern (wechseln der sprache)
    => laden der strings ist durch das .net framework bereits full tested und dadurch auch build-in fertig
    => du bist vorbereitet wenn du es mal professioneller machen willst
    => du hast die beste uebersicht, da die xaml dateien bis auf die uebersetzungen selber gleich aussehen



  • Habe es jetzt mit dem RessourceDictionary gelöst. Wie würde man es denn professioneller Lösen?



  • man erstellt eine Strings.xaml
    dann uebersetzt man diese nach einer Deutschen Strings.xaml
    und diese baut man zu einer sattelite dll - die muss dan im sub verzeichnis der exe liegen mit dem culture kuerzel

    \Demo.exe
    \de-DE\Demo.resoruces.dll
    \fr-FR\Demo.resoruces.dll

    der aufbau und der inhalt ist alles ganz genau vorgeschrieben - damit es funktioniert

    wenn: Demo.exe\Resources\Demo.g.resources -> mypath/strings.baml
    dann: Demo.resources.dll\Resources\Demo.de-DE.g.resources -> mypath/strings.baml

    in der applikation laed man einfach alle dictionaries neu beim sprachen wechsel - wpf schaut dann voll automatisch obs die entsprechenden dlls gibt - und wenn nicht wird auch voll automatisch das englische original als fallback genommen

    die frage ist nur - wie kommt man zur dll
    da kannst du zb das locbaml verwenden

    wir in der firma haben ne eigene methode daufuer entwickelt - hab also ein Xaml2Dll tool geschrieben



  • Student83 schrieb:

    ... Er scheint auch nur von hier rauskopiert und etwas abgeändert worden zu sein:
    http://www.turkhackteam.org/c-j-vb-net-net-dilleri/multi-language-ornegi-37568.html
    ....
    Gruß Student83

    Ich finde solche Behauptung ehrlich gesagt etwas gewagt und so nicht in Ordnung. Ich habe dir in meinem Blog Unterstützung angeboten und muss dann so etwas lesen... 👎



  • Und um noch etwas Klarheit reinzubringen, der Artikel im Blog hat lediglich den Hintergrund, dass hier zweierlei Methodiken vorgestellt wurden, wie man eine Anwendung lokalisieren kann.

    Der Code hierfür muss natürlich verstanden und ausgebaut werden. Des Weiteren macht die XML Methodik nur dann Sinn, wenn diese z.B. in einer SOA Umgebung verwendet wird. Für eine einfache Lokalisierung einer kleinen Applikation ist die Verwendung von Resourcen natürlich die bessere Wahl.

    mfg
    Mario



  • Falls es von interesse ist, ich Schreibe zZt eine Artikel Serie zum thema Lokalisierung von WPF Applikationen.
    Zu sehen auf meiner Website.
    Angefangen von einfachen übersetzen bis hin zum Professionellen Lokalisieren.



  • CSL schrieb:

    Falls es von interesse ist, ich Schreibe zZt eine Artikel Serie zum thema Lokalisierung von WPF Applikationen.
    Zu sehen auf meiner Website.
    Angefangen von einfachen übersetzen bis hin zum Professionellen Lokalisieren.

    Nettes WPF Blog, gleich mal in den Reader gepackt : )



  • Das freut mich immer wenn es Anklang findet 🙂



  • @ Mario Priebe
    Sorry, wollte dir nichts unterstellen, der Code hat sich halt teilweise sehr geähnelt, was ich mit der Verwendung des Worts "abgeschrieben" ausdrücken wollte. Dies war jedoch völlig ohne negative Wertung meinerseits gedacht.

    Zitat: "Ich finde solche Behauptung ehrlich gesagt etwas gewagt und so nicht in Ordnung. Ich habe dir in meinem Blog Unterstützung angeboten und muss dann so etwas lesen..."

    An der genannten Konversation war ich nicht beteiligt. Trotzdem nochmal danke für deinen Blog, hat mir schließlich auch geholfen.


Anmelden zum Antworten