![]() |
multilingual mit ini datei ?
hallo leute, also ich wollte mein programm möglichst multilingual machen.
also das beim click auf ne combo box die sprache eingestellt wird. dies wollte ich über eine ini datei regeln, damit ich später nur noch die ini abändern muß. so jetzt hab ich aber ein problem...sagen wir 2 sprachen sind schon in der ini file:
Delphi-Quellcode:
dann hab ich ja später das problem, dass ich die anderen beim laden in die combo auch manuel angeben muß .
CBLang.Items.Add(Ini.ReadString('Language','1',''));
CBLang.Items.Add(Ini.ReadString('Language','2','')); oder habt ihr da ne idee ? |
Re: multilingual mit ini datei ?
Hallo,
ich weiß nicht, ob ich dein Problem richtig verstanden habe. Vielleicht suchst du so etwas:
Code:
Mit diesem Abschnitt in der .ini-Datei kannst du sowohl die Anzahl, als auch die Namen der Sprachen einlesen:
[Languages]
Count=3 1=Deutsch 2=English 3=Dialekt
Delphi-Quellcode:
Gruß Hawkeye
Count := Ini.ReadInteger('Languages', 'Count', 0);
for i := 1 to Count do CBLang.Items.Add(Ini.ReadString('Languages', IntToStr(i), '(noname)')); |
Re: multilingual mit ini datei ?
ja genau das könnte die lösung meines problems sein ..ich teste es direkt
|
Re: multilingual mit ini datei ?
danke funtzt
|
Re: multilingual mit ini datei ?
Ich hab das wie folgt gelöst:
- jede Sprache hat eine eigene INI Datei - diese Datei hat folgenden Aufbau: Zitat:
- dann gibt's noch in jeder Form eine Funktion, die beim Erstellen der Form und beim Ändern der Spracheinstellungen aufgerufen wird - diese Function sieht so aus bei mir
Delphi-Quellcode:
(Aufbau von GetLocalizedString: 1. Parameter = Section; 2. Parameter = Ident; 3. Parameter = Standardwert)
procedure TfrmOnlineUpdate.LoadLocalizedStrings;
const cLngFormSection = 'OnlineUpdate Window'; begin Caption := GetLocalizedString(cLngFormSection, 'Caption', Caption); btnClose.Caption := GetLocalizedString(cLngFormSection, 'Button_Close', btnClose.Caption); Label1.Caption := GetLocalizedString(cLngFormSection, 'Label_YourVersion', Label1.Caption); Label2.Caption := GetLocalizedString(cLngFormSection, 'Label_CurrentVersion', Label2.Caption); Label3.Caption := GetLocalizedString(cLngFormSection, 'Label_UpdateDate', Label3.Caption); Label4.Caption := GetLocalizedString(cLngFormSection, 'Label_LastVersionNews', Label4.Caption); Label5.Caption := GetLocalizedString(cLngFormSection, 'Label_ClickHereToDownload', Label5.Caption); fUnknown := GetLocalizedString(cLngFormSection, 'Text_Unknown', fUnknown); end; - GetLocalizedString geht nun in die aktuell ausgewählte Sprachdatei und liest mit Hilfe der INI Functionen den entsprechenden Text aus der Sprachdatei aus - falls dieser nicht vorhanden ist wird dieser Eintrag in der Sprachdatei mit dem Standardwert ergänzt Das ist eigentlich auch schon alles. Aus dem oben genannten solltest du eigentlich ohne Probleme deinen eigenen Code ableiten/erstellen können. Gruss Thomas |
Re: multilingual mit ini datei ?
Liste der Anhänge anzeigen (Anzahl: 1)
Hai ihr,
ich habe mir da auch mal etwas zum spielen gebastelt. Ich lese/schreibe die Komponentennamen und den Wert für ein Stringproperty in die INI (aufgeteilt nach Klasse und Property). Das ganze sieht dann so aus:
Delphi-Quellcode:
und so die INI für diesen Fall:
uses
TypInfo, IniFiles; var apppath: string; function MyGetWideStrProp(Instance: TObject; const PropName: string): Widestring; var PropInfo: PPropInfo; begin PropInfo := GetPropInfo(Instance, PropName); if PropInfo = NIL then begin raise EPropertyError.CreateResFmt(@SUnknownProperty, [PropName]); end; result := GetWideStrProp(Instance, PropName); end; procedure MySetWideStrProp(Instance: TObject; const PropName: string; const Value: Widestring); var PropInfo: PPropInfo; begin PropInfo := GetPropInfo(Instance, PropName); if PropInfo = NIL then begin raise EPropertyError.CreateResFmt(@SUnknownProperty, [PropName]); end; SetWideStrProp(Instance, PropInfo, Value); end; procedure WriteIni(aForm: TForm; aType: TClass; const aProperty: string = 'Text'); var CurrentCompo: TComponent; ndx: Integer; TranslateIni: TMemIniFile; CurrentText: string; begin TranslateIni := TMemIniFile.Create(apppath + 'default.lng'); try for ndx := 0 to Pred(aForm.ComponentCount) do begin CurrentCompo := aForm.Components[ndx]; if (CurrentCompo is aType) then begin CurrentText := MyGetWideStrProp(CurrentCompo, aProperty); TranslateIni.WriteString(CurrentCompo.ClassName + '-' + aProperty, CurrentCompo.Name, CurrentText); end; end; TranslateIni.UpdateFile; finally TranslateIni.Free; end; end; procedure ReadIni(aForm: TForm; aType: TClass; const aProperty: string = 'Text'); var CurrentCompo: TComponent; ndx: Integer; TranslateIni: TMemIniFile; NewText: string; begin TranslateIni := TMemIniFile.Create(apppath + 'default.lng'); try for ndx := 0 to Pred(aForm.ComponentCount) do begin CurrentCompo := aForm.Components[ndx]; if (CurrentCompo is aType) then begin NewText := TranslateIni.ReadString(CurrentCompo.ClassName + '-' + aProperty, CurrentCompo.Name, ''); MySetWideStrProp(CurrentCompo, aProperty, NewText); end; end; finally TranslateIni.Free; end; end; procedure TDemoForm.FormCreate(Sender: TObject); begin apppath := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0))); ReadIni(self, TEdit, 'Text'); ReadIni(self, TLabel, 'Caption'); end; procedure TDemoForm.FormDestroy(Sender: TObject); begin WriteIni(self, TEdit, 'Text'); WriteIni(self, TLabel, 'Caption'); end;
Code:
Der Vorteil ist das ich nicht für jedes Label und jeden Button usw. aus der INI lesen muss.
[TEdit-Text]
Edit1=Ein Text Edit2=noch einer Edit3= Edit4=*blubb* [TLabel-Caption] Label1=Ich bin ein Label Label2=Ich auch Label3=*blubb* Im Angang mal ein DemoProjekt. Zur Zeit bin ich noch daran die Funktion in eine eigene Klasse zu wuchten. |
Re: multilingual mit ini datei ?
Zitat:
![]() |
Re: multilingual mit ini datei ?
Hi Sharky,
Also ich habe das mal getestet udn auch mit SQL DB erfolgreich implementiert. Ich mache einmal alle Kompos in die SQL passe die Sprache an und lade die Daten von der SQL in eine ini um weniger LAst aufm Server zu habn. Geht super. Aber ein Problem hab i noch. Bei Komponenten wie zb.:LMDExplorerBar ClasS: TLMDExplorerbarsection und Item. Aufruf der Caption durch.
Delphi-Quellcode:
Nun wie bekomme ich die verschiedenen Section udn items mit in deine Version rein.
LMDExplorerbar1.Section[0].Items[0].caption:='test';
Das selbe bei TStatusbar.panels[0].caption. Danke. |
Re: multilingual mit ini datei ?
Zitat:
Eine Frage habe ich aber dennoch: Wie erreiche ich ein LabeledEdit.Editlabel.Caption ??? Wenn ich WriteLangIni(self, TLabeledEdit, 'Editlabel.Caption'); anwende, kennt er die property nicht ! Gruß, bluescreen25 |
Re: multilingual mit ini datei ?
Hai bluescreen25,
das "Problem" ist das ein TLabeledEdit ja ein "normales" Edit ist welches einfach noch ein TBoundLabel als "Unterkomponente" erzeugt. Darum geht das mit dem Code nicht. Aber man kann ihn ja erweitern um einfach die Unterkomponenten auch zu berücksichtigen. Ich habe das mal für die Funktion WriteIni gemacht.
Delphi-Quellcode:
Und dann so aufrufen:
interface
procedure WriteIni(aForm: TForm; aType: TClass; const aProperty: string = 'Text') overload; procedure WriteIni(aForm: TForm; aType, ASubType: TClass; const aProperty: string = 'Text') overload; implementation procedure WriteIni(aForm: TForm; aType: TClass; const aProperty: string = 'Text'); begin // Diese bleibt so wie gehabt end; // Das ist die überladene Funktion mit der Unterkompo procedure WriteIni(aForm: TForm; aType, aSubType: TClass; const aProperty: string = 'Text'); var CurrentCompo: TComponent; SubCompo: TComponent; ndx: Integer; subndx: Integer; TranslateIni: TMemIniFile; CurrentText: string; begin TranslateIni := TMemIniFile.Create(apppath + 'default.lng'); try for ndx := 0 to Pred(aForm.ComponentCount) do begin CurrentCompo := aForm.Components[ndx]; if (CurrentCompo is aType) then begin for subndx := 0 to Pred(currentcompo.ComponentCount) do // Hier suche ich die Unterkomponente begin SubCompo := CurrentCompo.Components[subndx]; if (SubCompo is aSubType) then begin CurrentText := MyGetWideStrProp(SubCompo, aProperty); TranslateIni.WriteString(aForm.Name + '-' + CurrentCompo.ClassName + '-' + SubCompo.ClassName + '-' + aProperty, SubCompo.Name, CurrentText); end; end; end; end; TranslateIni.UpdateFile; finally TranslateIni.Free; end; end;
Delphi-Quellcode:
Das musst Du jetzt nur noch für WriteIni umsetzen und dann sollte es gehen.
WriteIni(self, TEdit, 'Text');
WriteIni(self, TLabel, 'Caption'); WriteIni(self, TButton, 'Caption'); WriteIni(self, TLabeledEdit,TBoundLabel, 'Caption'); |
Re: multilingual mit ini datei ?
Zitat:
Danach kann ich das Write ausklammern und die ini kann mit diversen Sprachen vervielfältigt werden. Mal sehn vielleicht mache ich das noch umschaltbar im laufenden Betrieb. Hmm da fällt mir gerade ein, ein Ansatz für die Items (können ja mehrere sein) einer TRadioGroup hast evt auch noch im Kopf ? Ich denke mit den Möglichkeiten dann kann man alle anderen Kompos wohl erschlagen. Sagenhaft... :dancer: |
Re: multilingual mit ini datei ?
Ich habe das mal ein wenig abgewandet, weil writeIni SubCompo.name beim schreiben in die ini immer gleich ist. Es wurde dann ein Einzeiler (immer überschrieben) :wink:
Hier mal zusammenhängend für alle die dieses nützliche Tool gebrauchen können.
Delphi-Quellcode:
Aufruf:
unit Language;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls; procedure ReadLangIni(aForm: TForm; aType: TClass; const aProperty: string = 'Text'); overload; procedure ReadLangIni(aForm: TForm; aType, ASubType: TClass; const aProperty: string = 'Text'); overload; procedure WriteLangIni(aForm: TForm; aType: TClass; const aProperty: string = 'Text'); overload; procedure WriteLangIni(aForm: TForm; aType, ASubType: TClass; const aProperty: string = 'Text'); overload; resourcestring SUnknownProperty = 'Eigenschaft %s existiert nicht.'; implementation uses TypInfo, IniFiles, frmSetup; function MyGetWideStrProp(Instance: TObject; const PropName: string): Widestring; var PropInfo: PPropInfo; begin PropInfo := GetPropInfo(Instance, PropName); if PropInfo = NIL then begin raise EPropertyError.CreateResFmt(@SUnknownProperty, [PropName]); end; result := GetWideStrProp(Instance, PropName); end; procedure MySetWideStrProp(Instance: TObject; const PropName: string; const Value: Widestring); var PropInfo: PPropInfo; begin PropInfo := GetPropInfo(Instance, PropName); if PropInfo = NIL then begin raise EPropertyError.CreateResFmt(@SUnknownProperty, [PropName]); end; SetWideStrProp(Instance, PropInfo, Value); end; procedure WriteLangIni(aForm: TForm; aType: TClass; const aProperty: string = 'Text'); var CurrentCompo: TComponent; ndx: Integer; TranslateIni: TMemIniFile; CurrentText: string; begin TranslateIni := TMemIniFile.Create(Programmpfad + '\default.lng'); try for ndx := 0 to Pred(aForm.ComponentCount) do begin CurrentCompo := aForm.Components[ndx]; if (CurrentCompo is aType) then begin CurrentText := MyGetWideStrProp(CurrentCompo, aProperty); TranslateIni.WriteString(CurrentCompo.ClassName + '-' + aProperty, CurrentCompo.Name, CurrentText); end; end; TranslateIni.UpdateFile; finally TranslateIni.Free; end; end; // Das ist die überladene Funktion mit der Unterkompo procedure WriteLangIni(aForm: TForm; aType, aSubType: TClass; const aProperty: string = 'Text'); var CurrentCompo: TComponent; SubCompo: TComponent; ndx: Integer; subndx: Integer; TranslateIni: TMemIniFile; CurrentText: string; begin TranslateIni := TMemIniFile.Create(ProgrammPfad + '\default.lng'); try for ndx := 0 to Pred(aForm.ComponentCount) do begin CurrentCompo := aForm.Components[ndx]; if (CurrentCompo is aType) then begin for subndx := 0 to Pred(currentcompo.ComponentCount) do // Hier suche ich die Unterkomponente begin SubCompo := CurrentCompo.Components[subndx]; if (SubCompo is aSubType) then begin CurrentText := MyGetWideStrProp(SubCompo, aProperty); TranslateIni.WriteString(CurrentCompo.ClassName + '-' + SubCompo.ClassName + '-' + aProperty, CurrentCompo.Name, CurrentText); end; end; end; end; TranslateIni.UpdateFile; finally TranslateIni.Free; end; end; procedure ReadLangIni(aForm: TForm; aType: TClass; const aProperty: string = 'Text'); var CurrentCompo: TComponent; ndx: Integer; TranslateIni: TMemIniFile; NewText: string; begin TranslateIni := TMemIniFile.Create(ProgrammPfad + '\default.lng'); try for ndx := 0 to Pred(aForm.ComponentCount) do begin CurrentCompo := aForm.Components[ndx]; if (CurrentCompo is aType) then begin NewText := TranslateIni.ReadString(CurrentCompo.ClassName + '-' + aProperty, CurrentCompo.Name, ''); MySetWideStrProp(CurrentCompo, aProperty, NewText); end; end; finally TranslateIni.Free; end; end; // Das ist die überladene Funktion mit der Unterkompo procedure ReadLangIni(aForm: TForm; aType, ASubType: TClass; const aProperty: string = 'Text'); var CurrentCompo: TComponent; SubCompo: TComponent; ndx: Integer; subndx: Integer; TranslateIni: TMemIniFile; NewText: string; begin TranslateIni := TMemIniFile.Create(ProgrammPfad + '\default.lng'); try for ndx := 0 to Pred(aForm.ComponentCount) do begin CurrentCompo := aForm.Components[ndx]; if (CurrentCompo is aType) then begin for subndx := 0 to Pred(currentcompo.ComponentCount) do // Hier suche ich die Unterkomponente begin SubCompo := CurrentCompo.Components[subndx]; if (SubCompo is aSubType) then begin NewText := TranslateIni.ReadString(CurrentCompo.ClassName + '-' + SubCompo.ClassName + '-' + aProperty, CurrentCompo.Name, ''); MySetWideStrProp(SubCompo, aProperty, NewText); end; end; end; end; TranslateIni.UpdateFile; finally TranslateIni.Free; end; end; end.
Delphi-Quellcode:
Ergebnis Auszugsweise default.lng :
//Language-file-read
ReadLangIni(self, TButton, 'Caption'); ReadLangIni(self, TEdit, 'Text'); ReadLangIni(self, TLabel, 'Caption'); ReadLangIni(self, TGroupBox, 'Caption'); ReadLangIni(self, TCheckBox, 'Caption'); ReadLangIni(self, TOpenDialog, 'Title'); ReadLangIni(self, TLabeledEdit,TBoundLabel,'Caption'); ... //Language-file-write WriteLangIni(self, TButton, 'Caption'); WriteLangIni(self, TEdit, 'Text'); WriteLangIni(self, TLabel, 'Caption'); WriteLangIni(self, TGroupBox, 'Caption'); WriteLangIni(self, TCheckBox, 'Caption'); WriteLangIni(self, TLabeledEdit,TBoundLabel, 'Caption'); ...
Delphi-Quellcode:
Gruß bluescreen25
[TButton-Caption]
btnAudiopfad=Select btnPlaypfad=Select btnBilderpfad=Select [TLabel-Caption] labShortVor=selection forward labShortBack=selection backwards labShortEnter=selection execute [TGroupBox-Caption] gbDatei=rootfolder setup [TLabeledEdit-TBoundLabel-Caption] edtAudiopfad=music rootfolder edtPlaypfad=playlist rootfolder edtBilderpfad=photo rootfolder |
Re: multilingual mit ini datei ?
Hallo
Vielen Dank, eine absolut tolle und einfache Library! Wie würdet ihr nun mit einer gesamten Applikation umgehen. Es kann ja gut sein, dass es z.B. in zwei verschiedenen Dialogen einen Button namens TButton1 gibt. Möglich wäre meiner Ansicht nach vielleicht für jedes Formular eine Datei anzulegen oder zu den Namen als Prefix den Formularnamen hinzufügen
Delphi-Quellcode:
procedure TTfrmLanguageTest.Button1Click(Sender: TObject);
var j: integer; Form:TForm; begin for j := 0 to -1 + Screen.FormCount do Begin Form:=Screen.Forms[j]; WriteLangIni(Form, TButton, 'Caption'); WriteLangIni(Form, TMenuitem, 'Caption'); WriteLangIni(Form, TEdit, 'Text'); WriteLangIni(Form, TLabel, 'Caption'); WriteLangIni(Form, TGroupBox, 'Caption'); WriteLangIni(Form, TCheckBox, 'Caption'); End; end; Gibt es auch eine Möglichkeit um Ressourcenstrings auf diese weise auszulesen? Vielleicht hier nicht sinnvoll für mich aber trotzdem aber interessant. Oder noch viel besser. In meinen Programmen habe ich vielfach direkt Texte übergeben. S.w. sollte man dies vermeiden:) Beispiel raise Exception.create('Unknown class in Audiofile defintion ' + t.ClassName); oder in Messageboxen etc.:) Kann man solche "hart" codierte Strings mit ähnlichen Mitteln auch aufspüren? Beste Grüsse und vielen Dank für die Infos Geri |
Re: multilingual mit ini datei ?
Hi,
von einer Ini-Lösung würde ich Dir abraten, Geri. Bernhard Geyer hat in Beitrag #7 GNU GetText genannt, mit dem geht das ganze viel einfacher und Du brauchst Dir um solche Sachen wie "zwei Buttons1" keine Gedanken machen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:09 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz