Index: /trunk/CoolDisk.lpi
===================================================================
--- /trunk/CoolDisk.lpi	(revision 39)
+++ /trunk/CoolDisk.lpi	(revision 40)
@@ -153,4 +153,5 @@
       <Item1>
         <PackageName Value="CoolTranslator"/>
+        <DefaultFilename Value="Packages/CoolTranslator/CoolTranslator.lpk" Prefer="True"/>
       </Item1>
       <Item2>
Index: /trunk/Packages/Common/Common.lpk
===================================================================
--- /trunk/Packages/Common/Common.lpk	(revision 39)
+++ /trunk/Packages/Common/Common.lpk	(revision 40)
@@ -4,4 +4,5 @@
     <PathDelim Value="\"/>
     <Name Value="Common"/>
+    <Type Value="RunAndDesignTime"/>
     <AddToProjectUsesSection Value="True"/>
     <Author Value="Chronos (robie@centrum.cz)"/>
@@ -109,14 +110,17 @@
       <EnableI18N Value="True"/>
       <OutDir Value="Languages"/>
+      <EnableI18NForLFM Value="True"/>
     </i18n>
-    <Type Value="RunAndDesignTime"/>
-    <RequiredPkgs Count="2">
+    <RequiredPkgs Count="3">
       <Item1>
-        <PackageName Value="TemplateGenerics"/>
+        <PackageName Value="LCL"/>
       </Item1>
       <Item2>
+        <PackageName Value="TemplateGenerics"/>
+      </Item2>
+      <Item3>
         <PackageName Value="FCL"/>
         <MinVersion Major="1" Valid="True"/>
-      </Item2>
+      </Item3>
     </RequiredPkgs>
     <UsageOptions>
Index: /trunk/Packages/Common/Languages/UJobProgressView.po
===================================================================
--- /trunk/Packages/Common/Languages/UJobProgressView.po	(revision 39)
+++ /trunk/Packages/Common/Languages/UJobProgressView.po	(revision 40)
@@ -14,4 +14,8 @@
 msgstr ""
 
+#: ujobprogressview.soperations
+msgid "Operations"
+msgstr ""
+
 #: ujobprogressview.spleasewait
 msgid "Please wait..."
Index: /trunk/Packages/Common/UCommon.pas
===================================================================
--- /trunk/Packages/Common/UCommon.pas	(revision 39)
+++ /trunk/Packages/Common/UCommon.pas	(revision 40)
@@ -6,5 +6,6 @@
 
 uses
-  {$IFDEF Windows}Windows,{$ENDIF}
+  {$ifdef Windows}Windows,{$endif}
+  {$ifdef Linux}baseunix,{$endif}
   Classes, SysUtils, StrUtils, Dialogs, Process, LCLIntf,
   FileUtil; //, ShFolder, ShellAPI;
@@ -65,4 +66,8 @@
 procedure FreeThenNil(var Obj);
 function RemoveQuotes(Text: string): string;
+function ComputerName: string;
+function OccurenceOfChar(What: Char; Where: string): Integer;
+function GetDirCount(Dir: string): Integer;
+function MergeArray(A, B: array of string): TArrayOfString;
 function LoadFileToStr(const FileName: TFileName): AnsiString;
 
@@ -288,5 +293,4 @@
   L: LongWord;
 begin
-
   L := MAX_USERNAME_LENGTH + 2;
   SetLength(Result, L);
@@ -303,5 +307,33 @@
   end;
 end;
-
+{$endif}
+
+function ComputerName: string;
+{$ifdef mswindows}
+const
+ INFO_BUFFER_SIZE = 32767;
+var
+  Buffer : array[0..INFO_BUFFER_SIZE] of WideChar;
+  Ret : DWORD;
+begin
+  Ret := INFO_BUFFER_SIZE;
+  If (GetComputerNameW(@Buffer[0],Ret)) then begin
+    Result := UTF8Encode(WideString(Buffer));
+  end
+  else begin
+    Result := 'ERROR_NO_COMPUTERNAME_RETURNED';
+  end;
+end;
+{$endif}
+{$ifdef unix}
+var
+  Name: UtsName;
+begin
+  fpuname(Name);
+  Result := Name.Nodename;
+end;
+{$endif}
+
+{$ifdef windows}
 function LoggedOnUserNameEx(Format: TUserNameFormat): string;
 const
@@ -418,21 +450,6 @@
 
 procedure OpenWebPage(URL: string);
-var
-  Process: TProcess;
-  Browser, Params: string;
 begin
   OpenURL(URL);
-  {try
-    Process := TProcess.Create(nil);
-    Browser := '';
-    //FindDefaultBrowser(Browser, Params);
-    //Process.Executable := Browser;
-    //Process.Parameters.Add(Format(Params, [ApplicationInfo.HomePage]);
-    Process.CommandLine := 'cmd.exe /c start ' + URL;
-    Process.Options := [poNoConsole];
-    Process.Execute;
-  finally
-    Process.Free;
-  end;}
 end;
 
@@ -447,4 +464,31 @@
   if (Pos('"', Text) = 1) and (Text[Length(Text)] = '"') then
     Result := Copy(Text, 2, Length(Text) - 2);
+end;
+
+function OccurenceOfChar(What: Char; Where: string): Integer;
+var
+  I: Integer;
+begin
+  Result := 0;
+  for I := 1 to Length(Where) do
+    if Where[I] = What then Inc(Result);
+end;
+
+function GetDirCount(Dir: string): Integer;
+begin
+  Result := OccurenceOfChar(DirectorySeparator, Dir);
+  if Copy(Dir, Length(Dir), 1) = DirectorySeparator then
+    Dec(Result);
+end;
+
+function MergeArray(A, B: array of string): TArrayOfString;
+var
+  I: Integer;
+begin
+  SetLength(Result, Length(A) + Length(B));
+  for I := 0 to Length(A) - 1 do
+    Result[I] := A[I];
+  for I := 0 to Length(B) - 1 do
+    Result[Length(A) + I] := B[I];
 end;
 
@@ -467,4 +511,6 @@
 end;
 
+
+
 initialization
 
Index: /trunk/Packages/Common/UFindFile.pas
===================================================================
--- /trunk/Packages/Common/UFindFile.pas	(revision 39)
+++ /trunk/Packages/Common/UFindFile.pas	(revision 40)
@@ -55,4 +55,12 @@
   end;
 
+const
+{$IFDEF WINDOWS}
+  FilterAll = '*.*';
+{$ENDIF}
+{$IFDEF LINUX}
+  FilterAll = '*';
+{$ENDIF}
+
 procedure Register;
 
@@ -71,5 +79,5 @@
   inherited Create(AOwner);
   Path := IncludeTrailingBackslash(UTF8Encode(GetCurrentDir));
-  FileMask := '*.*';
+  FileMask := FilterAll;
   FileAttr := [ffaAnyFile];
   s := TStringList.Create;
@@ -127,5 +135,5 @@
   If not InSubFolders then Exit;
 
-  if SysUtils.FindFirst(UTF8Decode(inPath + '*.*'), faDirectory, Rec) = 0 then
+  if SysUtils.FindFirst(UTF8Decode(inPath + FilterAll), faDirectory, Rec) = 0 then
   try
     repeat
Index: /trunk/Packages/Common/UJobProgressView.lfm
===================================================================
--- /trunk/Packages/Common/UJobProgressView.lfm	(revision 39)
+++ /trunk/Packages/Common/UJobProgressView.lfm	(revision 40)
@@ -14,5 +14,5 @@
   OnDestroy = FormDestroy
   Position = poScreenCenter
-  LCLVersion = '1.1'
+  LCLVersion = '1.6.0.4'
   object PanelOperationsTitle: TPanel
     Left = 0
Index: /trunk/Packages/Common/UJobProgressView.lrt
===================================================================
--- /trunk/Packages/Common/UJobProgressView.lrt	(revision 39)
+++ /trunk/Packages/Common/UJobProgressView.lrt	(revision 40)
@@ -1,3 +1,3 @@
-TJOBPROGRESSVIEW.LABELOPERATION.CAPTION=Operations:
-TJOBPROGRESSVIEW.LABELESTIMATEDTIMEPART.CAPTION=Estimated time:
-TJOBPROGRESSVIEW.LABELESTIMATEDTIMETOTAL.CAPTION=Total estimated time:
+TFORMJOBPROGRESSVIEW.LABELOPERATION.CAPTION=Operations:
+TFORMJOBPROGRESSVIEW.LABELESTIMATEDTIMEPART.CAPTION=Estimated time:
+TFORMJOBPROGRESSVIEW.LABELESTIMATEDTIMETOTAL.CAPTION=Total estimated time:
Index: /trunk/Packages/Common/UJobProgressView.pas
===================================================================
--- /trunk/Packages/Common/UJobProgressView.pas	(revision 39)
+++ /trunk/Packages/Common/UJobProgressView.pas	(revision 40)
@@ -166,4 +166,5 @@
   STotalEstimatedTime = 'Total estimated time: %s';
   SFinished = 'Finished';
+  SOperations = 'Operations';
 
 procedure Register;
Index: /trunk/Packages/Common/UListViewSort.pas
===================================================================
--- /trunk/Packages/Common/UListViewSort.pas	(revision 39)
+++ /trunk/Packages/Common/UListViewSort.pas	(revision 40)
@@ -9,5 +9,6 @@
 uses
   {$IFDEF Windows}Windows, CommCtrl, {$ENDIF}Classes, Graphics, ComCtrls, SysUtils,
-  Controls, DateUtils, Dialogs, SpecializedList, Forms, Grids, StdCtrls, ExtCtrls;
+  Controls, DateUtils, Dialogs, SpecializedList, Forms, Grids, StdCtrls, ExtCtrls,
+  LclIntf, LMessages, LclType, LResources;
 
 type
@@ -18,4 +19,6 @@
   TCompareEvent = function (Item1, Item2: TObject): Integer of object;
   TListFilterEvent = procedure (ListViewSort: TListViewSort) of object;
+
+  { TListViewSort }
 
   TListViewSort = class(TComponent)
@@ -28,4 +31,9 @@
     FColumn: Integer;
     FOrder: TSortOrder;
+    FOldListViewWindowProc: TWndMethod;
+    FOnColumnWidthChanged: TNotifyEvent;
+    procedure DoColumnBeginResize(const AColIndex: Integer);
+    procedure DoColumnResized(const AColIndex: Integer);
+    procedure DoColumnResizing(const AColIndex, AWidth: Integer);
     procedure SetListView(const Value: TListView);
     procedure ColumnClick(Sender: TObject; Column: TListColumn);
@@ -40,4 +48,7 @@
     procedure SetColumn(const Value: Integer);
     procedure SetOrder(const Value: TSortOrder);
+    {$IFDEF WINDOWS}
+    procedure NewListViewWindowProc(var AMsg: TMessage);
+    {$ENDIF}
   public
     List: TListObject;
@@ -58,4 +69,6 @@
     property OnCustomDraw: TLVCustomDrawItemEvent read FOnCustomDraw
       write FOnCustomDraw;
+    property OnColumnWidthChanged: TNotifyEvent read FOnColumnWidthChanged
+      write FOnColumnWidthChanged;
     property Column: Integer read FColumn write SetColumn;
     property Order: TSortOrder read FOrder write SetOrder;
@@ -69,8 +82,10 @@
     FStringGrid1: TStringGrid;
     procedure DoOnKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+    procedure DoOnResize(Sender: TObject);
   public
     constructor Create(AOwner: TComponent); override;
     procedure UpdateFromListView(ListView: TListView);
     function TextEntered: Boolean;
+    function TextEnteredCount: Integer;
     function TextEnteredColumn(Index: Integer): Boolean;
     function GetColValue(Index: Integer): string;
@@ -80,4 +95,5 @@
     property Align;
     property Anchors;
+    property BorderSpacing;
   end;
 
@@ -99,4 +115,9 @@
   if Assigned(FOnChange) then
     FOnChange(Self);
+end;
+
+procedure TListViewFilter.DoOnResize(Sender: TObject);
+begin
+  FStringGrid1.DefaultRowHeight := FStringGrid1.Height;
 end;
 
@@ -115,4 +136,5 @@
     goHorzLine, goRangeSelect, goEditing, goAlwaysShowEditor, goSmoothScroll];
   FStringGrid1.OnKeyUp := DoOnKeyUp;
+  FStringGrid1.OnResize := DoOnResize;
 end;
 
@@ -120,10 +142,9 @@
 var
   I: Integer;
-  NewColumn: TGridColumn;
 begin
   with FStringGrid1 do begin
-    Columns.Clear;
+    //Columns.Clear;
     while Columns.Count > ListView.Columns.Count do Columns.Delete(Columns.Count - 1);
-    while Columns.Count < ListView.Columns.Count do NewColumn := Columns.Add;
+    while Columns.Count < ListView.Columns.Count do Columns.Add;
     for I := 0 to ListView.Columns.Count - 1 do begin
       Columns[I].Width := ListView.Columns[I].Width;
@@ -133,12 +154,16 @@
 
 function TListViewFilter.TextEntered: Boolean;
+begin
+  Result := TextEnteredCount > 0;
+end;
+
+function TListViewFilter.TextEnteredCount: Integer;
 var
   I: Integer;
 begin
-  Result := False;
+  Result := 0;
   for I := 0 to FStringGrid1.ColCount - 1 do begin
     if FStringGrid1.Cells[I, 0] <> '' then begin
-      Result := True;
-      Break;
+      Inc(Result);
     end;
   end;
@@ -159,4 +184,53 @@
 { TListViewSort }
 
+{$IFDEF WINDOWS}
+procedure TListViewSort.NewListViewWindowProc(var AMsg: TMessage);
+var
+  vColWidth: Integer;
+  vMsgNotify: TLMNotify absolute AMsg;
+  Code: Integer;
+begin
+  // call the old WindowProc of ListView
+  FOldListViewWindowProc(AMsg);
+
+  // Currently we care only with WM_NOTIFY message
+  if AMsg.Msg = WM_NOTIFY then
+  begin
+    Code := PHDNotify(vMsgNotify.NMHdr)^.Hdr.Code;
+    case Code of
+      HDN_ENDTRACKA, HDN_ENDTRACKW:
+        DoColumnResized(PHDNotify(vMsgNotify.NMHdr)^.Item);
+
+      HDN_BEGINTRACKA, HDN_BEGINTRACKW:
+        DoColumnBeginResize(PHDNotify(vMsgNotify.NMHdr)^.Item);
+
+      HDN_TRACKA, HDN_TRACKW:
+        begin
+          vColWidth := -1;
+          if (PHDNotify(vMsgNotify.NMHdr)^.PItem<>nil)
+             and (PHDNotify(vMsgNotify.NMHdr)^.PItem^.Mask and HDI_WIDTH <> 0)
+          then
+            vColWidth := PHDNotify(vMsgNotify.NMHdr)^.PItem^.cxy;
+
+          DoColumnResizing(PHDNotify(vMsgNotify.NMHdr)^.Item, vColWidth);
+        end;
+    end;
+  end;
+end;
+{$ENDIF}
+
+procedure TListViewSort.DoColumnBeginResize(const AColIndex: Integer);
+begin
+end;
+
+procedure TListViewSort.DoColumnResizing(const AColIndex, AWidth: Integer);
+begin
+end;
+
+procedure TListViewSort.DoColumnResized(const AColIndex: Integer);
+begin
+  if Assigned(FOnColumnWidthChanged) then
+    FOnColumnWidthChanged(Self);
+end;
 
 procedure TListViewSort.ColumnClick(Sender: TObject; Column: TListColumn);
@@ -185,8 +259,15 @@
 procedure TListViewSort.SetListView(const Value: TListView);
 begin
+  if FListView = Value then Exit;
+  if Assigned(FListView) then
+    ListView.WindowProc := FOldListViewWindowProc;
   FListView := Value;
   FListView.OnColumnClick := ColumnClick;
   FListView.OnCustomDrawItem := ListViewCustomDrawItem;
   FListView.OnClick := ListViewClick;
+  FOldListViewWindowProc := FListView.WindowProc;
+  {$IFDEF WINDOWS}
+  FListView.WindowProc := NewListViewWindowProc;
+  {$ENDIF}
 end;
 
@@ -205,5 +286,5 @@
   if ListView.Items.Count <> List.Count then
     ListView.Items.Count := List.Count;
-  if Assigned(FOnCompareItem) then Sort(FOnCompareItem);
+  if Assigned(FOnCompareItem) and (Order <> soNone) then Sort(FOnCompareItem);
   //ListView.Items[-1]; // Workaround for not show first row if selected
   ListView.Refresh;
Index: /trunk/Packages/Common/UPersistentForm.pas
===================================================================
--- /trunk/Packages/Common/UPersistentForm.pas	(revision 39)
+++ /trunk/Packages/Common/UPersistentForm.pas	(revision 40)
@@ -8,5 +8,5 @@
 
 uses
-  Classes, SysUtils, Forms, URegistry, LCLIntf, Registry;
+  Classes, SysUtils, Forms, URegistry, LCLIntf, Registry, Controls, ComCtrls;
 
 type
@@ -19,4 +19,6 @@
     FMinVisiblePart: Integer;
     FRegistryContext: TRegistryContext;
+    procedure LoadControl(Control: TControl);
+    procedure SaveControl(Control: TControl);
   public
     FormNormalSize: TRect;
@@ -49,4 +51,66 @@
 
 { TPersistentForm }
+
+procedure TPersistentForm.LoadControl(Control: TControl);
+var
+  I: Integer;
+  WinControl: TWinControl;
+  Count: Integer;
+begin
+  if Control is TListView then begin
+    with Form, TRegistryEx.Create do
+    try
+      RootKey := RegistryContext.RootKey;
+      OpenKey(RegistryContext.Key + '\Forms\' + Form.Name + '\' + Control.Name, True);
+      for I := 0 to TListView(Control).Columns.Count - 1 do begin
+        if ValueExists('ColWidth' + IntToStr(I)) then
+          TListView(Control).Columns[I].Width := ReadInteger('ColWidth' + IntToStr(I));
+      end;
+    finally
+      Free;
+    end;
+  end;
+
+  if Control is TWinControl then begin
+    WinControl := TWinControl(Control);
+    if WinControl.ControlCount > 0 then begin
+      for I := 0 to WinControl.ControlCount - 1 do begin
+        if WinControl.Controls[I] is TControl then begin
+          LoadControl(WinControl.Controls[I]);
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TPersistentForm.SaveControl(Control: TControl);
+var
+  I: Integer;
+  WinControl: TWinControl;
+begin
+  if Control is TListView then begin
+    with Form, TRegistryEx.Create do
+    try
+      RootKey := RegistryContext.RootKey;
+      OpenKey(RegistryContext.Key + '\Forms\' + Form.Name + '\' + Control.Name, True);
+      for I := 0 to TListView(Control).Columns.Count - 1 do begin
+        WriteInteger('ColWidth' + IntToStr(I), TListView(Control).Columns[I].Width);
+      end;
+    finally
+      Free;
+    end;
+  end;
+
+  if Control is TWinControl then begin
+      WinControl := TWinControl(Control);
+      if WinControl.ControlCount > 0 then begin
+        for I := 0 to WinControl.ControlCount - 1 do begin
+          if WinControl.Controls[I] is TControl then begin
+            SaveControl(WinControl.Controls[I]);
+          end;
+        end;
+      end;
+    end;
+end;
 
 procedure TPersistentForm.LoadFromRegistry(RegistryContext: TRegistryContext);
@@ -181,4 +245,5 @@
       Form.BoundsRect := FormNormalSize;
   end;
+  LoadControl(Form);
 end;
 
@@ -191,4 +256,5 @@
   FormWindowState := Form.WindowState;
   SaveToRegistry(RegistryContext);
+  SaveControl(Form);
 end;
 
Index: /trunk/Packages/Common/UPrefixMultiplier.pas
===================================================================
--- /trunk/Packages/Common/UPrefixMultiplier.pas	(revision 39)
+++ /trunk/Packages/Common/UPrefixMultiplier.pas	(revision 40)
@@ -39,5 +39,5 @@
     (ShortText: 'n'; FullText: 'nano'; Value: 1e-9),
     (ShortText: 'u'; FullText: 'mikro'; Value: 1e-6),
-    (ShortText: 'm'; FullText: 'mili'; Value: 1-3),
+    (ShortText: 'm'; FullText: 'mili'; Value: 1e-3),
     (ShortText: ''; FullText: ''; Value: 1e0),
     (ShortText: 'k'; FullText: 'kilo'; Value: 1e3),
Index: /trunk/Packages/Common/UScaleDPI.pas
===================================================================
--- /trunk/Packages/Common/UScaleDPI.pas	(revision 39)
+++ /trunk/Packages/Common/UScaleDPI.pas	(revision 40)
@@ -17,7 +17,11 @@
   TControlDimension = class
     BoundsRect: TRect;
-    AuxSize: TPoint;
     FontHeight: Integer;
     Controls: TObjectList; // TList<TControlDimension>
+    // Class specifics
+    ButtonSize: TPoint; // TToolBar
+    CoolBandWidth: Integer;
+    ConstraintsMin: TPoint; // TForm
+    ConstraintsMax: TPoint; // TForm
     constructor Create;
     destructor Destroy; override;
@@ -74,5 +78,5 @@
 destructor TControlDimension.Destroy;
 begin
-  Controls.Free;
+  FreeAndNil(Controls);
   inherited Destroy;
 end;
@@ -113,9 +117,16 @@
   Dimensions.Controls.Clear;
   if Control is TToolBar then
-    Dimensions.AuxSize := Point(TToolBar(Control).ButtonWidth, TToolBar(Control).ButtonHeight);
-
+    Dimensions.ButtonSize := Point(TToolBar(Control).ButtonWidth, TToolBar(Control).ButtonHeight);
+  if Control is TForm then begin
+    Dimensions.ConstraintsMin := Point(TForm(Control).Constraints.MinWidth,
+      TForm(Control).Constraints.MinHeight);
+    Dimensions.ConstraintsMax := Point(TForm(Control).Constraints.MaxWidth,
+      TForm(Control).Constraints.MaxHeight);
+  end;
   if Control is TWinControl then
   for I := 0 to TWinControl(Control).ControlCount - 1 do begin
-    if TWinControl(Control).Controls[I] is TControl then begin
+    if TWinControl(Control).Controls[I] is TControl then
+    // Do not scale docked forms twice
+    if not (TWinControl(Control).Controls[I] is TForm) then begin
       NewControl := TControlDimension.Create;
       Dimensions.Controls.Add(NewControl);
@@ -133,10 +144,18 @@
   Control.Font.Height := Dimensions.FontHeight;
   if Control is TToolBar then begin
-    TToolBar(Control).ButtonWidth := Dimensions.AuxSize.X;
-    TToolBar(Control).ButtonHeight := Dimensions.AuxSize.Y;
+    TToolBar(Control).ButtonWidth := Dimensions.ButtonSize.X;
+    TToolBar(Control).ButtonHeight := Dimensions.ButtonSize.Y;
+  end;
+  if Control is TForm then begin
+    TForm(Control).Constraints.MinWidth := Dimensions.ConstraintsMin.X;
+    TForm(Control).Constraints.MinHeight := Dimensions.ConstraintsMin.Y;
+    TForm(Control).Constraints.MaxWidth := Dimensions.ConstraintsMax.X;
+    TForm(Control).Constraints.MaxHeight := Dimensions.ConstraintsMax.Y;
   end;
   if Control is TWinControl then
   for I := 0 to TWinControl(Control).ControlCount - 1 do begin
-    if TWinControl(Control).Controls[I] is TControl then begin
+    if TWinControl(Control).Controls[I] is TControl then
+    // Do not scale docked forms twice
+    if not (TWinControl(Control).Controls[I] is TForm) then begin
       RestoreDimensions(TWinControl(Control).Controls[I], TControlDimension(Dimensions.Controls[I]));
     end;
@@ -152,10 +171,27 @@
   Control.Font.Height := ScaleY(Dimensions.FontHeight, DesignDPI.Y);
   if Control is TToolBar then begin
-    TToolBar(Control).ButtonWidth := ScaleX(Dimensions.AuxSize.X, DesignDPI.X);
-    TToolBar(Control).ButtonHeight := ScaleY(Dimensions.AuxSize.Y, DesignDPI.Y);
+    TToolBar(Control).ButtonWidth := ScaleX(Dimensions.ButtonSize.X, DesignDPI.X);
+    TToolBar(Control).ButtonHeight := ScaleY(Dimensions.ButtonSize.Y, DesignDPI.Y);
+  end;
+  if Control is TCoolBar then begin
+    with TCoolBar(Control) do
+    for I := 0 to Bands.Count - 1 do
+    with TCoolBand(Bands[I]) do begin
+      MinWidth := ScaleX(Dimensions.ButtonSize.X, DesignDPI.X);
+      MinHeight := ScaleY(Dimensions.ButtonSize.Y, DesignDPI.Y);
+      //Width := ScaleX(Dimensions.BoundsRect.Left -
+    end;
+  end;
+  if Control is TForm then begin
+    TForm(Control).Constraints.MinWidth := ScaleX(Dimensions.ConstraintsMin.X, DesignDPI.X);
+    TForm(Control).Constraints.MaxWidth := ScaleX(Dimensions.ConstraintsMax.X, DesignDPI.X);
+    TForm(Control).Constraints.MinHeight := ScaleY(Dimensions.ConstraintsMin.Y, DesignDPI.Y);
+    TForm(Control).Constraints.MaxHeight := ScaleY(Dimensions.ConstraintsMax.Y, DesignDPI.Y);
   end;
   if Control is TWinControl then
   for I := 0 to TWinControl(Control).ControlCount - 1 do begin
-    if TWinControl(Control).Controls[I] is TControl then begin
+    if TWinControl(Control).Controls[I] is TControl then
+    // Do not scale docked forms twice
+    if not (TWinControl(Control).Controls[I] is TForm) then begin
       ScaleDimensions(TWinControl(Control).Controls[I], TControlDimension(Dimensions.Controls[I]));
     end;
@@ -183,11 +219,12 @@
 
   SetLength(Temp, ImgList.Count);
-  TempBmp := TBitmap.Create;
   for I := 0 to ImgList.Count - 1 do
   begin
+    TempBmp := TBitmap.Create;
+    TempBmp.PixelFormat := pf32bit;
     ImgList.GetBitmap(I, TempBmp);
-    //TempBmp.PixelFormat := pfDevice;
     Temp[I] := TBitmap.Create;
     Temp[I].SetSize(NewWidth, NewHeight);
+    Temp[I].PixelFormat := pf32bit;
     Temp[I].TransparentColor := TempBmp.TransparentColor;
     //Temp[I].TransparentMode := TempBmp.TransparentMode;
@@ -199,6 +236,6 @@
     if (Temp[I].Width = 0) or (Temp[I].Height = 0) then Continue;
     Temp[I].Canvas.StretchDraw(Rect(0, 0, Temp[I].Width, Temp[I].Height), TempBmp);
-  end;
-  TempBmp.Free;
+    TempBmp.Free;
+  end;
 
   ImgList.Clear;
@@ -272,5 +309,16 @@
   end;
 
-
+  if Control is TCoolBar then
+  with TCoolBar(Control) do begin
+    BeginUpdate;
+    for I := 0 to Bands.Count - 1 do
+      with Bands[I] do begin
+        MinWidth := ScaleX(MinWidth, FromDPI.X);
+        MinHeight := ScaleY(MinHeight, FromDPI.Y);
+        Width := ScaleX(Width, FromDPI.X);
+        //Control.Invalidate;
+      end;
+    EndUpdate;
+  end;
 
   if Control is TToolBar then begin
Index: /trunk/Packages/CoolTranslator/CoolTranslator.lpk
===================================================================
--- /trunk/Packages/CoolTranslator/CoolTranslator.lpk	(revision 40)
+++ /trunk/Packages/CoolTranslator/CoolTranslator.lpk	(revision 40)
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <Package Version="4">
+    <PathDelim Value="\"/>
+    <Name Value="CoolTranslator"/>
+    <AddToProjectUsesSection Value="True"/>
+    <Author Value="Chronos (robie@centrum.cz)"/>
+    <CompilerOptions>
+      <Version Value="10"/>
+      <PathDelim Value="\"/>
+      <SearchPaths>
+        <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+      </SearchPaths>
+      <Other>
+        <CompilerPath Value="$(CompPath)"/>
+      </Other>
+    </CompilerOptions>
+    <Description Value="Application interface translator tool"/>
+    <License Value="GNU/GPL"/>
+    <Version Minor="1"/>
+    <Files Count="3">
+      <Item1>
+        <Filename Value="UCoolTranslator.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="UCoolTranslator"/>
+      </Item1>
+      <Item2>
+        <Filename Value="ULanguages.pas"/>
+        <UnitName Value="ULanguages"/>
+      </Item2>
+      <Item3>
+        <Filename Value="ReadMe.txt"/>
+        <Type Value="Text"/>
+      </Item3>
+    </Files>
+    <i18n>
+      <EnableI18N Value="True"/>
+      <OutDir Value="Languages"/>
+    </i18n>
+    <Type Value="RunAndDesignTime"/>
+    <RequiredPkgs Count="2">
+      <Item1>
+        <PackageName Value="LCL"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="FCL"/>
+        <MinVersion Major="1" Valid="True"/>
+      </Item2>
+    </RequiredPkgs>
+    <UsageOptions>
+      <UnitPath Value="$(PkgOutDir)"/>
+    </UsageOptions>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+  </Package>
+</CONFIG>
Index: /trunk/Packages/CoolTranslator/CoolTranslator.pas
===================================================================
--- /trunk/Packages/CoolTranslator/CoolTranslator.pas	(revision 40)
+++ /trunk/Packages/CoolTranslator/CoolTranslator.pas	(revision 40)
@@ -0,0 +1,21 @@
+{ This file was automatically created by Lazarus. Do not edit!
+  This source is only used to compile and install the package.
+ }
+
+unit CoolTranslator; 
+
+interface
+
+uses
+  UCoolTranslator, ULanguages, LazarusPackageIntf;
+
+implementation
+
+procedure Register; 
+begin
+  RegisterUnit('UCoolTranslator', @UCoolTranslator.Register); 
+end; 
+
+initialization
+  RegisterPackage('CoolTranslator', @Register); 
+end.
Index: /trunk/Packages/CoolTranslator/Languages/UCoolTranslator.po
===================================================================
--- /trunk/Packages/CoolTranslator/Languages/UCoolTranslator.po	(revision 40)
+++ /trunk/Packages/CoolTranslator/Languages/UCoolTranslator.po	(revision 40)
@@ -0,0 +1,15 @@
+msgid ""
+msgstr "Content-Type: text/plain; charset=UTF-8"
+
+#: ucooltranslator.slanguageautomatic
+msgid "Automatic"
+msgstr ""
+
+#: ucooltranslator.slanguageczech
+msgid "Czech"
+msgstr ""
+
+#: ucooltranslator.slanguageenglish
+msgid "English"
+msgstr ""
+
Index: /trunk/Packages/CoolTranslator/Languages/ULanguages.cs.po
===================================================================
--- /trunk/Packages/CoolTranslator/Languages/ULanguages.cs.po	(revision 40)
+++ /trunk/Packages/CoolTranslator/Languages/ULanguages.cs.po	(revision 40)
@@ -0,0 +1,789 @@
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: Jiří Hajda <software@mezservis.cz>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ulanguages.slangauto
+msgid "Automatic"
+msgstr "Automaticky"
+
+#: ulanguages.slang_aa
+msgid "Afar"
+msgstr ""
+
+#: ulanguages.slang_ab
+msgid "Abkhazian"
+msgstr "Abcházština"
+
+#: ulanguages.slang_ae
+msgid "Avestan"
+msgstr ""
+
+#: ulanguages.slang_af
+msgid "Afrikaans"
+msgstr "Afrikánština"
+
+#: ulanguages.slang_ak
+msgid "Akan"
+msgstr ""
+
+#: ulanguages.slang_am
+msgid "Amharic"
+msgstr ""
+
+#: ulanguages.slang_an
+msgid "Aragonese"
+msgstr ""
+
+#: ulanguages.slang_ar
+msgid "Arabic"
+msgstr "Arabština"
+
+#: ulanguages.slang_as
+msgid "Assamese"
+msgstr ""
+
+#: ulanguages.slang_av
+msgid "Avaric"
+msgstr ""
+
+#: ulanguages.slang_ay
+msgid "Aymara"
+msgstr ""
+
+#: ulanguages.slang_az
+msgid "Azerbaijani"
+msgstr ""
+
+#: ulanguages.slang_ba
+msgid "Bashkir"
+msgstr ""
+
+#: ulanguages.slang_be
+msgid "Belarusian"
+msgstr ""
+
+#: ulanguages.slang_bg
+msgid "Bulgarian"
+msgstr "Maďarština"
+
+#: ulanguages.slang_bh
+msgid "Bihari"
+msgstr ""
+
+#: ulanguages.slang_bi
+msgid "Bislama"
+msgstr ""
+
+#: ulanguages.slang_bm
+msgid "Bambara"
+msgstr ""
+
+#: ulanguages.slang_bn
+msgid "Bengali"
+msgstr ""
+
+#: ulanguages.slang_bo
+msgid "Tibetan"
+msgstr "Tibetština"
+
+#: ulanguages.slang_br
+msgid "Breton"
+msgstr ""
+
+#: ulanguages.slang_bs
+msgid "Bosnian"
+msgstr ""
+
+#: ulanguages.slang_ca
+msgid "Catalan"
+msgstr "Katalánština"
+
+#: ulanguages.slang_ce
+msgid "Chechen"
+msgstr ""
+
+#: ulanguages.slang_ch
+msgid "Chamorro"
+msgstr ""
+
+#: ulanguages.slang_co
+msgid "Corsican"
+msgstr ""
+
+#: ulanguages.slang_cr
+msgid "Cree"
+msgstr "Kríjština"
+
+#: ulanguages.slang_cs
+msgid "Czech"
+msgstr "Čeština"
+
+#: ulanguages.slang_cv
+msgid "Chuvash"
+msgstr ""
+
+#: ulanguages.slang_cy
+msgid "Welsh"
+msgstr ""
+
+#: ulanguages.slang_da
+msgid "Danish"
+msgstr "Dánština"
+
+#: ulanguages.slang_de
+msgid "German"
+msgstr "Němčina"
+
+#: ulanguages.slang_de_at
+msgid "Austrian German"
+msgstr "Australská němčina"
+
+#: ulanguages.slang_de_ch
+msgid "Swiss German"
+msgstr "Švédská němčina"
+
+#: ulanguages.slang_dv
+msgid "Divehi"
+msgstr ""
+
+#: ulanguages.slang_dz
+msgid "Dzongkha"
+msgstr ""
+
+#: ulanguages.slang_ee
+msgid "Ewe"
+msgstr ""
+
+#: ulanguages.slang_el
+msgid "Greek"
+msgstr "Řečtina"
+
+#: ulanguages.slang_en
+msgid "English"
+msgstr "Angličtina"
+
+#: ulanguages.slang_en_au
+msgid "Australian English"
+msgstr "Australská angličtina"
+
+#: ulanguages.slang_en_ca
+msgid "Canadian English"
+msgstr "Kanadská angličtina"
+
+#: ulanguages.slang_en_gb
+msgid "British English"
+msgstr "Britská angličtina"
+
+#: ulanguages.slang_en_us
+msgid "American English"
+msgstr "Americká angličtina"
+
+#: ulanguages.slang_eo
+msgid "Esperanto"
+msgstr "Esperanto"
+
+#: ulanguages.slang_es
+msgid "Spanish"
+msgstr "Španělština"
+
+#: ulanguages.slang_et
+msgid "Estonian"
+msgstr "Estonština"
+
+#: ulanguages.slang_eu
+msgid "Basque"
+msgstr ""
+
+#: ulanguages.slang_fa
+msgid "Persian"
+msgstr "Perština"
+
+#: ulanguages.slang_ff
+msgid "Fulah"
+msgstr ""
+
+#: ulanguages.slang_fi
+msgid "Finnish"
+msgstr "Finština"
+
+#: ulanguages.slang_fj
+msgid "Fijian"
+msgstr ""
+
+#: ulanguages.slang_fo
+msgid "Faroese"
+msgstr ""
+
+#: ulanguages.slang_fr
+msgid "French"
+msgstr "Francouzština"
+
+#: ulanguages.slang_fr_be
+msgctxt "ulanguages.slang_fr_be"
+msgid "Walloon"
+msgstr ""
+
+#: ulanguages.slang_fy
+msgid "Frisian"
+msgstr ""
+
+#: ulanguages.slang_ga
+msgid "Irish"
+msgstr "Irština"
+
+#: ulanguages.slang_gd
+msgid "Gaelic"
+msgstr ""
+
+#: ulanguages.slang_gl
+msgid "Gallegan"
+msgstr ""
+
+#: ulanguages.slang_gn
+msgid "Guarani"
+msgstr ""
+
+#: ulanguages.slang_gu
+msgid "Gujarati"
+msgstr ""
+
+#: ulanguages.slang_gv
+msgid "Manx"
+msgstr ""
+
+#: ulanguages.slang_ha
+msgid "Hausa"
+msgstr ""
+
+#: ulanguages.slang_he
+msgid "Hebrew"
+msgstr "Hebrejština"
+
+#: ulanguages.slang_hi
+msgid "Hindi"
+msgstr ""
+
+#: ulanguages.slang_ho
+msgid "Hiri Motu"
+msgstr ""
+
+#: ulanguages.slang_hr
+msgid "Croatian"
+msgstr "Chorvatština"
+
+#: ulanguages.slang_ht
+msgid "Haitian"
+msgstr ""
+
+#: ulanguages.slang_hu
+msgid "Hungarian"
+msgstr "Maďarština"
+
+#: ulanguages.slang_hy
+msgid "Armenian"
+msgstr "Arménština"
+
+#: ulanguages.slang_hz
+msgid "Herero"
+msgstr ""
+
+#: ulanguages.slang_ia
+msgid "Interlingua"
+msgstr ""
+
+#: ulanguages.slang_id
+msgid "Indonesian"
+msgstr ""
+
+#: ulanguages.slang_ie
+msgid "Interlingue"
+msgstr ""
+
+#: ulanguages.slang_ig
+msgid "Igbo"
+msgstr ""
+
+#: ulanguages.slang_ii
+msgid "Sichuan Yi"
+msgstr ""
+
+#: ulanguages.slang_ik
+msgid "Inupiaq"
+msgstr ""
+
+#: ulanguages.slang_io
+msgid "Ido"
+msgstr ""
+
+#: ulanguages.slang_is
+msgid "Icelandic"
+msgstr "Islandština"
+
+#: ulanguages.slang_it
+msgid "Italian"
+msgstr "Italština"
+
+#: ulanguages.slang_iu
+msgid "Inuktitut"
+msgstr ""
+
+#: ulanguages.slang_ja
+msgid "Japanese"
+msgstr "Japonština"
+
+#: ulanguages.slang_jv
+msgid "Javanese"
+msgstr ""
+
+#: ulanguages.slang_ka
+msgid "Georgian"
+msgstr "Gruzínština"
+
+#: ulanguages.slang_kg
+msgid "Kongo"
+msgstr "Konžština"
+
+#: ulanguages.slang_ki
+msgid "Kikuyu"
+msgstr ""
+
+#: ulanguages.slang_kj
+msgid "Kuanyama"
+msgstr ""
+
+#: ulanguages.slang_kk
+msgid "Kazakh"
+msgstr ""
+
+#: ulanguages.slang_kl
+msgid "Greenlandic"
+msgstr "Grónština"
+
+#: ulanguages.slang_km
+msgid "Khmer"
+msgstr ""
+
+#: ulanguages.slang_kn
+msgid "Kannada"
+msgstr "Kannadština"
+
+#: ulanguages.slang_ko
+msgid "Korean"
+msgstr "Korejština"
+
+#: ulanguages.slang_kr
+msgid "Kanuri"
+msgstr ""
+
+#: ulanguages.slang_ks
+msgid "Kashmiri"
+msgstr ""
+
+#: ulanguages.slang_ku
+msgid "Kurdish"
+msgstr ""
+
+#: ulanguages.slang_kv
+msgid "Komi"
+msgstr ""
+
+#: ulanguages.slang_kw
+msgid "Cornish"
+msgstr "Kornština"
+
+#: ulanguages.slang_ky
+msgid "Kirghiz"
+msgstr ""
+
+#: ulanguages.slang_la
+msgid "Latin"
+msgstr "Latina"
+
+#: ulanguages.slang_lb
+msgid "Luxembourgish"
+msgstr "Lucemburština"
+
+#: ulanguages.slang_lg
+msgid "Ganda"
+msgstr ""
+
+#: ulanguages.slang_li
+msgid "Limburgan"
+msgstr ""
+
+#: ulanguages.slang_ln
+msgid "Lingala"
+msgstr ""
+
+#: ulanguages.slang_lo
+msgid "Lao"
+msgstr "Laoština"
+
+#: ulanguages.slang_lt
+msgid "Lithuanian"
+msgstr "Litevština"
+
+#: ulanguages.slang_lu
+msgid "Luba-Katanga"
+msgstr ""
+
+#: ulanguages.slang_lv
+msgid "Latvian"
+msgstr "Lotyština"
+
+#: ulanguages.slang_mg
+msgid "Malagasy"
+msgstr ""
+
+#: ulanguages.slang_mh
+msgid "Marshallese"
+msgstr ""
+
+#: ulanguages.slang_mi
+msgid "Maori"
+msgstr ""
+
+#: ulanguages.slang_mk
+msgid "Macedonian"
+msgstr "Makedonština"
+
+#: ulanguages.slang_ml
+msgid "Malayalam"
+msgstr ""
+
+#: ulanguages.slang_mn
+msgid "Mongolian"
+msgstr "Mongolština"
+
+#: ulanguages.slang_mo
+msgid "Moldavian"
+msgstr "Moldavština"
+
+#: ulanguages.slang_mr
+msgid "Marathi"
+msgstr ""
+
+#: ulanguages.slang_ms
+msgid "Malay"
+msgstr ""
+
+#: ulanguages.slang_mt
+msgid "Maltese"
+msgstr ""
+
+#: ulanguages.slang_my
+msgid "Burmese"
+msgstr ""
+
+#: ulanguages.slang_na
+msgid "Nauru"
+msgstr ""
+
+#: ulanguages.slang_nb
+msgid "Norwegian Bokmaal"
+msgstr ""
+
+#: ulanguages.slang_nd
+msgid "Ndebele, North"
+msgstr ""
+
+#: ulanguages.slang_ne
+msgid "Nepali"
+msgstr ""
+
+#: ulanguages.slang_ng
+msgid "Ndonga"
+msgstr ""
+
+#: ulanguages.slang_nl
+msgid "Dutch"
+msgstr "Němčina"
+
+#: ulanguages.slang_nl_be
+msgid "Flemish"
+msgstr ""
+
+#: ulanguages.slang_nn
+msgid "Norwegian Nynorsk"
+msgstr ""
+
+#: ulanguages.slang_no
+msgid "Norwegian"
+msgstr "Norština"
+
+#: ulanguages.slang_nr
+msgid "Ndebele, South"
+msgstr ""
+
+#: ulanguages.slang_nv
+msgid "Navajo"
+msgstr "Navažština"
+
+#: ulanguages.slang_ny
+msgid "Chichewa"
+msgstr ""
+
+#: ulanguages.slang_oc
+msgid "Occitan"
+msgstr ""
+
+#: ulanguages.slang_oj
+msgid "Ojibwa"
+msgstr ""
+
+#: ulanguages.slang_om
+msgid "Oromo"
+msgstr ""
+
+#: ulanguages.slang_or
+msgid "Oriya"
+msgstr ""
+
+#: ulanguages.slang_os
+msgid "Ossetian"
+msgstr ""
+
+#: ulanguages.slang_pa
+msgid "Panjabi"
+msgstr ""
+
+#: ulanguages.slang_pi
+msgid "Pali"
+msgstr ""
+
+#: ulanguages.slang_pl
+msgid "Polish"
+msgstr "Polština"
+
+#: ulanguages.slang_ps
+msgid "Pushto"
+msgstr ""
+
+#: ulanguages.slang_pt
+msgid "Portuguese"
+msgstr "Portugalština"
+
+#: ulanguages.slang_pt_br
+msgid "Brazilian Portuguese"
+msgstr "Brazislká portugalština"
+
+#: ulanguages.slang_qu
+msgid "Quechua"
+msgstr ""
+
+#: ulanguages.slang_rm
+msgid "Raeto-Romance"
+msgstr ""
+
+#: ulanguages.slang_rn
+msgid "Rundi"
+msgstr ""
+
+#: ulanguages.slang_ro
+msgid "Romanian"
+msgstr "Romština"
+
+#: ulanguages.slang_ru
+msgid "Russian"
+msgstr "Ruština"
+
+#: ulanguages.slang_rw
+msgid "Kinyarwanda"
+msgstr ""
+
+#: ulanguages.slang_sa
+msgid "Sanskrit"
+msgstr ""
+
+#: ulanguages.slang_sc
+msgid "Sardinian"
+msgstr ""
+
+#: ulanguages.slang_sd
+msgid "Sindhi"
+msgstr ""
+
+#: ulanguages.slang_se
+msgid "Northern Sami"
+msgstr ""
+
+#: ulanguages.slang_sg
+msgid "Sango"
+msgstr ""
+
+#: ulanguages.slang_si
+msgid "Sinhalese"
+msgstr ""
+
+#: ulanguages.slang_sk
+msgid "Slovak"
+msgstr "Slovenština"
+
+#: ulanguages.slang_sl
+msgid "Slovenian"
+msgstr "Slovinština"
+
+#: ulanguages.slang_sm
+msgid "Samoan"
+msgstr ""
+
+#: ulanguages.slang_sn
+msgid "Shona"
+msgstr ""
+
+#: ulanguages.slang_so
+msgid "Somali"
+msgstr ""
+
+#: ulanguages.slang_sq
+msgid "Albanian"
+msgstr "Albánština"
+
+#: ulanguages.slang_sr
+msgid "Serbian"
+msgstr ""
+
+#: ulanguages.slang_ss
+msgid "Swati"
+msgstr ""
+
+#: ulanguages.slang_st
+msgid "Sotho, Southern"
+msgstr ""
+
+#: ulanguages.slang_su
+msgid "Sundanese"
+msgstr "Sundština"
+
+#: ulanguages.slang_sv
+msgid "Swedish"
+msgstr "Švédština"
+
+#: ulanguages.slang_sw
+msgid "Swahili"
+msgstr ""
+
+#: ulanguages.slang_ta
+msgid "Tamil"
+msgstr ""
+
+#: ulanguages.slang_te
+msgid "Telugu"
+msgstr ""
+
+#: ulanguages.slang_tg
+msgid "Tajik"
+msgstr ""
+
+#: ulanguages.slang_th
+msgid "Thai"
+msgstr ""
+
+#: ulanguages.slang_ti
+msgid "Tigrinya"
+msgstr ""
+
+#: ulanguages.slang_tk
+msgid "Turkmen"
+msgstr ""
+
+#: ulanguages.slang_tl
+msgid "Tagalog"
+msgstr ""
+
+#: ulanguages.slang_tn
+msgid "Tswana"
+msgstr ""
+
+#: ulanguages.slang_to
+msgid "Tonga"
+msgstr ""
+
+#: ulanguages.slang_tr
+msgid "Turkish"
+msgstr "Turečtina"
+
+#: ulanguages.slang_ts
+msgid "Tsonga"
+msgstr ""
+
+#: ulanguages.slang_tt
+msgid "Tatar"
+msgstr "Tatarština"
+
+#: ulanguages.slang_tw
+msgid "Twi"
+msgstr ""
+
+#: ulanguages.slang_ty
+msgid "Tahitian"
+msgstr ""
+
+#: ulanguages.slang_ug
+msgid "Uighur"
+msgstr ""
+
+#: ulanguages.slang_uk
+msgid "Ukrainian"
+msgstr "Ukrajinština"
+
+#: ulanguages.slang_ur
+msgid "Urdu"
+msgstr ""
+
+#: ulanguages.slang_uz
+msgid "Uzbek"
+msgstr ""
+
+#: ulanguages.slang_ve
+msgid "Venda"
+msgstr ""
+
+#: ulanguages.slang_vi
+msgid "Vietnamese"
+msgstr "Vietnamština"
+
+#: ulanguages.slang_vo
+msgid "Volapuk"
+msgstr ""
+
+#: ulanguages.slang_wa
+msgctxt "ulanguages.slang_wa"
+msgid "Walloon"
+msgstr ""
+
+#: ulanguages.slang_wo
+msgid "Wolof"
+msgstr ""
+
+#: ulanguages.slang_xh
+msgid "Xhosa"
+msgstr ""
+
+#: ulanguages.slang_yi
+msgid "Yiddish"
+msgstr ""
+
+#: ulanguages.slang_yo
+msgid "Yoruba"
+msgstr ""
+
+#: ulanguages.slang_za
+msgid "Zhuang"
+msgstr ""
+
+#: ulanguages.slang_zh
+msgid "Chinese"
+msgstr "Čínština"
+
+#: ulanguages.slang_zu
+msgid "Zulu"
+msgstr "Zuluština"
+
Index: /trunk/Packages/CoolTranslator/Languages/ULanguages.po
===================================================================
--- /trunk/Packages/CoolTranslator/Languages/ULanguages.po	(revision 40)
+++ /trunk/Packages/CoolTranslator/Languages/ULanguages.po	(revision 40)
@@ -0,0 +1,781 @@
+msgid ""
+msgstr "Content-Type: text/plain; charset=UTF-8"
+
+#: ulanguages.slangauto
+msgid "Automatic"
+msgstr ""
+
+#: ulanguages.slang_aa
+msgid "Afar"
+msgstr ""
+
+#: ulanguages.slang_ab
+msgid "Abkhazian"
+msgstr ""
+
+#: ulanguages.slang_ae
+msgid "Avestan"
+msgstr ""
+
+#: ulanguages.slang_af
+msgid "Afrikaans"
+msgstr ""
+
+#: ulanguages.slang_ak
+msgid "Akan"
+msgstr ""
+
+#: ulanguages.slang_am
+msgid "Amharic"
+msgstr ""
+
+#: ulanguages.slang_an
+msgid "Aragonese"
+msgstr ""
+
+#: ulanguages.slang_ar
+msgid "Arabic"
+msgstr ""
+
+#: ulanguages.slang_as
+msgid "Assamese"
+msgstr ""
+
+#: ulanguages.slang_av
+msgid "Avaric"
+msgstr ""
+
+#: ulanguages.slang_ay
+msgid "Aymara"
+msgstr ""
+
+#: ulanguages.slang_az
+msgid "Azerbaijani"
+msgstr ""
+
+#: ulanguages.slang_ba
+msgid "Bashkir"
+msgstr ""
+
+#: ulanguages.slang_be
+msgid "Belarusian"
+msgstr ""
+
+#: ulanguages.slang_bg
+msgid "Bulgarian"
+msgstr ""
+
+#: ulanguages.slang_bh
+msgid "Bihari"
+msgstr ""
+
+#: ulanguages.slang_bi
+msgid "Bislama"
+msgstr ""
+
+#: ulanguages.slang_bm
+msgid "Bambara"
+msgstr ""
+
+#: ulanguages.slang_bn
+msgid "Bengali"
+msgstr ""
+
+#: ulanguages.slang_bo
+msgid "Tibetan"
+msgstr ""
+
+#: ulanguages.slang_br
+msgid "Breton"
+msgstr ""
+
+#: ulanguages.slang_bs
+msgid "Bosnian"
+msgstr ""
+
+#: ulanguages.slang_ca
+msgid "Catalan"
+msgstr ""
+
+#: ulanguages.slang_ce
+msgid "Chechen"
+msgstr ""
+
+#: ulanguages.slang_ch
+msgid "Chamorro"
+msgstr ""
+
+#: ulanguages.slang_co
+msgid "Corsican"
+msgstr ""
+
+#: ulanguages.slang_cr
+msgid "Cree"
+msgstr ""
+
+#: ulanguages.slang_cs
+msgid "Czech"
+msgstr ""
+
+#: ulanguages.slang_cv
+msgid "Chuvash"
+msgstr ""
+
+#: ulanguages.slang_cy
+msgid "Welsh"
+msgstr ""
+
+#: ulanguages.slang_da
+msgid "Danish"
+msgstr ""
+
+#: ulanguages.slang_de
+msgid "German"
+msgstr ""
+
+#: ulanguages.slang_de_at
+msgid "Austrian German"
+msgstr ""
+
+#: ulanguages.slang_de_ch
+msgid "Swiss German"
+msgstr ""
+
+#: ulanguages.slang_dv
+msgid "Divehi"
+msgstr ""
+
+#: ulanguages.slang_dz
+msgid "Dzongkha"
+msgstr ""
+
+#: ulanguages.slang_ee
+msgid "Ewe"
+msgstr ""
+
+#: ulanguages.slang_el
+msgid "Greek"
+msgstr ""
+
+#: ulanguages.slang_en
+msgid "English"
+msgstr ""
+
+#: ulanguages.slang_en_au
+msgid "Australian English"
+msgstr ""
+
+#: ulanguages.slang_en_ca
+msgid "Canadian English"
+msgstr ""
+
+#: ulanguages.slang_en_gb
+msgid "British English"
+msgstr ""
+
+#: ulanguages.slang_en_us
+msgid "American English"
+msgstr ""
+
+#: ulanguages.slang_eo
+msgid "Esperanto"
+msgstr ""
+
+#: ulanguages.slang_es
+msgid "Spanish"
+msgstr ""
+
+#: ulanguages.slang_et
+msgid "Estonian"
+msgstr ""
+
+#: ulanguages.slang_eu
+msgid "Basque"
+msgstr ""
+
+#: ulanguages.slang_fa
+msgid "Persian"
+msgstr ""
+
+#: ulanguages.slang_ff
+msgid "Fulah"
+msgstr ""
+
+#: ulanguages.slang_fi
+msgid "Finnish"
+msgstr ""
+
+#: ulanguages.slang_fj
+msgid "Fijian"
+msgstr ""
+
+#: ulanguages.slang_fo
+msgid "Faroese"
+msgstr ""
+
+#: ulanguages.slang_fr
+msgid "French"
+msgstr ""
+
+#: ulanguages.slang_fr_be
+msgctxt "ulanguages.slang_fr_be"
+msgid "Walloon"
+msgstr ""
+
+#: ulanguages.slang_fy
+msgid "Frisian"
+msgstr ""
+
+#: ulanguages.slang_ga
+msgid "Irish"
+msgstr ""
+
+#: ulanguages.slang_gd
+msgid "Gaelic"
+msgstr ""
+
+#: ulanguages.slang_gl
+msgid "Gallegan"
+msgstr ""
+
+#: ulanguages.slang_gn
+msgid "Guarani"
+msgstr ""
+
+#: ulanguages.slang_gu
+msgid "Gujarati"
+msgstr ""
+
+#: ulanguages.slang_gv
+msgid "Manx"
+msgstr ""
+
+#: ulanguages.slang_ha
+msgid "Hausa"
+msgstr ""
+
+#: ulanguages.slang_he
+msgid "Hebrew"
+msgstr ""
+
+#: ulanguages.slang_hi
+msgid "Hindi"
+msgstr ""
+
+#: ulanguages.slang_ho
+msgid "Hiri Motu"
+msgstr ""
+
+#: ulanguages.slang_hr
+msgid "Croatian"
+msgstr ""
+
+#: ulanguages.slang_ht
+msgid "Haitian"
+msgstr ""
+
+#: ulanguages.slang_hu
+msgid "Hungarian"
+msgstr ""
+
+#: ulanguages.slang_hy
+msgid "Armenian"
+msgstr ""
+
+#: ulanguages.slang_hz
+msgid "Herero"
+msgstr ""
+
+#: ulanguages.slang_ia
+msgid "Interlingua"
+msgstr ""
+
+#: ulanguages.slang_id
+msgid "Indonesian"
+msgstr ""
+
+#: ulanguages.slang_ie
+msgid "Interlingue"
+msgstr ""
+
+#: ulanguages.slang_ig
+msgid "Igbo"
+msgstr ""
+
+#: ulanguages.slang_ii
+msgid "Sichuan Yi"
+msgstr ""
+
+#: ulanguages.slang_ik
+msgid "Inupiaq"
+msgstr ""
+
+#: ulanguages.slang_io
+msgid "Ido"
+msgstr ""
+
+#: ulanguages.slang_is
+msgid "Icelandic"
+msgstr ""
+
+#: ulanguages.slang_it
+msgid "Italian"
+msgstr ""
+
+#: ulanguages.slang_iu
+msgid "Inuktitut"
+msgstr ""
+
+#: ulanguages.slang_ja
+msgid "Japanese"
+msgstr ""
+
+#: ulanguages.slang_jv
+msgid "Javanese"
+msgstr ""
+
+#: ulanguages.slang_ka
+msgid "Georgian"
+msgstr ""
+
+#: ulanguages.slang_kg
+msgid "Kongo"
+msgstr ""
+
+#: ulanguages.slang_ki
+msgid "Kikuyu"
+msgstr ""
+
+#: ulanguages.slang_kj
+msgid "Kuanyama"
+msgstr ""
+
+#: ulanguages.slang_kk
+msgid "Kazakh"
+msgstr ""
+
+#: ulanguages.slang_kl
+msgid "Greenlandic"
+msgstr ""
+
+#: ulanguages.slang_km
+msgid "Khmer"
+msgstr ""
+
+#: ulanguages.slang_kn
+msgid "Kannada"
+msgstr ""
+
+#: ulanguages.slang_ko
+msgid "Korean"
+msgstr ""
+
+#: ulanguages.slang_kr
+msgid "Kanuri"
+msgstr ""
+
+#: ulanguages.slang_ks
+msgid "Kashmiri"
+msgstr ""
+
+#: ulanguages.slang_ku
+msgid "Kurdish"
+msgstr ""
+
+#: ulanguages.slang_kv
+msgid "Komi"
+msgstr ""
+
+#: ulanguages.slang_kw
+msgid "Cornish"
+msgstr ""
+
+#: ulanguages.slang_ky
+msgid "Kirghiz"
+msgstr ""
+
+#: ulanguages.slang_la
+msgid "Latin"
+msgstr ""
+
+#: ulanguages.slang_lb
+msgid "Luxembourgish"
+msgstr ""
+
+#: ulanguages.slang_lg
+msgid "Ganda"
+msgstr ""
+
+#: ulanguages.slang_li
+msgid "Limburgan"
+msgstr ""
+
+#: ulanguages.slang_ln
+msgid "Lingala"
+msgstr ""
+
+#: ulanguages.slang_lo
+msgid "Lao"
+msgstr ""
+
+#: ulanguages.slang_lt
+msgid "Lithuanian"
+msgstr ""
+
+#: ulanguages.slang_lu
+msgid "Luba-Katanga"
+msgstr ""
+
+#: ulanguages.slang_lv
+msgid "Latvian"
+msgstr ""
+
+#: ulanguages.slang_mg
+msgid "Malagasy"
+msgstr ""
+
+#: ulanguages.slang_mh
+msgid "Marshallese"
+msgstr ""
+
+#: ulanguages.slang_mi
+msgid "Maori"
+msgstr ""
+
+#: ulanguages.slang_mk
+msgid "Macedonian"
+msgstr ""
+
+#: ulanguages.slang_ml
+msgid "Malayalam"
+msgstr ""
+
+#: ulanguages.slang_mn
+msgid "Mongolian"
+msgstr ""
+
+#: ulanguages.slang_mo
+msgid "Moldavian"
+msgstr ""
+
+#: ulanguages.slang_mr
+msgid "Marathi"
+msgstr ""
+
+#: ulanguages.slang_ms
+msgid "Malay"
+msgstr ""
+
+#: ulanguages.slang_mt
+msgid "Maltese"
+msgstr ""
+
+#: ulanguages.slang_my
+msgid "Burmese"
+msgstr ""
+
+#: ulanguages.slang_na
+msgid "Nauru"
+msgstr ""
+
+#: ulanguages.slang_nb
+msgid "Norwegian Bokmaal"
+msgstr ""
+
+#: ulanguages.slang_nd
+msgid "Ndebele, North"
+msgstr ""
+
+#: ulanguages.slang_ne
+msgid "Nepali"
+msgstr ""
+
+#: ulanguages.slang_ng
+msgid "Ndonga"
+msgstr ""
+
+#: ulanguages.slang_nl
+msgid "Dutch"
+msgstr ""
+
+#: ulanguages.slang_nl_be
+msgid "Flemish"
+msgstr ""
+
+#: ulanguages.slang_nn
+msgid "Norwegian Nynorsk"
+msgstr ""
+
+#: ulanguages.slang_no
+msgid "Norwegian"
+msgstr ""
+
+#: ulanguages.slang_nr
+msgid "Ndebele, South"
+msgstr ""
+
+#: ulanguages.slang_nv
+msgid "Navajo"
+msgstr ""
+
+#: ulanguages.slang_ny
+msgid "Chichewa"
+msgstr ""
+
+#: ulanguages.slang_oc
+msgid "Occitan"
+msgstr ""
+
+#: ulanguages.slang_oj
+msgid "Ojibwa"
+msgstr ""
+
+#: ulanguages.slang_om
+msgid "Oromo"
+msgstr ""
+
+#: ulanguages.slang_or
+msgid "Oriya"
+msgstr ""
+
+#: ulanguages.slang_os
+msgid "Ossetian"
+msgstr ""
+
+#: ulanguages.slang_pa
+msgid "Panjabi"
+msgstr ""
+
+#: ulanguages.slang_pi
+msgid "Pali"
+msgstr ""
+
+#: ulanguages.slang_pl
+msgid "Polish"
+msgstr ""
+
+#: ulanguages.slang_ps
+msgid "Pushto"
+msgstr ""
+
+#: ulanguages.slang_pt
+msgid "Portuguese"
+msgstr ""
+
+#: ulanguages.slang_pt_br
+msgid "Brazilian Portuguese"
+msgstr ""
+
+#: ulanguages.slang_qu
+msgid "Quechua"
+msgstr ""
+
+#: ulanguages.slang_rm
+msgid "Raeto-Romance"
+msgstr ""
+
+#: ulanguages.slang_rn
+msgid "Rundi"
+msgstr ""
+
+#: ulanguages.slang_ro
+msgid "Romanian"
+msgstr ""
+
+#: ulanguages.slang_ru
+msgid "Russian"
+msgstr ""
+
+#: ulanguages.slang_rw
+msgid "Kinyarwanda"
+msgstr ""
+
+#: ulanguages.slang_sa
+msgid "Sanskrit"
+msgstr ""
+
+#: ulanguages.slang_sc
+msgid "Sardinian"
+msgstr ""
+
+#: ulanguages.slang_sd
+msgid "Sindhi"
+msgstr ""
+
+#: ulanguages.slang_se
+msgid "Northern Sami"
+msgstr ""
+
+#: ulanguages.slang_sg
+msgid "Sango"
+msgstr ""
+
+#: ulanguages.slang_si
+msgid "Sinhalese"
+msgstr ""
+
+#: ulanguages.slang_sk
+msgid "Slovak"
+msgstr ""
+
+#: ulanguages.slang_sl
+msgid "Slovenian"
+msgstr ""
+
+#: ulanguages.slang_sm
+msgid "Samoan"
+msgstr ""
+
+#: ulanguages.slang_sn
+msgid "Shona"
+msgstr ""
+
+#: ulanguages.slang_so
+msgid "Somali"
+msgstr ""
+
+#: ulanguages.slang_sq
+msgid "Albanian"
+msgstr ""
+
+#: ulanguages.slang_sr
+msgid "Serbian"
+msgstr ""
+
+#: ulanguages.slang_ss
+msgid "Swati"
+msgstr ""
+
+#: ulanguages.slang_st
+msgid "Sotho, Southern"
+msgstr ""
+
+#: ulanguages.slang_su
+msgid "Sundanese"
+msgstr ""
+
+#: ulanguages.slang_sv
+msgid "Swedish"
+msgstr ""
+
+#: ulanguages.slang_sw
+msgid "Swahili"
+msgstr ""
+
+#: ulanguages.slang_ta
+msgid "Tamil"
+msgstr ""
+
+#: ulanguages.slang_te
+msgid "Telugu"
+msgstr ""
+
+#: ulanguages.slang_tg
+msgid "Tajik"
+msgstr ""
+
+#: ulanguages.slang_th
+msgid "Thai"
+msgstr ""
+
+#: ulanguages.slang_ti
+msgid "Tigrinya"
+msgstr ""
+
+#: ulanguages.slang_tk
+msgid "Turkmen"
+msgstr ""
+
+#: ulanguages.slang_tl
+msgid "Tagalog"
+msgstr ""
+
+#: ulanguages.slang_tn
+msgid "Tswana"
+msgstr ""
+
+#: ulanguages.slang_to
+msgid "Tonga"
+msgstr ""
+
+#: ulanguages.slang_tr
+msgid "Turkish"
+msgstr ""
+
+#: ulanguages.slang_ts
+msgid "Tsonga"
+msgstr ""
+
+#: ulanguages.slang_tt
+msgid "Tatar"
+msgstr ""
+
+#: ulanguages.slang_tw
+msgid "Twi"
+msgstr ""
+
+#: ulanguages.slang_ty
+msgid "Tahitian"
+msgstr ""
+
+#: ulanguages.slang_ug
+msgid "Uighur"
+msgstr ""
+
+#: ulanguages.slang_uk
+msgid "Ukrainian"
+msgstr ""
+
+#: ulanguages.slang_ur
+msgid "Urdu"
+msgstr ""
+
+#: ulanguages.slang_uz
+msgid "Uzbek"
+msgstr ""
+
+#: ulanguages.slang_ve
+msgid "Venda"
+msgstr ""
+
+#: ulanguages.slang_vi
+msgid "Vietnamese"
+msgstr ""
+
+#: ulanguages.slang_vo
+msgid "Volapuk"
+msgstr ""
+
+#: ulanguages.slang_wa
+msgctxt "ulanguages.slang_wa"
+msgid "Walloon"
+msgstr ""
+
+#: ulanguages.slang_wo
+msgid "Wolof"
+msgstr ""
+
+#: ulanguages.slang_xh
+msgid "Xhosa"
+msgstr ""
+
+#: ulanguages.slang_yi
+msgid "Yiddish"
+msgstr ""
+
+#: ulanguages.slang_yo
+msgid "Yoruba"
+msgstr ""
+
+#: ulanguages.slang_za
+msgid "Zhuang"
+msgstr ""
+
+#: ulanguages.slang_zh
+msgid "Chinese"
+msgstr ""
+
+#: ulanguages.slang_zu
+msgid "Zulu"
+msgstr ""
+
Index: /trunk/Packages/CoolTranslator/ReadMe.txt
===================================================================
--- /trunk/Packages/CoolTranslator/ReadMe.txt	(revision 40)
+++ /trunk/Packages/CoolTranslator/ReadMe.txt	(revision 40)
@@ -0,0 +1,46 @@
+=Introduction=
+
+This package contains component which make translation of application easy.
+
+==Features==
+
+* Easy to use non-visual component
+* Support runtime translation
+* Native to lazarus (use .po files)
+* Native to FPC (use resourcestrings)
+* Supply available language list
+
+=How translation is done=
+
+Strings are translated runtime and there is no need to do it as first step during initialization phase.
+
+==Resourcestring=
+
+Resourcestrings are translated automatically.
+
+==Components==
+
+All application components are translated automatically.
+This mean all TPersistent descendants with published properties linked to Application object.
+
+===Component and properties exclusion===
+It is possible to exclude properties which should not be translated
+
+===TCollection, TStrings===
+Some class properties are translated.
+
+* TCollection: TListView.Columns
+* TStrings: TRadioGroup.Items, TPageControl.Pages, TComboBox.Items, TMemo.Lines
+
+==Other constants==
+
+
+==Custom translation==
+
+You can handle OnTranslate event and do translation of custom structures.
+
+=Download=
+
+You can download source code using subversion:
+
+svn checkout http://svn.zdechov.net/PascalClassLibrary/CoolTranslator
Index: /trunk/Packages/CoolTranslator/UCoolTranslator.pas
===================================================================
--- /trunk/Packages/CoolTranslator/UCoolTranslator.pas	(revision 40)
+++ /trunk/Packages/CoolTranslator/UCoolTranslator.pas	(revision 40)
@@ -0,0 +1,559 @@
+unit UCoolTranslator;
+
+{$mode Delphi}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, ExtCtrls, Controls, Contnrs, LazFileUtils, LazUTF8,
+  Translations, TypInfo, Dialogs, FileUtil, LCLProc, ULanguages, LCLType;
+
+type
+  THandleStringEvent = function (AValue: string): string of object;
+
+  { TComponentExcludes }
+
+  TComponentExcludes = class
+    ExcludedClassType: TClass;
+    PropertyExcludes: TStringList;
+    constructor Create;
+    destructor Destroy; override;
+  end;
+
+  { TComponentExcludesList }
+
+  TComponentExcludesList = class(TObjectList)
+    function FindByClassType(AClassType: TClass): TComponentExcludes;
+    procedure DumpToStrings(Strings: TStrings);
+  end;
+
+  { TCoolTranslator }
+
+  TCoolTranslator = class(TComponent)
+  private
+    FLanguage: TLanguage;
+    FOnAutomaticLanguage: THandleStringEvent;
+    FOnTranslate: TNotifyEvent;
+    FPOFilesFolder: string;
+    FPOFiles: TObjectList; // TObjectList<TPOFile>;
+    function GetLocale: string;
+    function GetLocaleShort: string;
+    function FindLocaleFileName(LCExt: string): string;
+    function GetLocaleFileName(const LangID, LCExt: string): string;
+    procedure ReloadFiles;
+    procedure SetPOFilesFolder(const AValue: string);
+    procedure SetLanguage(const AValue: TLanguage);
+    procedure TranslateProperty(Component: TPersistent; PropInfo: PPropInfo);
+    function IsExcluded(Component: TPersistent; PropertyName: string): Boolean;
+    function GetLangFileDir: string;
+  public
+    ComponentExcludes: TComponentExcludesList;
+    Languages: TLanguageList;
+    procedure Translate;
+    procedure LanguageListToStrings(Strings: TStrings);
+    procedure TranslateResourceStrings(PoFileName: string);
+    procedure TranslateUnitResourceStrings(UnitName: string; PoFileName: string);
+    procedure TranslateComponent(Component: TPersistent);
+    procedure TranslateComponentRecursive(Component: TComponent);
+    function TranslateText(Identifier, Text: string): string;
+    procedure AddExcludes(AClassType: TClass; PropertyName: string);
+    procedure CheckLanguageFiles;
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+  published
+    property POFilesFolder: string read FPOFilesFolder write SetPOFilesFolder;
+    property Language: TLanguage read FLanguage write SetLanguage;
+    property OnTranslate: TNotifyEvent read FOnTranslate write FOnTranslate;
+    property OnAutomaticLanguage: THandleStringEvent read FOnAutomaticLanguage
+      write FOnAutomaticLanguage;
+  end;
+
+procedure Register;
+
+implementation
+
+procedure Register;
+begin
+  RegisterComponents('Samples', [TCoolTranslator]);
+end;
+
+{ TComponentExcludesList }
+
+function TComponentExcludesList.FindByClassType(AClassType: TClass
+  ): TComponentExcludes;
+var
+  I: Integer;
+begin
+  I := 0;
+  while (I < Count) and (TComponentExcludes(Items[I]).ExcludedClassType <> AClassType) do
+    Inc(I);
+  if I < Count then Result := TComponentExcludes(Items[I])
+    else Result := nil;
+end;
+
+procedure TComponentExcludesList.DumpToStrings(Strings: TStrings);
+var
+  I, J: Integer;
+  Text: string;
+begin
+  Strings.Clear;
+  for I := 0 to Count - 1 do
+  with TComponentExcludes(Items[I]) do begin
+    Text := ExcludedClassType.ClassName + ': ';
+    for J := 0 to PropertyExcludes.Count - 1 do
+      Text := Text + PropertyExcludes[J] + ', ';
+    Strings.Add(Text);
+  end;
+end;
+
+{ TComponentExcludes }
+
+constructor TComponentExcludes.Create;
+begin
+  PropertyExcludes := TStringList.Create;
+end;
+
+destructor TComponentExcludes.Destroy;
+begin
+  PropertyExcludes.Free;
+  inherited Destroy;
+end;
+
+
+{ TCoolTranslator }
+
+procedure TCoolTranslator.Translate;
+var
+  I, J: Integer;
+  Po: TPoFile;
+begin
+  TranslateComponentRecursive(Application);
+
+  // Merge files to single translation file
+  try
+    Po := TPOFile.Create;
+    for I := 0 to FPOFiles.Count - 1 do
+    with TPoFile(FPoFiles[I]) do
+      for J := 0 to Items.Count - 1 do
+      with TPoFileItem(Items[J]) do
+        Po.Add(IdentifierLow, Original, Translation, Comments, Context,
+          Flags, PreviousID);
+    Translations.TranslateResourceStrings(Po);
+  finally
+    Po.Free;
+  end;
+end;
+
+procedure TCoolTranslator.ReloadFiles;
+var
+  FileName: string;
+  FileList: TStringList;
+  I: Integer;
+  LocaleShort: string;
+  SearchMask: string;
+begin
+  FPOFiles.Clear;
+  if Assigned(FLanguage) then
+  try
+    LocaleShort := GetLocaleShort;
+    //ShowMessage(ExtractFileDir(Application.ExeName) +
+    //  DirectorySeparator + 'Languages' + ' ' + '*.' + LocaleShort + '.po');
+    SearchMask := '*';
+    if LocaleShort <> '' then SearchMask := SearchMask + '.' + LocaleShort;
+    SearchMask := SearchMask + '.po';
+    FileList := FindAllFiles(GetLangFileDir, SearchMask);
+    for I := 0 to FileList.Count - 1 do begin
+      FileName := FileList[I];
+      //FileName := FindLocaleFileName('.po');
+      if FileExists(FileName) and (
+      ((LocaleShort = '') and (Pos('.', FileName) = Pos('.po', FileName))) or
+      (LocaleShort <> '')) then FPOFiles.Add(TPOFile.Create(FileName));
+    end;
+  finally
+    FileList.Free;
+  end;
+end;
+
+procedure TCoolTranslator.SetPOFilesFolder(const AValue: string);
+begin
+  if FPoFilesFolder = AValue then Exit;
+  FPoFilesFolder := AValue;
+  ReloadFiles;
+  CheckLanguageFiles;
+end;
+
+procedure TCoolTranslator.SetLanguage(const AValue: TLanguage);
+begin
+  if FLanguage = AValue then Exit;
+  FLanguage := AValue;
+  ReloadFiles;
+  Translate;
+  if Assigned(FOnTranslate) then FOnTranslate(Self);
+end;
+
+procedure TCoolTranslator.TranslateComponent(Component: TPersistent);
+var
+  I, Count: Integer;
+  PropInfo: PPropInfo;
+  PropList: PPropList;
+  Excludes: TComponentExcludes;
+begin
+  Count := GetTypeData(Component.ClassInfo)^.PropCount;
+  if Count > 0 then begin
+    GetMem(PropList, Count * SizeOf(Pointer));
+    try
+      GetPropInfos(Component.ClassInfo, PropList);
+      for I := 0 to Count - 1 do
+      begin
+        PropInfo := PropList^[I];
+        if PropInfo = nil then
+          Break;
+        TranslateProperty(Component, PropInfo);
+      end;
+    finally
+      FreeMem(PropList, Count * SizeOf(Pointer));
+    end;
+  end;
+end;
+
+procedure TCoolTranslator.TranslateComponentRecursive(Component: TComponent);
+var
+  I: Integer;
+begin
+  TranslateComponent(Component);
+  for I := 0 to Component.ComponentCount - 1 do
+    TranslateComponentRecursive(Component.Components[I]);
+end;
+
+procedure TCoolTranslator.TranslateProperty(Component: TPersistent;
+  PropInfo: PPropInfo);
+var
+  PropType: PTypeInfo;
+  Obj: TObject;
+  I: Integer;
+begin
+
+//  PropInfo^.Name;
+  // Using IsDefaultPropertyValue will tell us if we should write out
+  // a given property because it was different from the default or
+  // different from the Ancestor (if applicable).
+  if (PropInfo^.GetProc <> nil) and
+     ((PropInfo^.SetProc <> nil) or
+     ((PropInfo^.PropType^.Kind = tkClass) and
+      (TObject(GetOrdProp(Component, PropInfo)) is TComponent) and
+      (csSubComponent in TComponent(GetOrdProp(Component, PropInfo)).ComponentStyle))) then
+  begin
+    begin
+      PropType := PropInfo^.PropType;
+      case PropType^.Kind of
+        tkString, tkLString, tkWString, tkAString: begin
+          if (UpperCase(PropType.Name) = 'TTRANSLATESTRING') then
+          //if not IsExcluded(Component, PropInfo^.Name) then
+              SetStrProp(Component, PropInfo, TranslateText(PropInfo^.Name, GetWideStrProp(Component, PropInfo)));
+        end;
+        tkClass: begin
+          Obj := TObject(GetOrdProp(Component, PropInfo));
+          if Obj is TCollection then
+            for I := 0 to TCollection(Obj).Count - 1 do
+              with TCollection(Obj).Items[I] do
+                TranslateComponent(TCollection(Obj).Items[I]);
+          (*if Obj is TStrings then
+            for I := 0 to TStrings(Obj).Count - 1 do
+              with TStrings(Obj) do
+                Strings[I] := TranslateText(Strings[I], Strings[I]);
+          *)
+        end;
+      end;
+    end;
+  end;
+end;
+
+function TCoolTranslator.IsExcluded(Component: TPersistent; PropertyName: string
+  ): Boolean;
+var
+  Item: TClass;
+
+  Excludes: TComponentExcludes;
+begin
+  Result := False;
+  Item := Component.ClassType;
+  while Assigned(Item) do begin
+    //ShowMessage(Component.Name + ', ' + Component.ClassName + ', ' + Item.ClassName + ', ' + PropertyName);
+    Excludes := ComponentExcludes.FindByClassType(Item.ClassType);
+    if Assigned(Excludes) then begin
+      if Excludes.PropertyExcludes.IndexOf(PropertyName) <> -1 then begin
+        Result := True;
+        Exit;
+      end;
+    end;
+    Item := Item.ClassParent;
+  end;
+end;
+
+function TCoolTranslator.GetLangFileDir: string;
+begin
+  Result := FPOFilesFolder;
+  if Copy(Result, 1, 1) <> DirectorySeparator then
+    Result := ExtractFileDir(UTF8Encode(Application.ExeName)) +
+      DirectorySeparator + Result;
+end;
+
+procedure TCoolTranslator.LanguageListToStrings(Strings: TStrings);
+var
+  I: Integer;
+  ItemName: string;
+begin
+  with Strings do begin
+    Clear;
+    for I := 0 to Languages.Count - 1 do
+    with TLanguage(Languages[I]) do
+      if Available then begin
+        ItemName := Name;
+        if Code <> '' then ItemName := ItemName + ' (' + Code + ')';
+        AddObject(ItemName, Languages[I]);
+      end;
+  end;
+end;
+
+procedure TCoolTranslator.TranslateResourceStrings(PoFileName: string);
+begin
+  Translations.TranslateResourceStrings(PoFileName);
+end;
+
+procedure TCoolTranslator.TranslateUnitResourceStrings(UnitName: string;
+  PoFileName: string);
+begin
+  Translations.TranslateUnitResourceStrings(UnitName, PoFileName);
+end;
+
+function TCoolTranslator.TranslateText(Identifier, Text: string): string;
+var
+  I: Integer;
+begin
+  Result := '';
+  if Text <> '' then begin
+    for I := 0 to FPoFiles.Count - 1 do begin
+      Result := TPoFile(FPOFiles[I]).Translate(Identifier, Text);
+      if Result <> Text then Break;
+    end;
+    if Result = '' then Result := Text;
+  end else Result := '';
+end;
+
+procedure TCoolTranslator.AddExcludes(AClassType: TClass; PropertyName: string
+  );
+var
+  NewItem: TComponentExcludes;
+begin
+  NewItem := ComponentExcludes.FindByClassType(AClassType);
+  if not Assigned(NewItem) then begin
+    NewItem := TComponentExcludes.Create;
+    NewItem.ExcludedClassType := AClassType;
+    ComponentExcludes.Add(NewItem);
+  end;
+  NewItem.PropertyExcludes.Add(PropertyName);
+end;
+
+procedure TCoolTranslator.CheckLanguageFiles;
+var
+  I: Integer;
+  LangDir: string;
+begin
+  LangDir := GetLangFileDir;
+  TLanguage(Languages[0]).Available := True; // Automatic
+
+  for I := 1 to Languages.Count - 1 do
+  with TLanguage(Languages[I]) do begin
+    Available := FileExists(LangDir + DirectorySeparator + ExtractFileNameOnly(Application.ExeName) +
+      '.' + Code + ExtensionSeparator + 'po') or (Code = 'en');
+  end;
+end;
+
+constructor TCoolTranslator.Create(AOwner: TComponent);
+begin
+  inherited;
+  FPOFiles := TObjectList.Create;
+  ComponentExcludes := TComponentExcludesList.Create;
+  Languages := TLanguageList.Create;
+  POFilesFolder := 'Languages';
+  CheckLanguageFiles;
+
+  // LCL
+  AddExcludes(TComponent, 'Name');
+  //AddExcludes(TAction, 'Category');
+  AddExcludes(TControl, 'HelpKeyword');
+end;
+
+destructor TCoolTranslator.Destroy;
+begin
+  FPOFiles.Free;
+  Languages.Free;
+  ComponentExcludes.Free;
+  inherited Destroy;
+end;
+
+function TCoolTranslator.GetLocale: string;
+var
+  Lang: string;
+  I: Integer;
+  T: string;
+begin
+  // Win32 user may decide to override locale with LANG variable.
+  Lang := GetEnvironmentVariable('LANG');
+
+  // Use user selected language
+  if Assigned(Language) and (Language.Code <> '') then
+    Lang := Language.Code;
+
+  if Lang = '' then begin
+    for i := 1 to Paramcount - 1 do
+      if (ParamStr(i) = '--LANG') or (ParamStr(i) = '-l') or
+        (ParamStr(i) = '--lang') then
+        Lang := ParamStr(i + 1);
+  end;
+  if Lang = '' then
+    LCLGetLanguageIDs(Lang, T);
+
+  if Assigned(Language) and (Language.Code = '') and Assigned(FOnAutomaticLanguage) then begin
+    Lang := FOnAutomaticLanguage(Lang);
+  end;
+
+  Result := Lang;
+end;
+
+function TCoolTranslator.GetLocaleShort: string;
+begin
+  Result := Copy(GetLocale, 1, 2);
+end;
+
+function TCoolTranslator.FindLocaleFileName(LCExt: string): string;
+var
+  T: string;
+  Lang: string;
+begin
+  Result := '';
+  Lang := GetLocale;
+
+  Result := GetLocaleFileName(Lang, LCExt);
+  if Result <> '' then
+    Exit;
+
+  Result := ChangeFileExt(ParamStr(0), LCExt);
+  if FileExistsUTF8(Result) then
+    Exit;
+
+  Result := '';
+end;
+
+function TCoolTranslator.GetLocaleFileName(const LangID, LCExt: string): string;
+var
+  LangShortID: string;
+  FormatLang: string;
+begin
+  if LangID <> '' then FormatLang := '.%s' else FormatLang := '';
+
+  begin
+
+    // ParamStrUTF8(0) is said not to work properly in linux, but I've tested it
+    Result := ExtractFilePath(ParamStrUTF8(0)) + LangID +
+      DirectorySeparator + ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), LCExt);
+    if FileExistsUTF8(Result) then
+      exit;
+
+    Result := ExtractFilePath(ParamStrUTF8(0)) + 'languages' + DirectorySeparator + LangID +
+      DirectorySeparator + ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), LCExt);
+    if FileExistsUTF8(Result) then
+      exit;
+
+    Result := ExtractFilePath(ParamStrUTF8(0)) + 'locale' + DirectorySeparator
+      + LangID + DirectorySeparator + ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), LCExt);
+    if FileExistsUTF8(Result) then
+      exit;
+
+    Result := ExtractFilePath(ParamStrUTF8(0)) + 'locale' + DirectorySeparator
+      + LangID + DirectorySeparator + 'LC_MESSAGES' + DirectorySeparator +
+      ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), LCExt);
+    if FileExistsUTF8(Result) then
+      exit;
+
+    {$IFDEF UNIX}
+    // In unix-like systems we can try to search for global locale
+    Result := '/usr/share/locale/' + LangID + '/LC_MESSAGES/' +
+      ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), LCExt);
+    if FileExistsUTF8(Result) then
+      exit;
+    {$ENDIF}
+    // Let us search for reducted files
+    LangShortID := copy(LangID, 1, 2);
+    // At first, check all was checked
+    Result := ExtractFilePath(ParamStrUTF8(0)) + LangShortID +
+      DirectorySeparator + ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), LCExt);
+    if FileExistsUTF8(Result) then
+      exit;
+
+    Result := ExtractFilePath(ParamStrUTF8(0)) + 'languages' + DirectorySeparator +
+      LangShortID + DirectorySeparator + ChangeFileExt(
+      ExtractFileName(ParamStrUTF8(0)), LCExt);
+    if FileExistsUTF8(Result) then
+      exit;
+
+    Result := ExtractFilePath(ParamStrUTF8(0)) + 'locale' + DirectorySeparator
+      + LangShortID + DirectorySeparator + ChangeFileExt(
+      ExtractFileName(ParamStrUTF8(0)), LCExt);
+    if FileExistsUTF8(Result) then
+      exit;
+
+    Result := ExtractFilePath(ParamStrUTF8(0)) + 'locale' + DirectorySeparator
+      + LangShortID + DirectorySeparator + 'LC_MESSAGES' + DirectorySeparator +
+      ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), LCExt);
+    if FileExistsUTF8(Result) then
+      exit;
+
+    // Full language in file name - this will be default for the project
+    // We need more careful handling, as it MAY result in incorrect filename
+    try
+      Result := ExtractFilePath(ParamStrUTF8(0)) + ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), Format(FormatLang, [LangID])) + LCExt;
+      if FileExistsUTF8(Result) then
+        exit;
+      // Common location (like in Lazarus)
+      Result := ExtractFilePath(ParamStrUTF8(0)) + 'locale' + DirectorySeparator +
+        ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), Format(FormatLang, [LangID])) + LCExt;
+      if FileExistsUTF8(Result) then
+        exit;
+
+      Result := ExtractFilePath(ParamStrUTF8(0)) + 'languages' +
+        DirectorySeparator + ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), Format(FormatLang, [LangID])) + LCExt;
+      if FileExistsUTF8(Result) then
+        exit;
+    except
+      Result := ''; // Or do something else (useless)
+    end;
+
+    {$IFDEF UNIX}
+    Result := '/usr/share/locale/' + LangShortID + '/LC_MESSAGES/' +
+      ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), LCExt);
+    if FileExistsUTF8(Result) then
+      exit;
+    {$ENDIF}
+    Result := ExtractFilePath(ParamStrUTF8(0)) + ChangeFileExt(
+      ExtractFileName(ParamStrUTF8(0)), Format(FormatLang, [LangShortID])) + LCExt;
+    if FileExistsUTF8(Result) then
+      exit;
+
+    Result := ExtractFilePath(ParamStrUTF8(0)) + 'locale' + DirectorySeparator +
+      ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), Format(FormatLang, [LangShortID])) + LCExt;
+    if FileExistsUTF8(Result) then
+      exit;
+
+    Result := ExtractFilePath(ParamStrUTF8(0)) + 'languages' + DirectorySeparator +
+      ChangeFileExt(ExtractFileName(ParamStrUTF8(0)), Format(FormatLang, [LangShortID])) + LCExt;
+    if FileExistsUTF8(Result) then
+      exit;
+  end;
+
+  Result := '';
+end;
+
+
+end.
+
Index: /trunk/Packages/CoolTranslator/ULanguages.pas
===================================================================
--- /trunk/Packages/CoolTranslator/ULanguages.pas	(revision 40)
+++ /trunk/Packages/CoolTranslator/ULanguages.pas	(revision 40)
@@ -0,0 +1,447 @@
+unit ULanguages;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Contnrs;
+
+type
+  TLanguage = class
+    Name: string;
+    Code: string;
+    Available: Boolean;
+  end;
+
+  { TLanguageList }
+
+  TLanguageList = class(TObjectList)
+    function SearchByCode(ACode: string): TLanguage;
+    procedure AddNew(Code: string; Name: string);
+    constructor Create;
+  end;
+
+
+resourcestring
+  SLangAuto = 'Automatic';
+  SLang_aa = 'Afar';
+  SLang_ab = 'Abkhazian';
+  SLang_ae = 'Avestan';
+  SLang_af = 'Afrikaans';
+  SLang_ak = 'Akan';
+  SLang_am = 'Amharic';
+  SLang_an = 'Aragonese';
+  SLang_ar = 'Arabic';
+  SLang_as = 'Assamese';
+  SLang_av = 'Avaric';
+  SLang_ay = 'Aymara';
+  SLang_az = 'Azerbaijani';
+  SLang_ba = 'Bashkir';
+  SLang_be = 'Belarusian';
+  SLang_bg = 'Bulgarian';
+  SLang_bh = 'Bihari';
+  SLang_bi = 'Bislama';
+  SLang_bm = 'Bambara';
+  SLang_bn = 'Bengali';
+  SLang_bo = 'Tibetan';
+  SLang_br = 'Breton';
+  SLang_bs = 'Bosnian';
+  SLang_ca = 'Catalan';
+  SLang_ce = 'Chechen';
+  SLang_ch = 'Chamorro';
+  SLang_co = 'Corsican';
+  SLang_cr = 'Cree';
+  SLang_cs = 'Czech';
+  SLang_cv = 'Chuvash';
+  SLang_cy = 'Welsh';
+  SLang_da = 'Danish';
+  SLang_de = 'German';
+  SLang_de_AT = 'Austrian German';
+  SLang_de_CH = 'Swiss German';
+  SLang_dv = 'Divehi';
+  SLang_dz = 'Dzongkha';
+  SLang_ee = 'Ewe';
+  SLang_el = 'Greek';
+  SLang_en = 'English';
+  SLang_en_AU = 'Australian English';
+  SLang_en_CA = 'Canadian English';
+  SLang_en_GB = 'British English';
+  SLang_en_US = 'American English';
+  SLang_eo = 'Esperanto';
+  SLang_es = 'Spanish';
+  SLang_et = 'Estonian';
+  SLang_eu = 'Basque';
+  SLang_fa = 'Persian';
+  SLang_ff = 'Fulah';
+  SLang_fi = 'Finnish';
+  SLang_fj = 'Fijian';
+  SLang_fo = 'Faroese';
+  SLang_fr = 'French';
+  SLang_fr_BE = 'Walloon';
+  SLang_fy = 'Frisian';
+  SLang_ga = 'Irish';
+  SLang_gd = 'Gaelic';
+  SLang_gl = 'Gallegan';
+  SLang_gn = 'Guarani';
+  SLang_gu = 'Gujarati';
+  SLang_gv = 'Manx';
+  SLang_ha = 'Hausa';
+  SLang_he = 'Hebrew';
+  SLang_hi = 'Hindi';
+  SLang_ho = 'Hiri Motu';
+  SLang_hr = 'Croatian';
+  SLang_ht = 'Haitian';
+  SLang_hu = 'Hungarian';
+  SLang_hy = 'Armenian';
+  SLang_hz = 'Herero';
+  SLang_ia = 'Interlingua';
+  SLang_id = 'Indonesian';
+  SLang_ie = 'Interlingue';
+  SLang_ig = 'Igbo';
+  SLang_ii = 'Sichuan Yi';
+  SLang_ik = 'Inupiaq';
+  SLang_io = 'Ido';
+  SLang_is = 'Icelandic';
+  SLang_it = 'Italian';
+  SLang_iu = 'Inuktitut';
+  SLang_ja = 'Japanese';
+  SLang_jv = 'Javanese';
+  SLang_ka = 'Georgian';
+  SLang_kg = 'Kongo';
+  SLang_ki = 'Kikuyu';
+  SLang_kj = 'Kuanyama';
+  SLang_kk = 'Kazakh';
+  SLang_kl = 'Greenlandic';
+  SLang_km = 'Khmer';
+  SLang_kn = 'Kannada';
+  SLang_ko = 'Korean';
+  SLang_kr = 'Kanuri';
+  SLang_ks = 'Kashmiri';
+  SLang_ku = 'Kurdish';
+  SLang_kw = 'Cornish';
+  SLang_kv = 'Komi';
+  SLang_ky = 'Kirghiz';
+  SLang_la = 'Latin';
+  SLang_lb = 'Luxembourgish';
+  SLang_lg = 'Ganda';
+  SLang_li = 'Limburgan';
+  SLang_ln = 'Lingala';
+  SLang_lo = 'Lao';
+  SLang_lt = 'Lithuanian';
+  SLang_lu = 'Luba-Katanga';
+  SLang_lv = 'Latvian';
+  SLang_mg = 'Malagasy';
+  SLang_mh = 'Marshallese';
+  SLang_mi = 'Maori';
+  SLang_mk = 'Macedonian';
+  SLang_ml = 'Malayalam';
+  SLang_mn = 'Mongolian';
+  SLang_mo = 'Moldavian';
+  SLang_mr = 'Marathi';
+  SLang_ms = 'Malay';
+  SLang_mt = 'Maltese';
+  SLang_my = 'Burmese';
+  SLang_na = 'Nauru';
+  SLang_nb = 'Norwegian Bokmaal';
+  SLang_nd = 'Ndebele, North';
+  SLang_ne = 'Nepali';
+  SLang_ng = 'Ndonga';
+  SLang_nl = 'Dutch';
+  SLang_nl_BE = 'Flemish';
+  SLang_nn = 'Norwegian Nynorsk';
+  SLang_no = 'Norwegian';
+  SLang_nr = 'Ndebele, South';
+  SLang_nv = 'Navajo';
+  SLang_ny = 'Chichewa';
+  SLang_oc = 'Occitan';
+  SLang_oj = 'Ojibwa';
+  SLang_om = 'Oromo';
+  SLang_or = 'Oriya';
+  SLang_os = 'Ossetian';
+  SLang_pa = 'Panjabi';
+  SLang_pi = 'Pali';
+  SLang_pl = 'Polish';
+  SLang_ps = 'Pushto';
+  SLang_pt = 'Portuguese';
+  SLang_pt_BR = 'Brazilian Portuguese';
+  SLang_qu = 'Quechua';
+  SLang_rm = 'Raeto-Romance';
+  SLang_rn = 'Rundi';
+  SLang_ro = 'Romanian';
+  SLang_ru = 'Russian';
+  SLang_rw = 'Kinyarwanda';
+  SLang_sa = 'Sanskrit';
+  SLang_sc = 'Sardinian';
+  SLang_sd = 'Sindhi';
+  SLang_se = 'Northern Sami';
+  SLang_sg = 'Sango';
+  SLang_si = 'Sinhalese';
+  SLang_sk = 'Slovak';
+  SLang_sl = 'Slovenian';
+  SLang_sm = 'Samoan';
+  SLang_sn = 'Shona';
+  SLang_so = 'Somali';
+  SLang_sq = 'Albanian';
+  SLang_sr = 'Serbian';
+  SLang_ss = 'Swati';
+  SLang_st = 'Sotho, Southern';
+  SLang_su = 'Sundanese';
+  SLang_sv = 'Swedish';
+  SLang_sw = 'Swahili';
+  SLang_ta = 'Tamil';
+  SLang_te = 'Telugu';
+  SLang_tg = 'Tajik';
+  SLang_th = 'Thai';
+  SLang_ti = 'Tigrinya';
+  SLang_tk = 'Turkmen';
+  SLang_tl = 'Tagalog';
+  SLang_tn = 'Tswana';
+  SLang_to = 'Tonga';
+  SLang_tr = 'Turkish';
+  SLang_ts = 'Tsonga';
+  SLang_tt = 'Tatar';
+  SLang_tw = 'Twi';
+  SLang_ty = 'Tahitian';
+  SLang_ug = 'Uighur';
+  SLang_uk = 'Ukrainian';
+  SLang_ur = 'Urdu';
+  SLang_uz = 'Uzbek';
+  SLang_ve = 'Venda';
+  SLang_vi = 'Vietnamese';
+  SLang_vo = 'Volapuk';
+  SLang_wa = 'Walloon';
+  SLang_wo = 'Wolof';
+  SLang_xh = 'Xhosa';
+  SLang_yi = 'Yiddish';
+  SLang_yo = 'Yoruba';
+  SLang_za = 'Zhuang';
+  SLang_zh = 'Chinese';
+  SLang_zu = 'Zulu';
+
+implementation
+
+
+{ TLanguageList }
+
+function TLanguageList.SearchByCode(ACode: string): TLanguage;
+var
+  I: Integer;
+begin
+  I := 0;
+  while (I < Count) and (TLanguage(Items[I]).Code < ACode) do Inc(I);
+  if I < Count then Result := TLanguage(Items[I])
+    else Result := nil;
+end;
+
+procedure TLanguageList.AddNew(Code: string; Name: string);
+var
+  NewItem: TLanguage;
+begin
+  NewItem := TLanguage.Create;
+  NewItem.Name := Name;
+  NewItem.Code := Code;
+  Add(NewItem);
+end;
+
+constructor TLanguageList.Create;
+begin
+  inherited Create;
+  AddNew('', SLangAuto);
+  AddNew('aa', SLang_aa);
+  AddNew('ab', SLang_ab);
+  AddNew('ae', SLang_ae);
+  AddNew('af', SLang_af);
+  AddNew('ak', SLang_ak);
+  AddNew('am', SLang_am);
+  AddNew('an', SLang_an);
+  AddNew('ar', SLang_ar);
+  AddNew('as', SLang_as);
+  AddNew('av', SLang_av);
+  AddNew('ay', SLang_ay);
+  AddNew('az', SLang_az);
+  AddNew('ba', SLang_ba);
+  AddNew('be', SLang_be);
+  AddNew('bg', SLang_bg);
+  AddNew('bh', SLang_bh);
+  AddNew('bi', SLang_bi);
+  AddNew('bm', SLang_bm);
+  AddNew('bn', SLang_bn);
+  AddNew('bo', SLang_bo);
+  AddNew('br', SLang_br);
+  AddNew('bs', SLang_bs);
+  AddNew('ca', SLang_ca);
+  AddNew('ce', SLang_ce);
+  AddNew('ch', SLang_ch);
+  AddNew('co', SLang_co);
+  AddNew('cr', SLang_cr);
+  AddNew('cs', SLang_cs);
+  AddNew('cv', SLang_cv);
+  AddNew('cy', SLang_cy);
+  AddNew('da', SLang_da);
+  AddNew('de', SLang_de);
+  AddNew('de_AT', SLang_de_AT);
+  AddNew('de_CH', SLang_de_CH);
+  AddNew('dv', SLang_dv);
+  AddNew('dz', SLang_dz);
+  AddNew('ee', SLang_ee);
+  AddNew('el', SLang_el);
+  AddNew('en', SLang_en);
+  AddNew('en_AU', SLang_en_AU);
+  AddNew('en_CA', SLang_en_CA);
+  AddNew('en_GB', SLang_en_GB);
+  AddNew('en_US', SLang_en_US);
+  AddNew('eo', SLang_eo);
+  AddNew('es', SLang_es);
+  AddNew('et', SLang_et);
+  AddNew('eu', SLang_eu);
+  AddNew('fa', SLang_fa);
+  AddNew('ff', SLang_ff);
+  AddNew('fi', SLang_fi);
+  AddNew('fj', SLang_fj);
+  AddNew('fo', SLang_fo);
+  AddNew('fr', SLang_fr);
+  AddNew('fr_BE', SLang_fr_BE);
+  AddNew('fy', SLang_fy);
+  AddNew('ga', SLang_ga);
+  AddNew('gd', SLang_gd);
+  AddNew('gl', SLang_gl);
+  AddNew('gn', SLang_gn);
+  AddNew('gu', SLang_gu);
+  AddNew('gv', SLang_gv);
+  AddNew('ha', SLang_ha);
+  AddNew('he', SLang_he);
+  AddNew('hi', SLang_hi);
+  AddNew('ho', SLang_ho);
+  AddNew('hr', SLang_hr);
+  AddNew('ht', SLang_ht);
+  AddNew('hu', SLang_hu);
+  AddNew('hy', SLang_hy);
+  AddNew('hz', SLang_hz);
+  AddNew('ia', SLang_ia);
+  AddNew('id', SLang_id);
+  AddNew('ie', SLang_ie);
+  AddNew('ig', SLang_ig);
+  AddNew('ii', SLang_ii);
+  AddNew('ik', SLang_ik);
+  AddNew('io', SLang_io);
+  AddNew('is', SLang_is);
+  AddNew('it', SLang_it);
+  AddNew('iu', SLang_iu);
+  AddNew('ja', SLang_ja);
+  AddNew('jv', SLang_jv);
+  AddNew('ka', SLang_ka);
+  AddNew('kg', SLang_kg);
+  AddNew('ki', SLang_ki);
+  AddNew('kj', SLang_kj);
+  AddNew('kk', SLang_kk);
+  AddNew('kl', SLang_kl);
+  AddNew('km', SLang_km);
+  AddNew('kn', SLang_kn);
+  AddNew('ko', SLang_ko);
+  AddNew('kr', SLang_kr);
+  AddNew('ks', SLang_ks);
+  AddNew('ku', SLang_ku);
+  AddNew('kw', SLang_kw);
+  AddNew('kv', SLang_kv);
+  AddNew('ky', SLang_ky);
+  AddNew('la', SLang_la);
+  AddNew('lb', SLang_lb);
+  AddNew('lg', SLang_lg);
+  AddNew('li', SLang_li);
+  AddNew('ln', SLang_ln);
+  AddNew('lo', SLang_lo);
+  AddNew('lt', SLang_lt);
+  AddNew('lu', SLang_lu);
+  AddNew('lv', SLang_lv);
+  AddNew('mg', SLang_mg);
+  AddNew('mh', SLang_mh);
+  AddNew('mi', SLang_mi);
+  AddNew('mk', SLang_mk);
+  AddNew('ml', SLang_ml);
+  AddNew('mn', SLang_mn);
+  AddNew('mo', SLang_mo);
+  AddNew('mr', SLang_mr);
+  AddNew('ms', SLang_ms);
+  AddNew('mt', SLang_mt);
+  AddNew('my', SLang_my);
+  AddNew('na', SLang_na);
+  AddNew('nb', SLang_nb);
+  AddNew('nd', SLang_nd);
+  AddNew('ne', SLang_ne);
+  AddNew('ng', SLang_ng);
+  AddNew('nl', SLang_nl);
+  AddNew('nl_BE', SLang_nl_BE);
+  AddNew('nn', SLang_nn);
+  AddNew('no', SLang_no);
+  AddNew('nr', SLang_nr);
+  AddNew('nv', SLang_nv);
+  AddNew('ny', SLang_ny);
+  AddNew('oc', SLang_oc);
+  AddNew('oj', SLang_oj);
+  AddNew('om', SLang_om);
+  AddNew('or', SLang_or);
+  AddNew('os', SLang_os);
+  AddNew('pa', SLang_pa);
+  AddNew('pi', SLang_pi);
+  AddNew('pl', SLang_pl);
+  AddNew('ps', SLang_ps);
+  AddNew('pt', SLang_pt);
+  AddNew('pt_BR', SLang_pt_BR);
+  AddNew('qu', SLang_qu);
+  AddNew('rm', SLang_rm);
+  AddNew('rn', SLang_rn);
+  AddNew('ro', SLang_ro);
+  AddNew('ru', SLang_ru);
+  AddNew('rw', SLang_rw);
+  AddNew('sa', SLang_sa);
+  AddNew('sc', SLang_sc);
+  AddNew('sd', SLang_sd);
+  AddNew('se', SLang_se);
+  AddNew('sg', SLang_sg);
+  AddNew('si', SLang_si);
+  AddNew('sk', SLang_sk);
+  AddNew('sl', SLang_sl);
+  AddNew('sm', SLang_sm);
+  AddNew('sn', SLang_sn);
+  AddNew('so', SLang_so);
+  AddNew('sq', SLang_sq);
+  AddNew('sr', SLang_sr);
+  AddNew('ss', SLang_ss);
+  AddNew('st', SLang_st);
+  AddNew('su', SLang_su);
+  AddNew('sv', SLang_sv);
+  AddNew('sw', SLang_sw);
+  AddNew('ta', SLang_ta);
+  AddNew('te', SLang_te);
+  AddNew('tg', SLang_tg);
+  AddNew('th', SLang_th);
+  AddNew('ti', SLang_ti);
+  AddNew('tk', SLang_tk);
+  AddNew('tl', SLang_tl);
+  AddNew('tn', SLang_tn);
+  AddNew('to', SLang_to);
+  AddNew('tr', SLang_tr);
+  AddNew('ts', SLang_ts);
+  AddNew('tt', SLang_tt);
+  AddNew('tw', SLang_tw);
+  AddNew('ty', SLang_ty);
+  AddNew('ug', SLang_ug);
+  AddNew('uk', SLang_uk);
+  AddNew('ur', SLang_ur);
+  AddNew('uz', SLang_uz);
+  AddNew('ve', SLang_ve);
+  AddNew('vi', SLang_vi);
+  AddNew('vo', SLang_vo);
+  AddNew('wa', SLang_wa);
+  AddNew('wo', SLang_wo);
+  AddNew('xh', SLang_xh);
+  AddNew('yi', SLang_yi);
+  AddNew('yo', SLang_yo);
+  AddNew('za', SLang_za);
+  AddNew('zh', SLang_zh);
+  AddNew('zu', SLang_zu);
+end;
+
+end.
+
