Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi multilingual mit ini datei ? (https://www.delphipraxis.net/69184-multilingual-mit-ini-datei.html)

agm65 11. Mai 2006 12:50


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:
CBLang.Items.Add(Ini.ReadString('Language','1',''));
CBLang.Items.Add(Ini.ReadString('Language','2',''));
dann hab ich ja später das problem, dass ich die anderen beim laden in die combo auch manuel angeben muß .
oder habt ihr da ne idee ?

Hawkeye219 11. Mai 2006 12:59

Re: multilingual mit ini datei ?
 
Hallo,

ich weiß nicht, ob ich dein Problem richtig verstanden habe. Vielleicht suchst du so etwas:

Code:
[Languages]
Count=3
1=Deutsch
2=English
3=Dialekt
Mit diesem Abschnitt in der .ini-Datei kannst du sowohl die Anzahl, als auch die Namen der Sprachen einlesen:

Delphi-Quellcode:
Count := Ini.ReadInteger('Languages', 'Count', 0);
for i := 1 to Count do
  CBLang.Items.Add(Ini.ReadString('Languages', IntToStr(i), '(noname)'));
Gruß Hawkeye

agm65 11. Mai 2006 13:01

Re: multilingual mit ini datei ?
 
ja genau das könnte die lösung meines problems sein ..ich teste es direkt

agm65 11. Mai 2006 13:16

Re: multilingual mit ini datei ?
 
danke funtzt

hitzi 11. Mai 2006 13:59

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:

[Language File Information]
Creator_Name=Thomas
LanguageID=$00000405

[Main Window]
Button_Close=Close
Button_Options_CheckNow=Check now

... u.s.w. ...
- über das Auslesen alle Languagedateien aus dem Verzeichnis und der LanguageID kann ich ganz leicht ne Combobox füllen lassen mit allen vorhandenen Sprachen

- 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:
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;
(Aufbau von GetLocalizedString: 1. Parameter = Section; 2. Parameter = Ident; 3. Parameter = Standardwert)
- 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

Sharky 11. Mai 2006 15:00

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:
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;
und so die INI für diesen Fall:
Code:
[TEdit-Text]
Edit1=Ein Text
Edit2=noch einer
Edit3=
Edit4=*blubb*
[TLabel-Caption]
Label1=Ich bin ein Label
Label2=Ich auch
Label3=*blubb*
Der Vorteil ist das ich nicht für jedes Label und jeden Button usw. aus der INI lesen muss.

Im Angang mal ein DemoProjekt. Zur Zeit bin ich noch daran die Funktion in eine eigene Klasse zu wuchten.

Bernhard Geyer 11. Mai 2006 20:28

Re: multilingual mit ini datei ?
 
Zitat:

Zitat von agm65
hallo leute, also ich wollte mein programm möglichst multilingual machen.

Schon mal GNU Gettext angeschaut?

renekr 25. Mai 2006 20:26

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:
LMDExplorerbar1.Section[0].Items[0].caption:='test';
Nun wie bekomme ich die verschiedenen Section udn items mit in deine Version rein.
Das selbe bei TStatusbar.panels[0].caption.


Danke.

bluescreen25 25. Jul 2007 21:09

Re: multilingual mit ini datei ?
 
Zitat:

Zitat von Sharky
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:
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;
und so die INI für diesen Fall:
Code:
[TEdit-Text]
Edit1=Ein Text
Edit2=noch einer
Edit3=
Edit4=*blubb*
[TLabel-Caption]
Label1=Ich bin ein Label
Label2=Ich auch
Label3=*blubb*
Der Vorteil ist das ich nicht für jedes Label und jeden Button usw. aus der INI lesen muss.

Im Angang mal ein DemoProjekt. Zur Zeit bin ich noch daran die Funktion in eine eigene Klasse zu wuchten.

Das funktioniert prima, gerade bei einem kleinen Project eine gute Stütze.

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

Sharky 26. Jul 2007 14:11

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:
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;
Und dann so aufrufen:
Delphi-Quellcode:
  WriteIni(self, TEdit, 'Text');
  WriteIni(self, TLabel, 'Caption');
  WriteIni(self, TButton, 'Caption');
  WriteIni(self, TLabeledEdit,TBoundLabel, 'Caption');
Das musst Du jetzt nur noch für WriteIni umsetzen und dann sollte es gehen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:37 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz