unit ULanguage;
{ ********************************************************************************* }
{ (c) GNU                                                                           }
{ author: Heiko Tietze                                                              }
{ version: 1.0                                                                      }
{ date: 11.12.2004                                                                  }
{ description: unit to change language from ini file; SetLanguage changes all       }
{              captions by reading the value from ini file by name of component;    }
{              procedure Translate(<string>) tries to read complement from ini      }
{ ********************************************************************************* }

{$I Def.inc}

interface

uses {$IFDEF VCL}
     Controls, Forms, StdCtrls, ExtCtrls, Graphics, ComCtrls, Dialogs,
     ImgList, Menus, Grids, ToolWin, ActnList,Buttons,
     {$ELSE}
     QControls, QForms, QStdCtrls, QExtCtrls, QGraphics, QComCtrls,
     QTypes, QDialogs, QImgList, QMenus, QGrids, QActnList,
     {$ENDIF}
     Classes, IniFiles, TypInfo, SysUtils;

type TLanguage=class
        private
          FCurrentLanguage : string;
          FIni : TIniFile;
          function HasProperty(comp:TComponent;prop:string):boolean;
          function GetProp(Comp:TComponent;Prop:string):string;
          procedure SetProp(comp:TComponent;const prop,value:string);
          procedure SetLanguage(const Value : string);
          function GetTranslation(Value: string): string;
        published
          constructor Create(const DefaultLanguage:string='english');
          destructor Destroy;override;
        public
          property CurrentLanguage:string read FCurrentLanguage write SetLanguage;
          property Translate[index:string]:string read GetTranslation;
        end;

var Language : TLanguage;

implementation

{ --- TLanguage --- }

constructor TLanguage.Create(const DefaultLanguage:string='english');
begin
  inherited Create;
  CurrentLanguage:=DefaultLanguage;
end;

destructor TLanguage.Destroy;
begin
  FIni.Free;
  inherited;
end;

function TLanguage.GetProp(Comp:TComponent;Prop:string):string;
var pi:PPropInfo;
begin
	pi:=GetPropInfo(Comp.ClassInfo,Prop);
  if pi<>nil then Result:=GetStrProp(Comp,pi)
             else Result:='';
end;

procedure TLanguage.SetProp(Comp:TComponent;const Prop,Value:string);
var pi:PPropInfo;
begin
	if Value<>'' then
  begin
   	pi:=GetPropInfo(Comp.ClassInfo,Prop);
    if pi<>nil then SetStrProp(Comp,pi,Value);
  end;
end;

function TLanguage.HasProperty(Comp:TComponent;Prop:string):boolean;
begin
	Result:=(GetPropInfo(Comp.classInfo,Prop)<>nil) and (Comp.Name<>'');
end;

procedure TLanguage.SetLanguage(const Value: string);
var i,j,k:integer;
    ParentComp,Comp:TComponent;
    s:string;
begin
   if (Value<>FCurrentLanguage) and (Value<>'') and (Value<>' ') then
   begin
     FIni.Free;
     FIni:=TIniFile.Create(ExtractFilePath(Application.ExeName)+Value+'.lang');
     for i:=0 to Application.ComponentCount-1 do
     begin
   	   ParentComp:=Application.Components[i];
       if HasProperty(ParentComp,'Caption') then //and not (ParentComp.Name=getProp(ParentComp,'Caption')) then
       begin
          s:=FIni.ReadString(Value,ParentComp.Name+'.Caption','');
          if s='' then
          begin
            s:=getProp(ParentComp,'Caption');
            FIni.WriteString(Value,ParentComp.Name+'.Caption',s);
          end;
          SetProp(ParentComp,'Caption',s);
       end;

       for j:=0 to ParentComp.ComponentCount-1 do
       begin
         Comp:=ParentComp.Components[j];
         if HasProperty(Comp,'Caption') and
            not (getProp(Comp,'Caption')='-') and
            not (getProp(Comp,'Caption')='') then
         begin
           s:=FIni.ReadString(Value,Comp.Name+'.Caption', '');
           if s='' then
           begin
              s:=getProp(Comp,'Caption');
              FIni.WriteString(Value,Comp.Name+'.Caption', s);
           end;
           SetProp(Comp,'Caption',s);
         end;

         if HasProperty(Comp,'Hint') and (getProp(Comp,'Hint')<>'') then
         begin
            s:=FIni.ReadString(Value,Comp.Name+'.Hint','');
            if s='' then
            begin
              s:=getProp(Comp,'Hint');
              FIni.WriteString(Value,Comp.Name+'.Hint',s);
            end;
            SetProp(Comp,'Hint',s);
         end;

         if (Comp is TRadioGroup) then
           for k:=0 to TRadioGroup(Comp).Items.Count-1 do
           begin
              s:=FIni.ReadString(Value,Comp.Name+'.Items['+IntToStr(k)+']','');
              if s='' then
              begin
                 s:=TRadioGroup(Comp).Items[k];
                 FIni.WriteString(Value,Comp.Name+'.Items['+IntToStr(k)+']',s);
              end;
              (Comp as TRadioGroup).Items[k]:=s;
           end;
       end; //for j
     end;//for i
     FCurrentLanguage:=Value;
   end;
end;

function TLanguage.GetTranslation(Value: string): string;
begin
  Result:=FIni.ReadString(FCurrentLanguage, Value, '');
  if Result='' then
  begin
    FIni.WriteString(FCurrentLanguage, Value, Value);
    Result:=Value;
  end;
end;

end.
