Lokalisierung

Aus DGL Wiki
Version vom 26. Juli 2006, 11:14 Uhr von The-Winner (Diskussion | Beiträge) (Erste Zwischenspeicherung, Unvollständig!)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

Lokalisierung

Allgemein

Als Lokalisirung bezeichnet man den Vorgang eine Software in verschiedene Sprachen zu übersetzen.

Anforderungen

  • Einfach einzusetzen
  • Software kann auch nach dem Übersetzen noch verändert werden
  • Auch bei anderem Satzbau noch verwendbar

Ansätze

  • Formularresourcen (Borland)
    Nachteil: Es ist schwer das Formular nach dem Übersetzen noch anzupassen und es wird bei sonstigen Texten keine Unterstüzung geboten
  • Programm das im Quelltext alle Strings suchen unt ersetzen kann
    Nachteil: Es gibt viele nicht zu übersetzende Strings, Programm muss für jede Spreche kompiliert werden
  • Übersetzungsfunktion:
    Vorteil: Kann überall im Quelltext eingesetzt werden
    Nachteil: Jeder zu übersetzende String muss an diese Funktion übergeben werden

Einfaches Übersetzungssystem

Hier werde ich den 3. Ansatz implementieren: eine Übersetzungsfunktion

unit Translator;
interface

Function Translate(const Name: string; const Args: array of const): string;overload;
Function Translate(const Name: string): string;overload;

procedure LoadLanguage(const Lang:String);
function CurrentLanguage:String;

implementation
uses sysutils,classes;

var langdata:TStringlist;
    CurLang:String;
Function Translate(const Name: string; const Args: array of const): string;overload;
begin
 result:=format(translate(Name),Args);
end;

Function Translate(const Name: string): string;overload;
var i:integer;
begin
 langdata.find(Name+'=',i);
 if (i<langdata.count)and(copy(langdata[i],1,length(Name)+1)=Name+'=')
  then result:=Copy(langdata[i], Length(Name) + 2, MaxInt)
  else raise exception.create('String not translated: "'+Name+'"');
 result:=stringreplace(result,'\r',#13,[rfReplaceAll]);
 result:=stringreplace(result,'\n',#10,[rfReplaceAll]);
 result:=stringreplace(result,'\\','\',[rfReplaceAll]);
end;

procedure LoadLanguage(const Lang:String);
begin
 CurLang:=lowercase(Lang);
 langdata.loadfromfile(changefileext(paramstr(0),'.'+CurLang));
end;

function CurrentLanguage:String;
begin
 result:=CurLang;
end;

initialization
 langdata:=TStringlist.create;
 langdata.sorted:=true;
finalization
 langdata.free;
end.
unit TranslatorVCL;

interface
uses classes,translator,controls,menus,actnlist,sysutils,comctrls,stdctrls;
Procedure Translate(const Component:TComponent;Path:String='');overload;
procedure CreateTranslationTable(const Component:TComponent;const Filename:String);
implementation
Type TMyControl=class(TControl);

Procedure Translate(const Component:TComponent;Path:String='');overload;
var i:integer;
begin
 //Pfad anpassen
 if Path=''
  then Path:=Component.Name
  else Path:=Path+'.'+Component.Name;
 //Eigenschaften übersetzen
 if (Component is TControl)and(TMyControl(Component).Caption<>'')then TMyControl(Component).Caption:=Translate(Path+'.Caption');
 if (Component is TControl)and(TControl(Component).Hint<>'')then TMyControl(Component).Hint:=Translate(Path+'.Hint');
 if (Component is TMenuItem)and(TMenuItem(Component).Caption<>'')and(TMenuItem(Component).Action=nil)then TMenuItem(Component).Caption:=Translate(Path+'.Caption');
 if (Component is TMenuItem)and(TMenuItem(Component).Hint<>'')and(TMenuItem(Component).Action=nil)then TMenuItem(Component).Hint:=Translate(Path+'.Hint');
 if (Component is TCustomAction)and(TCustomAction(Component).Caption<>'')then TCustomAction(Component).Caption:=Translate(Path+'.Caption');
 if (Component is TCustomAction)and(TCustomAction(Component).Hint<>'')then TCustomAction(Component).Hint:=Translate(Path+'.Hint');
 if (Component is TTabControl)and(TTabControl(Component).Tabs.text<>'')then TTabControl(Component).Tabs.text:=Translate(Path+'.Tabs');
 if (Component is TCustomComboBox)and(TCustomComboBox(Component).items.text<>'')then TCustomComboBox(Component).items.text:=Translate(Path+'.Items');
 if (Component is TCustomListBox)and(TCustomListBox(Component).items.text<>'')then TCustomListBox(Component).items.text:=Translate(Path+'.Items');
 //Unterkomponenten übersetzen
 for i:=0 to Component.ComponentCount-1do
  Translate(Component.Components[i],Path);
end;

procedure CreateTranslationTable(const Component:TComponent;const Filename:String);
var List:TStringlist;
   function Escape(const S:String):String;
   begin
    result:=S;
    result:=stringreplace(result,'\','\\',[rfReplaceAll]);
    result:=stringreplace(result,#13,'\r',[rfReplaceAll]);
    result:=stringreplace(result,#10,'\n',[rfReplaceAll]);
   end;

   procedure AddComponent(const Component:TComponent;Path:String);
   var i:integer;
   begin
    //Pfad anpassen
    if Path=''
     then Path:=Component.Name
     else Path:=Path+'.'+Component.Name;
    //Eigenschaften speichern
    if (Component is TControl)and(TMyControl(Component).Caption<>'')then List.add(Path+'.Caption='+Escape(TMyControl(Component).Caption));
    if (Component is TControl)and(TControl(Component).Hint<>'')then List.add(Path+'.Hint='+Escape(TMyControl(Component).Hint));
    if (Component is TMenuItem)and(TMenuItem(Component).Caption<>'')and(TMenuItem(Component).Action=nil)then List.add(Path+'.Caption='+Escape(TMenuItem(Component).Caption));
    if (Component is TMenuItem)and(TMenuItem(Component).Hint<>'')and(TMenuItem(Component).Action=nil)then List.add(Path+'.Hint='+Escape(TMenuItem(Component).Hint));
    if (Component is TCustomAction)and(TCustomAction(Component).Caption<>'')then List.add(Path+'.Caption='+Escape(TCustomAction(Component).Caption));
    if (Component is TCustomAction)and(TCustomAction(Component).Hint<>'')then List.add(Path+'.Hint='+Escape(TCustomAction(Component).Hint));
    if (Component is TTabControl)and(TTabControl(Component).Tabs.text<>'')then List.add(Path+'.Tabs='+Escape(TTabControl(Component).Tabs.text));
    if (Component is TCustomComboBox)and(TCustomComboBox(Component).Items.text<>'')then List.add(Path+'.Items='+Escape(TCustomComboBox(Component).Items.text));
    if (Component is TCustomListBox)and(TCustomListBox(Component).Items.text<>'')then List.add(Path+'.Items='+Escape(TCustomListBox(Component).Items.text));
    //Unterkomponenten speichern
    for i:=0 to Component.ComponentCount-1do
     AddComponent(Component.Components[i],Path);
   end;
begin
 List:=TStringlist.create;
 try
  AddComponent(Component,'');
  List.SaveToFile(Filename);
 finally
  List.free;
 end;
end;

end.