Autor |
Beitrag |
AXMD
Beiträge: 4006
Erhaltene Danke: 7
Windows 10 64 bit
C# (Visual Studio 2019 Express)
|
Verfasst: Sa 19.03.05 20:04
Moin !
Im Zuge der Entwicklung des [url= www.dustsigns.de.vu]DSTP2[/url] wurde eine Unit zum Ändern der Sprache während der Laufzeit des Programms fällig - und zwar am besten eine, die minimalen Aufwand seitens der Wartung benötigt.
Hier einmal der Quelltext der Unit:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220:
|
Unit dslangmgr;
Interface
Uses SysUtils, Classes, Forms, TypInfo; Type TFileEntryComponent = Record ComponentName: String; Caption: String; End;
TFileEntryComponent2 = Record Index: Integer; Caption: String; End;
Function LoadLanguageFile(AFilename: String; AForm: TForm): Integer; overload; Function LoadLanguageFile(AFilename: String; Var AnArray: Array Of String): Integer; overload;
Implementation
Function AssignCaption(AForm: TForm; ComponentName, ACaption: String): Boolean; Var p: PPropInfo; Begin Result := false; If AForm.FindComponent(ComponentName) = Nil Then exit; Try p := GetPropInfo(AForm.FindComponent(ComponentName).ClassInfo, 'Caption'); If (p <> Nil) And (p^.SetProc <> Nil) Then SetStrProp(AForm.FindComponent(ComponentName), 'Caption', ACaption) Else Begin p := GetPropInfo(AForm.FindComponent(ComponentName).ClassInfo, 'Text'); If (p <> Nil) And (p^.SetProc <> Nil) Then SetStrProp(AForm.FindComponent(ComponentName), 'Text', ACaption) Else Begin Result := false; exit; End; End; Result := true; Except Result := false; End; End;
Function ParseFileEntry(FileEntry: String; Var Components: TFileEntryComponent): Boolean; Begin Try Components.ComponentName := Copy(FileEntry, 1, Pos(':', FileEntry) - 1); Delete(FileEntry, 1, Pos(':', FileEntry)); Components.Caption := FileEntry; Result := true; Except Result := false; End; End;
Function ParseFileEntry2(FileEntry: String; Var Components: TFileEntryComponent2): Boolean; Begin Try Components.Index := StrToInt(Copy(FileEntry, 1, Pos(':', FileEntry) - 1)); Delete(FileEntry, 1, Pos(':', FileEntry)); Components.Caption := FileEntry; Result := true; Except Result := false; End; End;
Function LoadLanguageFile(AFilename: String; AForm: TForm): Integer; Overload; Var list: TStringList; i: Integer; components: TFileEntryComponent; Begin Result := 0; Try Try list := TStringList.Create; list.LoadFromFile(AFilename); For i := 0 To list.Count - 1 Do Begin If list[i] = '' Then continue; If Copy(list[i], 1, 1) = '!' Then continue; If Not (ParseFileEntry(list[i], components)) Then Begin Inc(Result); continue; End; If Not (AssignCaption(AForm, components.ComponentName, components.Caption)) Then Begin Inc(Result); continue; End; End; Except Result := -1; End; Finally list.Free; End; End;
Function LoadLanguageFile(AFilename: String; Var AnArray: Array Of String): Integer; Overload; Var list: TStringList; i: Integer; components: TFileEntryComponent2; Begin Result := 0; Try Try list := TStringList.Create; list.LoadFromFile(AFilename); For i := 0 To list.Count - 1 Do Begin If list[i] = '' Then continue; If Copy(list[i], 1, 1) = '!' Then continue; If Not (ParseFileEntry2(list[i], components)) Then Begin Inc(Result); continue; End; AnArray[components.Index] := components.Caption; End; Except Result := -1; End; Finally list.Free; End; End;
End. |
Zur Verwendung hier zwei Beispiele:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| Procedure LoadLanguageFiles(Language: String); Var TempErr: Integer; Begin With MainForm Do Begin TempErr := LoadLanguageFile('lang\mainform.' + Language + '.lang', MainForm); If TempErr <> 0 Then ShowMessage('An error occured while loading language files (Code: ' + IntToStr(TempErr) + ')'); TempErr := LoadLanguageFile('lang\messages.' + Language + '.lang', MessageArray); If TempErr <> 0 Then ShowMessage('An error occured while loading language files (Code: ' + IntToStr(TempErr) + ')'); End; End; |
wobei MessageArray wiefolgt deklariert ist: MessageArray: Array[0..M_COUNT - 1] Of String;
Natürlich müsst ihr dazu Languagefiles erstellen. Hier zwei Beispiele:
Quelltext 1: 2: 3: 4:
| !Hallo, ich bin ein Kommentar ;)
Label1:Hello world Label2:Ich bin Label 2 |
Hier z.B. zwei Label; das hinter dem Doppelpunkt ist der Text, der zugewiesen wird.
Quelltext 1: 2: 3: 4:
| !Beispiel für ein Array
0:Ich bin Item #0 1:Hallo Welt :) |
Hier das selbe, nur, dass die Zahlen den jeweiligen Indizes im Array entsprechen.
Die Unit ist Open Source, der Header muss allerdings bleiben wie er ist; eine Erwähnung in irgendeiner Form wäre nett, wenn jemand die Unit verwendet
AXMD
//EDIT: Beispiele zwecks Verständlichkeit verbessert
//EDIT2: Immer diese Tippfehler ^^
Zuletzt bearbeitet von AXMD am Sa 19.03.05 21:18, insgesamt 2-mal bearbeitet
|
|
Christian S.
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Sa 19.03.05 20:25
Irgendwie stehe ich gerade ein wenig auf dem Schlauch, wie ich die Unit denn nun benutze, will heißen, wie bekomme ich die Texte in die Komponenten?
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Karlson
Beiträge: 2088
|
Verfasst: Sa 19.03.05 20:50
Mit der Languagefile.
Ich hab kurz rübergeschaut, und as far as i see (gibts die abkürzung AFAIS schon? ) liest er einfach alle captions der componenten aus, überprüft ob sie in der Languagefileliste sind und tauscht dann ggf. die Caption aus.
|
|
AXMD
Beiträge: 4006
Erhaltene Danke: 7
Windows 10 64 bit
C# (Visual Studio 2019 Express)
|
Verfasst: Sa 19.03.05 20:51
Das macht die Unit für dich. Beispiel: du hast Label2 auf deiner Form, das den Text "Englisch" bekommen soll.
Hier mal die Datei (ich nenn sie mal bla.lang) dafür:
Quelltext
Und dann einfach laden (z.B.):
Delphi-Quelltext 1:
| TempErr := LoadLanguageFile('bla.lang', Form1 ); |
So einfach geht's
AXMD
|
|
AXMD
Beiträge: 4006
Erhaltene Danke: 7
Windows 10 64 bit
C# (Visual Studio 2019 Express)
|
Verfasst: Sa 19.03.05 20:59
Karlson hat folgendes geschrieben: | Mit der Languagefile.
Ich hab kurz rübergeschaut, und as far as i see (gibts die abkürzung AFAIS schon? ) liest er einfach alle captions der componenten aus, überprüft ob sie in der Languagefileliste sind und tauscht dann ggf. die Caption aus. |
So änhlich : ich gehe die Datei zeilenweise durch, überprüfe, ob die Komponente existiert und eine der Eigenschaften Caption oder Text hat; ist das der Fall, wird der jeweiligen Eigenschaft der Text hinter dem Doppelpunkt zugeweisen
AXMD
|
|
retnyg
Beiträge: 2754
SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
|
Verfasst: Sa 19.03.05 21:07
aha, und wie ginge das nun wenn ich ein file für englisch, deutsch, französisch und italienisch habe ?
dann wirds wohl nicht mehr funktionieren. wie wäre es wenn du über den komponentennamen (edit1) vorgehst ?
_________________ es gibt leute, die sind genetisch nicht zum programmieren geschaffen.
in der regel haben diese leute die regel...
|
|
AXMD
Beiträge: 4006
Erhaltene Danke: 7
Windows 10 64 bit
C# (Visual Studio 2019 Express)
|
Verfasst: Sa 19.03.05 21:08
retnyg hat folgendes geschrieben: | aha, und wie ginge das nun wenn ich ein file für englisch, deutsch, französisch und italienisch habe ? |
Einfach je nach Einstellung ein anderes File laden (siehe erster Beitrag). Nenn die Files z.B. englisch.lang und deutsch.lang und mach if Programmsprache = 'Deutsch' then LoadLanguageFile('\deutsch.lang', Form1);
retnyg hat folgendes geschrieben: | wie wäre es wenn du über den komponentennamen (edit1) vorgehst ? |
Tu ich doch
AXMD
|
|
retnyg
Beiträge: 2754
SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
|
Verfasst: Sa 19.03.05 21:12
bei deinem programm ist also z.b. __Start der name eines controls ?
_________________ es gibt leute, die sind genetisch nicht zum programmieren geschaffen.
in der regel haben diese leute die regel...
|
|
AXMD
Beiträge: 4006
Erhaltene Danke: 7
Windows 10 64 bit
C# (Visual Studio 2019 Express)
|
Verfasst: Sa 19.03.05 21:14
retnyg hat folgendes geschrieben: | bei deinem programm ist also z.b. __Start der name eines controls ? |
So ist es; Benennung ist bei mir nach Menütiefe; zwei Unterstriche bedeuten also zweite Ebene, sprich kein Hauptmenüpunkt, sondern eins weiter unten:
Quelltext 1: 2:
| Datei Neu <- Das wäre z.B. __Neu |
Alles klar
AXMD
//EDIT: ersten Beitrag bearbeitet um Verständlichkeit zu erhöhen Hab statt meinen MenuItems Labels genommen
|
|
bayou
Beiträge: 88
D6 PE
|
Verfasst: Mo 15.12.08 19:04
Hi,
das Thema ist zwar schon etwas älter aber genau was ich gesucht habe.
Dein Programm funktioniert super, leider habe ich ein Problem.
Wie kann ich den Items von RadioGroup umbenenen?
Gibt es eine Möglichkeit dein Programm so zu erweitern das auch diese Umbenannt werden?
Wäre für eine Antwort echt super Dankbar.
Jürgen
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 15.12.08 19:13
Im Grunde müsste (wenn ich das beim schnellen Überfliegen richtig gesehen habe) nur in AssignCaption neben den Properties auch geprüft werden, ob es eine RadioGroup ist.
Wenn ja, müsstest du aus dem Wert aus der Languagedatei (ACaption) irgendwie mehrere Items auslesen (z.B. getrennt durch Semikola) und zuweisen.
|
|
AXMD
Beiträge: 4006
Erhaltene Danke: 7
Windows 10 64 bit
C# (Visual Studio 2019 Express)
|
Verfasst: Mo 15.12.08 19:14
Hallo!
jaenicke hat eigentlich schon das vorweggenommen, was ich auch gerade sagen wollte
AXMD
|
|
bayou
Beiträge: 88
D6 PE
|
Verfasst: Mo 15.12.08 19:19
könntet Ihr mir dabei helfen?
Bin immer noch Anfänger, komme zu selten dazu mit Delphi zu arbeiten.
Ist schon 1 Jahr her wo ich das letzte mal was gemacht habe.
Vielen Dank im vorraus
Jürgen
Zuletzt bearbeitet von bayou am Mo 15.12.08 21:53, insgesamt 1-mal bearbeitet
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 15.12.08 19:29
Hmm, ganz schnell hingeschrieben (geht sicher auch besser): Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| Function AssignCaption(AForm: TForm; ComponentName, ACaption: String): Boolean; Var p: PPropInfo; i: Integer; RadioGroup: TRadioGroup; Begin Result := false; If AForm.FindComponent(ComponentName) = Nil Then exit; if AForm.FindComponent(ComponentName) is TRadioGroup then begin RadioGroup := TRadioGroup(AForm.FindComponent(ComponentName)); for i := 0 to RadioGroup.Items.Count - 1 do begin if Pos(';', ACaption) = 0 then RadioGroup.Items[i] := ACaption else RadioGroup.Items[i] := Copy(ACaption, 1, Pos(';', ACaption) - 1); Delete(ACaption, 1, Pos(';', ACaption)); end; Result := True; Exit; end; ... usw. | Ungetestet und es ginge vermutlich auch performanter (z.B. könnte man in der gesamten Routine eigentlich das Ergebnis von FindComponent zwischenspeichern ), aber es sollte seinen Zweck erfüllen. Die Items werden getrennt durch Semikola in der Datei erwartet.
|
|
bayou
Beiträge: 88
D6 PE
|
Verfasst: Mo 15.12.08 22:30
1000 Dank, es funktioniert super.
Ich werde jetzt erst mal ein wenig Testen um das ganze richtig zu verstehen.
nochmals Danke für Eure Hilfe
|
|
bayou
Beiträge: 88
D6 PE
|
Verfasst: Di 16.12.08 01:14
Könntet Ihr mir noch bitte einen Tip geben wie ich es mit den Caption der Form händeln muss?
Bin seit einiger Zeit dran und bekomme es nicht hin.
Vielen Dank
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 16.12.08 01:34
Nun ja, AForm.Name ist ja der Name deiner Form, wenn der Parameter ComponentName damit übereinstimmt, dann weise den Wert AForm.Caption zu.
|
|
bayou
Beiträge: 88
D6 PE
|
Verfasst: Di 16.12.08 08:09
OK, danke, ich versuche es mal.
|
|
ssb-blume
Beiträge: 375
Erhaltene Danke: 7
XP, W7, W8
Deutschland
|
Verfasst: Di 16.12.08 09:32
Frage:
Was macht der Anwender mit dem Programm, wenn er die Sprache wechseln will und
der Programmierer diese Sprache (noch) nicht berücksichtigt hat?
_________________ Brain: an apparatus with which we think we think.
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 16.12.08 09:38
Das kommt ja darauf an wie du das dann programmierst. Du kannst ja alle Sprachdateien suchen, die vorhanden sind, so dass man auch eigene erstellen kann, du kannst die theoretisch aber natürlich auch fest einprogrammieren.
Aber das hat mit der eigentlichen Unit ja nix zu tun, das liegt ja an deiner Programmierung, wenn du die Unit verwendest.
|
|
|