Mehrere Sprachen im Programm

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Giantics
Beiträge: 88
Registriert: Sa 3. Mär 2007, 13:46
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Langenbrettach

Beitrag von Giantics »

Habe eine Möglichkeit gefunden, wie sich die Captions automatisch aus den po-Dateien übersetzen lassen ohne dass dazu Resourcenstring gebraucht werden.

Allerdings habe ich das Problem (Laz 0.9.25 20080722), dass nur von einem Formular die Strings in die po-Datei übertragen werden.
Laut der Seite http://wiki.lazarus.freepascal.org/Tran ... rograms/de" onclick="window.open(this.href);return false; sollten alle Formulardaten zusammen in die po-Datei geschrieben werden.
Bei mir passiert das allerdings nicht. Er nimmt immer nur das zuletzt geöffnete und löscht die anderen dann wieder.

Habt ihr dafür eine Lösung gefunden?

Gruß
Thomas

Bernd
Beiträge: 27
Registriert: Mo 11. Jun 2007, 10:12
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Beitrag von Bernd »

Hallo
Für meine kleinen Programme suche ich auch eine einfache Lösung eine mehrsprachige Nutzeroberfläche hinzubekommen.
Der Hinweis mit der i18N Einstellung im Projekt war sehr hilfreich. Mit den Resourcen Strings geht das auch sehr gut, aber alle Komponenten (Captions) mittels dieser Strings an die Sprache anzupassen erschien mir zu umständlich, zumal diese ja bereits im .po File landen und bei Programmänderungen auch in allen .po Files angepasst werden.

Ich habe mir eine Funktion, ähnlich wie in der Unit Translation, geschrieben die dies für alle Einträge macht.

Code: Alles auswählen

function TForm1.TranslateUnitCaptionStrings(const ResUnitName, AFilename: string): boolean;
var
  TableID,TableCount: Integer;
  s       : String;
  t       : String;
  ap      : String;
  captext : String;
  DefValue: String;
  po      : TPOFile;
  aForm   : TForm;
 
  CurrentComponent : TComponent;
 
begin
  Result:=false;
  if (ResUnitName='') or (AFilename='') or (not FileExists(AFilename)) then
    exit;
  try
    po := nil;
    po := TPOFile.Create(AFilename);
    aForm := self;
    try
      TableCount := Pred(aForm.ComponentCount);
      for  TableID := 0 to TableCount  do
      begin
        CurrentComponent := aForm.Components[TableID];
        DefValue:= CurrentComponent.GetNamePath;
        if DefValue[1] = 'E' then ap := 'TEXT' else ap :='CAPTION';
        t := aForm.ClassName+'.'+CurrentComponent.GetNamePath+'.'+ap;
        captext  := po.Translate(t,DefValue);
        if captext <> DefValue then
        SetWideStrProp(CurrentComponent,ap, captext);
      end;
    finally
      po.Free;
    end;
    Result:=true;
  except
    on e: Exception do begin
    // Fehlermeldung
    end;
  end;
end;
Ist sicher noch nicht so ausgereift, kann also nur ein Ansatz sein.

Eventuell kann man darauf aufsetzen. Anbei mein Beispiel

Gruss Bernd
Dateianhänge
Potest.zip
(70.84 KiB) 67-mal heruntergeladen

Giantics
Beiträge: 88
Registriert: Sa 3. Mär 2007, 13:46
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Langenbrettach

Beitrag von Giantics »

So ähnlich sieht meine Variante auch aus.

Code: Alles auswählen

procedure PassComponents(po: TPOFile; aComponent: TComponent);
var
  i,k: Integer;
  comp: TComponent;
begin
  for i:=0 to aComponent.ComponentCount-1 do
  begin
    comp := aComponent.Components[i];
    if comp is TControl then
    begin
      TControl(comp).Caption := po.Translate(TControl(comp).Caption, TControl(comp).Caption);
      TControl(comp).Hint    := po.Translate(TControl(comp).Hint   , TControl(comp).Hint);
    end;
    if comp is TMenuItem then
      TMenuItem(comp).Caption := po.Translate(TMenuItem(comp).Caption, TMenuItem(comp).Caption);
    (*if comp is TListView then
      for k:=0 to TListView(comp).Columns.Count-1 do
        TListView(comp).Columns[k].Caption :=
          po.Translate(TListView(comp).Columns[k].Caption, TListView(comp).Columns[k].Caption);*)
    PassComponents(po, aComponent.Components[i]);
  end;
end;
 
procedure TranslateAll;
var
  PODirectory, Lang, FallbackLang: String;
  po : TPOFile;
begin
  PODirectory := strBinDir + '../languages/';    // change that for release
  GetLanguageIDs(Lang, FallbackLang); // in unit gettext
  TranslateUnitResourceStrings('UnitMain', PODirectory + 'easymp3gain.%s.po', Lang, FallbackLang);
  TranslateUnitResourceStrings('UnitMediaGain', PODirectory + 'easymp3gain.%s.po', Lang, FallbackLang);
  if FileExists(PODirectory+'easymp3gain.'+FallbackLang+'.po') then
  begin
    po := TPOFile.Create(PODirectory+'easymp3gain.'+FallbackLang+'.po');
    try
      PassComponents(po,frmMP3GainMain);
      PassComponents(po,frmMP3GainConstant);
      PassComponents(po,frmMP3GainConsoleOutput);
      PassComponents(po,frmMP3GainGUIInfo);
    finally
      po.Free;
    end;
  end;
end;
Jedoch habe ich nachwievor das Problem, dass die Captions und Texte immer nur von einer Form in die po-Datei geschrieben werden. Die Captions und Texte der anderen Forms werden jedes Mal gelöscht:-( Funktioniert das bei dir korrekt?

Bernd
Beiträge: 27
Registriert: Mo 11. Jun 2007, 10:12
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Beitrag von Bernd »

Nein es geht eigentlich nur mit einer Unit richtig. Schade :(

Antworten