Benutzer mit den meisten Antworten
Auslesen für Sprachtexte

Frage
-
Hallo,
Ich habe nun eine allgemeine Frage bezüglich "Auslesen". Wenn man ein Programm schreibt, welches in mehrere Sprachen einstellbar ist. zB Durch Klicken eines Buttons sollen alle Label Texte von Deutsch auf Englisch umgestellt werden.
Wie wäre dies am besten und schnellsten möglich?
Folgende Methoden habe ich probiert:
1.) Direkt ins Programm hineinschreiben
2.) In einer XML-Config Datei
3.) Normale Textdatei und Zeile für Zeile auslesen und anpassen.
Wobei die 1. Methode absoluter Schwachsinn ist, da dadurch 1000e Zeilen Code entstehen und die 3. Methode mir sehr eigenartig wirkt, da ich denke, dass es doch noch besseres gibt.
Das ganze sollte aber auch funktionieren, wenn man die "Sprachdatei"löscht, das heißt, dass sie direkt neu von einer Datenbank zB runtergeladen wird.
Mit freundlichen Grüßen.
Markus Ö.
- Bearbeitet Bashesz Samstag, 29. März 2014 01:07
Antworten
-
Hallo,
je nachdem mit welcher Technologie du arbeitest, gibt es leicht unterschiedliche Wege. Grundsätzlich gilt das alles in einer Resourcendatei gespeichert wird. Aufgrund deiner anderen Fragen vermute ich mal, dass du mit Windows Forms arbeitest. Unter Globalisieren von Windows Forms erfährst du alles wissenswerte zum Übersetzen. Speziell dieser Artikel könnte interessant sein.Dieser Weg basiert zwar auf Resourcen, die in der EXE enthalten sind und somit nach dem kompilieren unveränderlich sind, aber es ist der einfachste Weg. Löschen kann man die Dateien also auch nicht. (Es sei denn du lagerst die Resourcendateien in eine DLL aus, dann wäre es vielleicht auch möglich nachträglich Sprachen nachzuinstallieren.)
Es gibt noch verschiedene andere (teils kostenpflichtige) Übersetzungshilfsmittel. Aber ich weiß nicht ob sich das für dich lohnt, da ich die Größe der Anwendung nicht wirklich einschätzen kann.
Ich kenne aber keine größere Anwendung, bei der man die Anwendung zum Sprache ändern nicht neu starten muss. Das halte ich je nach Anzahl der Texte aber auch für Überflüssig, da man wohl nicht 2mal täglich die Sprache wechselt. Denn bei einer Änderung müsstest du alles manuell neu zuweisen.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Als Antwort markiert Bashesz Samstag, 29. März 2014 15:01
-
Hallo,
für WPF gibt es noch mal einen eigen AQrtikel in der MSDN, wo auch die dort wichtigen Eigenheiten von XAML beachtet werden: Globalisierung und LokalisierungIm Grunde ist unter WPF fast nichts anders als unter WinForms. Das Nachladen von Resourcen über das Internet habe ich zwar noch nicht probiert, sollte aber über DLL's funktionieren.
Das Ändern der Sprache wärend der Ausführung funktioniert durch eine manuelle Zuweisung, vielleicht auch durch eine art "Aktualisierung" in WPF.
Beim Übersetzen habe ich mehr Wissen zur Theorie als zur Praxis.Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Als Antwort markiert Bashesz Samstag, 29. März 2014 15:01
Alle Antworten
-
Hallo,
je nachdem mit welcher Technologie du arbeitest, gibt es leicht unterschiedliche Wege. Grundsätzlich gilt das alles in einer Resourcendatei gespeichert wird. Aufgrund deiner anderen Fragen vermute ich mal, dass du mit Windows Forms arbeitest. Unter Globalisieren von Windows Forms erfährst du alles wissenswerte zum Übersetzen. Speziell dieser Artikel könnte interessant sein.Dieser Weg basiert zwar auf Resourcen, die in der EXE enthalten sind und somit nach dem kompilieren unveränderlich sind, aber es ist der einfachste Weg. Löschen kann man die Dateien also auch nicht. (Es sei denn du lagerst die Resourcendateien in eine DLL aus, dann wäre es vielleicht auch möglich nachträglich Sprachen nachzuinstallieren.)
Es gibt noch verschiedene andere (teils kostenpflichtige) Übersetzungshilfsmittel. Aber ich weiß nicht ob sich das für dich lohnt, da ich die Größe der Anwendung nicht wirklich einschätzen kann.
Ich kenne aber keine größere Anwendung, bei der man die Anwendung zum Sprache ändern nicht neu starten muss. Das halte ich je nach Anzahl der Texte aber auch für Überflüssig, da man wohl nicht 2mal täglich die Sprache wechselt. Denn bei einer Änderung müsstest du alles manuell neu zuweisen.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Als Antwort markiert Bashesz Samstag, 29. März 2014 15:01
-
Hallo Koopakiller,
Erstmals danke für die schnelle Antwort.
Ja es stimmt ich arbeite zwar mit Windows Forms, nur möchte jetzt endgültig auf WPF umsteigen, da mir diese "Ruckler" beim Ein und Ausblenden von Panels nerven :)
Bin eben mal deine beiden Artikel überflogen und werde es dann nach der Bettruhe ausprobieren. Aber ich denke es ist genau so etwas, was ich suche. Ich hoffe, dass das dann auch mit WPF Funktioniert wenn ich schon dabei bin umzusteigen^^
Bezüglich der "ggrößeren Anwendung": Naja es ist ein Spiel in XNA geschrieben welches direkt ohne Neustart die die Texte auf die Ausggewählte Sprache anpasst. Was ich dabei bemerkt habe war, dass es die jeweiligen Sprachen in Textdokumenten vom Internet runterladet und dann anscheinend ausließt.
Mit freundlichen Grüßen
Markus Ö.
-
Hallo,
für WPF gibt es noch mal einen eigen AQrtikel in der MSDN, wo auch die dort wichtigen Eigenheiten von XAML beachtet werden: Globalisierung und LokalisierungIm Grunde ist unter WPF fast nichts anders als unter WinForms. Das Nachladen von Resourcen über das Internet habe ich zwar noch nicht probiert, sollte aber über DLL's funktionieren.
Das Ändern der Sprache wärend der Ausführung funktioniert durch eine manuelle Zuweisung, vielleicht auch durch eine art "Aktualisierung" in WPF.
Beim Übersetzen habe ich mehr Wissen zur Theorie als zur Praxis.Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Als Antwort markiert Bashesz Samstag, 29. März 2014 15:01
-
Hallo Koopakiller,
Ich hab mir nun deinen Artikel mal durchgesehen, und werde später versuchen es umzusetzen. Kling jedenfalls interessant!
Noch ein kurzer Sprung zu diesen Spiel, wo ich beobachtet habe, dass es die Sprachtexte aus einer Txt File nimmt. Ich habe in der Zwischenzeit auch probiert dies umzusetzen. Soweit so gut, Ich habe alle Zeilen ausgelesen und in einen Array gespeichert. In der textfile steht Links der Label und rechts der Text welcher dann dort stehen soll. (zB General_Cancel=Abbrechen)
Danach muss ich den Text Splitten von zB
General_Cancel=Abbrechen auf split[0] = General_Cancel und split[1] = Abbrechen
Das gesplittete speichere ich ebenfalls in einen Array ab, nur kommt für mich dann die Frage, wie es anschließend zum ändern der Texte von zB Labels kommt, alle auf einmal einer Klasse übergeben?, Das Array einer Klasse übergeben und jeden Label den jeweiligen Index des Arrays geben?
Hier ein kurzer Ausschnitt wie ich es eben zum testen geschrieben habe. Habe es vorerst in Console geschrieben^^
try { string[] splittet = new string[9999]; int counter2 = 0; StreamReader sr = new StreamReader("de.txt"); string[] txt = new string[9999]; int counter = 0; txt[counter] = sr.ReadLine(); while (txt[counter] != null) { counter++; txt[counter] = sr.ReadLine(); } while (counter > counter2) { string[] split = txt[counter2].Split('='); splittet[counter3] = split[0]; splittet[counter3+1] = split[1]; counter2++; counter3 = counter3+2; } } catch (Exception ex) { Console.WriteLine(ex.ToString()); Console.ReadLine(); } } }
Oder gebe es hier auch eine bessere Methode um dies Umzusetzen? Ich hoffe ich habe mich auch gut artikuliert :)
Mit freundlichen Grüßen
Markus Ö.
-
Hi,
die Idee mit dem Index finde ich nicht gut. Besser ist ein Dictionary. Die Zeilen der Textdatei werden nach "=" gesplittet. Der linke Teil ist der Schlüssel, der rechte Teil ist der Wert. Im Code bzw der Bindung kann dann über den Schlüssel der Anzeigewert geholt werden.--
Peter -
Hallo,
noch ergänzend zu Peter, je nachdem wie es sich für dich realisieren lässt, kannst du die Zuordnung von Schlüssel-Wert-Paaren (aus dem Dictionary<string,string>) vielleicht automatisch den Controls zuordnen.
So kannst du einfach alle Controls in einer Schleife durchgehen und anhand der Tag- oder Name-Eigenschaft den dazugehöhrigen Wert im Dictionary finden.Und noch ein kleiner Tipp: benutze zum Aufsplitten einer Zeile diese Überladung der Split-Methode:
string[] split = txt[counter2].Split(new char[]{'='}, 2);
Dadurch erhälst du maximal 2 Strings. Dadurch sind Zeilen wie "a=1+2=3" auch kein Problem da alles nach dem ersten = der Wert ist.
Deinen Code kann man aber noch deutlich verbessern:
var dict = ne Dictionary<string,string>(); using(var sr = new StreamReader("de.txt"))//Streamn öffnen { while(!sr.EndOfStream)//Lesen solange nicht am Ende der Datei { var split = sr.ReadLine().Split(new char[]{'='}, 2);//Aufspalten dict.Add(split[0],split[1]);//Schlüssel-Wert-Paar hinzufügen } } //dict enthält nun alle Zeilen der Datei
Der Code ist ungetestet, sollte aber so in etwa funktionieren.
Du könntest aber auch mit LINQ und File.ReadAllLines (bzw. ReadLines) arbeiten, das dürfte nochmal ein wenig schneller gehen.var dict = File.ReadLines(@"D:\Test\a.txt")//Alle Zeilen einlesen .Select(x => x.Split(new char[] { '=' }, 2))//Jede Zeile aufspalten .ToDictionary(x => x[0], x => x[1]);//Ein Schlüssel-Wert-Paar erstellen
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Bearbeitet Tom Lambert (Koopakiller)Moderator Samstag, 29. März 2014 18:16 LINQ Code ergänzt
-
Hallo,
habe eben probiert das ganze über ein Dictionary zu machen. Also wenn ich zB die erste Zeile Einlese (General_Cancel=Abbrechen) dann sollte das am Ende so aussehen oder?:
Dictionary<string, string> txt = new Dictionary<string, string>(); StreamReader sr = new StreamReader("de.txt"); string x = sr.ReadLine(); string[] split = x.Split('='); txt.Add(split[0],split[1]); Console.WriteLine(txt["General_Cancel"]); Console.ReadLine();
Und bei txt["General_cancel"] gebe ich dann den sozusagen den "Namen" des Labels oder was auch immer ein, da ja auf der Linken Seite Label,... steht und rechts der Text.
Mit freundlichen Grüßen
Markus Ö.
-
Hallo,
so in etwa. Den Stream soltest du besser in einen using-Block packen, damit dieser im Fehlerfall wieder frei gegeben wird.Auf die Strings zugreifen kannst du dann mit dem Teil, der vor dem = steht. Nun hatte ich die Idee, dass du beispielsweise ein Label mit dem Namen "General_Cancel" hast und somit nur über den Namen zugreifen musst:
foreach(var control in rootGrid.Children)//Alle Controls von rootGrid durchgehen { if(control is Label)//Ist das gefundene Control ein Label? (control as Label).Content = dict[control.Name];//Wert aus dem Wörterbuch anzeigen }
So könnte das in WPF aussehen, unter WinForms wäre es sehr ähnlich.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Bearbeitet Tom Lambert (Koopakiller)Moderator Samstag, 29. März 2014 19:28
-
Hallo,
erstmals danke euch beiden. Habe mir eben das 2. Codeexample von Koppakiller angesehen und es ist genau das was ich gesucht habe.
Nur frage ich mich jetzt noch wie in etwa die Schleife aussehen muss um zB alle Labels auf die Sprache anzupassen? Da ich jetzt wieder jeden einzelnen Label meines Wissen die Werte übergeben würde, was aber am Ende fast das gleiche ist als ich es vorher geschrieben habe.
EDIT:
Dein Post eben: Beim Textauslesen ist ja der linke Wert der Name des Labels oder was auch immer.Also wie du erwähnt hast zB General_Cancel
Mit freundlichen Grüßen
Markus Ö.
- Bearbeitet Bashesz Samstag, 29. März 2014 19:22
-
In meiner letzten Antwort siehst du schon den Ansatz für eine Schleife. Dabei ist rootGrid das Control mit den ganzen Labels. Jedes Control wird geprüft, ob es sich um ein Label handelt, wenn ja, dann wird der Text anhand des Namens gesetzt.
Wie gesagt, du könntest auch jedem Label die Tag-Eigenschaft zuweisen. Dann kannst du wie folgt den Text setzen:
foreach(var control in rootGrid.Children)//Alle Controls von rootGrid durchgehen { if(control is Label)//Ist das gefundene Control ein Label? (control as Label).Content = dict[control.Tag.ToString()];//Wert aus dem Wörterbuch anzeigen }
Wenn die Label in mehrere Container verteilt sind, dann musst du alle durch gehen.
Unter WinForms funktioniert es übrigens genauso. Nur das die Control-Auflistung dort Controls und nicht Children heißt.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Hallo,
Habe es nun mit beiden Examples ausgetestet in WPF. Ich habe ein Grid mit dem Namen grid1 erstellt und darin 1 Button und 1 Label mit dem namen label1 platziert. In meiner txtfile habe ich es so hineingeschrieben:
label1=Test
Nur aus irgendeinen Grund taucht dann ein Fehler auf:
"object" enthält keine Definition für "Name" und es konnte keine Erweiterungsmethode gefunden werden.
Im 2. Code Exemplar ist dann fast der gleiche Fehler..
"object" enthält keine Definition für "Tag" und es konnte keine Erweiterungsmethode gefunden werden.
Hier der Code:
private void button1_Click(object sender, RoutedEventArgs e) { var dict = new Dictionary<string, string>(); using (var sr = new StreamReader("de.txt")) { while (!sr.EndOfStream) { var split = sr.ReadLine().Split(new char[] { '=' }, 2); dict.Add(split[0], split[1]); } } foreach (var control in grid1.Children) { if (control is Label) (control as Label).Content = dict[control.Tag.ToString()]; }
}
Mit freundlichen Grüßen
Markus Ö.
- Bearbeitet Bashesz Samstag, 29. März 2014 19:45
-
Ok, da hatte ich es falsch in Erinnerung. foreach nur ein object für die Children-Auflistung zurück. Somit muss es so aussehen:
foreach (var control in grid1.Children) { if (control is Label) (control as Label).Content = dict[(control as Label).Tag.ToString()]; }
Die Variante mit Tag funktioniert natürlich nur, wenn der Wert der Tag-Eigenschaft (in deinem Beispiel) "label1" enthält:<Label Tag="label1"/>
Dafür kann dann der Name beliebig gewählt werden.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.