unit uutlLocalization; { Package: Utils Prefix: utl - UTiLs Beschreibung: diese Unit stellt Mechanismen zur Übersetzung von Texten mit Hilfe von PO/MO-Files zur Verfügung } {$mode objfpc}{$H+} interface uses Classes, SysUtils, gettext, uutlCommon, uutlGenerics, uutlStreamHelper; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TutlLocalizationItem = class(TObject) Name, Comment: String; constructor Create; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TutlLocalizationDatabase = class(TObject) private type TStringObjMap = specialize TutlMap; private fStringList: TStringObjMap; fLangFile: TMOFile; function GetCount: Integer; function GetObject(Index: Integer): TutlLocalizationItem; public property Count : Integer read GetCount; property Objects[Index: Integer]: TutlLocalizationItem read GetObject; function AddName(const Name, Comment: string): TutlLocalizationItem; function RemoveName(const Name: string): boolean; procedure LoadFromStream(const aStream: TStream); procedure SaveToStream(const aStream: TStream); procedure LoadLanguage(const aStream: TStream); function Translate(const Name: string): string; constructor Create; destructor Destroy; override; end; function utlLocalizationDatabase: TutlLocalizationDatabase; function __(Name: string; Default: string = #0): string; overload; implementation uses Dialogs, uvfsManager; var Entity: TutlLocalizationDatabase; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function utlLocalizationDatabase: TutlLocalizationDatabase; var str: IStreamHandle; begin if not Assigned(Entity) then begin Entity := TutlLocalizationDatabase.Create; if vfsManager.ReadFile('lang/strings', str) then Entity.LoadFromStream(str.GetStream); end; result := Entity; end; function __(Name: string; Default: string): string; begin if Default=#0 then Default := Name; Result := utlLocalizationDatabase.Translate(Name); if (Result = '') then Result := Default; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TutlLocalizationItem//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //erstellt das Objekt constructor TutlLocalizationItem.Create; begin inherited Create; Name := ''; Comment := ''; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TutlLocalizationDatabase/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Get-Methode der Count-Eigenschaft function TutlLocalizationDatabase.GetCount: Integer; begin result := fStringList.Count; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Get-Methode der Value-Eigenschaft function TutlLocalizationDatabase.GetObject(Index: Integer): TutlLocalizationItem; begin if (Index >= 0) and (Index < fStringList.Count) then result := fStringList.ValueAt[Index] else result := nil; end; function TutlLocalizationDatabase.AddName(const Name, Comment: string): TutlLocalizationItem; var e: TutlLocalizationItem; i: Integer; begin i := fStringList.IndexOf(Name); if i >= 0 then Result:= Objects[i] else begin e := TutlLocalizationItem.Create; e.Name := Name; e.Comment := Comment; fStringList.Add(e.Name, e); result := e; end; end; function TutlLocalizationDatabase.RemoveName(const Name: string): boolean; begin Result:= fStringList.IndexOf(Name) >= 0; if Result then fStringList.Delete(Name); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //läd die Datenbank aus einem Stream //@aStream: Stream aus der geladen werden soll; procedure TutlLocalizationDatabase.LoadFromStream(const aStream: TStream); const HEADER = 'StringDatabase'; var rd: TutlStreamReader; csv: TutlCSVList; co: string; begin rd:= TutlStreamReader.Create(aStream); try if HEADER <> rd.ReadLine then raise Exception.Create('TStringDatabase.LoadFromStream - invalid Stream'); fStringList.Clear; csv:= TutlCSVList.Create; try csv.Delimiter:= ';'; csv.StrictDelimitedText:= rd.ReadLine; while csv.Count>=1 do begin co:= ''; if csv.Count>1 then co:= csv[1]; AddName(csv[0],co); // next line csv.StrictDelimitedText:= rd.ReadLine; end; finally FreeAndNil(csv); end; finally FreeAndNil(rd); end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //speichert die Datenbank in einem Stream //@aStream: Stream in dem gespeichert werden soll; procedure TutlLocalizationDatabase.SaveToStream(const aStream: TStream); const HEADER = 'StringDatabase'; var i: Integer; wr: TutlStreamWriter; csv: TutlCSVList; o: TutlLocalizationItem; begin wr:= TutlStreamWriter.Create(aStream); try wr.WriteLine(HEADER); csv:= TutlCSVList.Create; try csv.Delimiter:= ';'; for i := 0 to fStringList.Count-1 do begin csv.Clear; o:= Objects[i]; csv.Add(o.Name); csv.Add(o.Comment); wr.WriteLine(csv.StrictDelimitedText); end; finally FreeAndNil(csv); end; finally FreeAndNil(wr); end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlLocalizationDatabase.LoadLanguage(const aStream: TStream); begin fLangFile.Free; fLangFile := nil; fLangFile := TMOFile.Create(aStream); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TutlLocalizationDatabase.Translate(const Name: string): string; begin if Assigned(fLangFile) then Result := UTF8Encode(fLangFile.Translate(Name)) else Result := ''; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //erstellt das Objekt constructor TutlLocalizationDatabase.Create; begin inherited Create; fStringList := TStringObjMap.Create(True); fLangFile := nil; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //gibt das Objekt frei destructor TutlLocalizationDatabase.Destroy; begin fLangFile.Free; fStringList.Free; inherited Destroy; end; finalization FreeAndNil(Entity); end.