294 lines
9.1 KiB
ObjectPascal
294 lines
9.1 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The Original Code is: JvgLanguageLoader.PAS, released on 2003-01-15.
|
|
|
|
The Initial Developer of the Original Code is Andrey V. Chudin, [chudin att yandex dott ru]
|
|
Portions created by Andrey V. Chudin are Copyright (C) 2003 Andrey V. Chudin.
|
|
All Rights Reserved.
|
|
|
|
Contributor(s):
|
|
Michael Beck [mbeck att bigfoot dott com].
|
|
Burov Dmitry, translation of russian text.
|
|
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|
located at http://jvcl.sourceforge.net
|
|
|
|
Description:
|
|
eng:
|
|
Load new string resources from file to components. Uses RTTI
|
|
|
|
Replaces the found lines(strings) from one language to another if found in dictionary
|
|
|
|
Dictionary is text like:
|
|
Langauge1_line=Language2_line
|
|
..
|
|
Language1_line=Language2_line
|
|
|
|
rus:
|
|
Çàìåíÿåò ïî ñëîâàðþ èç ôàéëà âñå íàéäåííûå ñòðîêè îäíîãî ÿçûêà íà äðóãîé
|
|
Ñëîâàðü â âèäå òåêñòà âèäà:
|
|
Ñòðîêà íà ÿçûêå 1=Ñòðîêà íà ÿçûêå 2
|
|
...
|
|
Ñòðîêà íà ÿçûêå 1=Ñòðîêà íà ÿçûêå 2
|
|
|
|
Known Issues:
|
|
-----------------------------------------------------------------------------}
|
|
// $Id: JvgLanguageLoader.pas,v 1.17 2005/09/15 07:22:55 marquardt Exp $
|
|
|
|
unit JvgLanguageLoader;
|
|
|
|
{$I jvcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF USEJVCL}
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
{$ENDIF USEJVCL}
|
|
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
|
|
{$IFDEF USEJVCL}
|
|
ComCtrls, Grids,
|
|
JvComponentBase;
|
|
{$ELSE}
|
|
ComCtrls, Grids;
|
|
{$ENDIF USEJVCL}
|
|
|
|
type
|
|
TLanguageLoaderOptions = set of (lofTrimSpaces);
|
|
//{îïöèÿ óäàëåíèÿ íà÷àëüíûõ è çàâåðøàþùèõ ïðîáåëîâ}
|
|
{ Option to Trim first and last spaces [translated] }
|
|
|
|
{$IFDEF USEJVCL}
|
|
TJvgLanguageLoader = class(TJvComponent)
|
|
{$ELSE}
|
|
TJvgLanguageLoader = class(TComponent)
|
|
{$ENDIF USEJVCL}
|
|
private
|
|
FList: TStringList;
|
|
FOptions: TLanguageLoaderOptions;
|
|
function TranslateString(AText: string): string;
|
|
protected
|
|
procedure UpdateComponent(Component: TPersistent); virtual;
|
|
public
|
|
procedure LoadLanguage(Component: TComponent; const FileName: string);
|
|
published
|
|
property Options: TLanguageLoaderOptions read FOptions write FOptions;
|
|
end;
|
|
|
|
procedure LoadLanguage(Component: TComponent; const FileName: string;
|
|
Options: TLanguageLoaderOptions);
|
|
|
|
{$IFDEF USEJVCL}
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$RCSfile: JvgLanguageLoader.pas,v $';
|
|
Revision: '$Revision: 1.17 $';
|
|
Date: '$Date: 2005/09/15 07:22:55 $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
{$ENDIF USEJVCL}
|
|
|
|
implementation
|
|
|
|
uses
|
|
TypInfo;
|
|
|
|
//{Ô-èÿ äëÿ çàãðóçêè ñëîâàðÿ áåç ïðåäâàðèòåëüíîãî ñîçäàíèÿ êîìïîíåíòà}
|
|
{ Function to load dictionary without previous creation of the component [translated] }
|
|
|
|
procedure LoadLanguage(Component: TComponent; const FileName: string;
|
|
Options: TLanguageLoaderOptions);
|
|
var
|
|
LanguageLoader: TJvgLanguageLoader;
|
|
begin
|
|
LanguageLoader := TJvgLanguageLoader.Create(nil);
|
|
try
|
|
LanguageLoader.LoadLanguage(Component, FileName);
|
|
finally
|
|
LanguageLoader.Free;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvgLanguageLoader } =================================================
|
|
|
|
//{ Çàãðóçêà ñëîâàðÿ, îáõîä óêàçàííîãî êîìïîíåíòà è }
|
|
//{ âñåõ åãî äî÷åðíèõ êîìïîíåíòîâ }
|
|
{ Loading dictionary, passing the given component and all his children components
|
|
[translated] }
|
|
|
|
procedure TJvgLanguageLoader.LoadLanguage(Component: TComponent; const FileName: string);
|
|
|
|
procedure UpdateAllComponents(Component: TComponent);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
//{ îáðàáîòêà ñâîöñòâ êîìïîíåíòà }
|
|
{ Processing the component's properties [translated] }
|
|
UpdateComponent(Component);
|
|
for I := 0 to Component.ComponentCount - 1 do
|
|
UpdateAllComponents(Component.Components[I]);
|
|
end;
|
|
|
|
begin
|
|
FList := TStringList.Create;
|
|
try
|
|
//{ Çàãðóçêà ñëîâàðÿ èç çàäàííîãî ôàéëà }
|
|
{ Loading dictionary from given file }
|
|
FList.LoadFromFile(FileName);
|
|
FList.Sorted := True;
|
|
UpdateAllComponents(Component);
|
|
finally
|
|
FreeAndNil(FList);
|
|
end;
|
|
end;
|
|
|
|
//{ Ïðîõîä ïî âñåì ñâîéñòâàì êîìïîíåíòà }
|
|
//{ Äëÿ âñåõ ñòðîêîâûõ ñâîéñòâ - çàãðóçêà ïåðåâîäà èç ñîîâàðÿ }
|
|
{ Passing(iterating) all the component's properties
|
|
For all string properties - load the translation from dictionary [translated] }
|
|
|
|
procedure TJvgLanguageLoader.UpdateComponent(Component: TPersistent);
|
|
var
|
|
PropInfo: PPropInfo;
|
|
TypeInf, PropTypeInf: PTypeInfo;
|
|
TypeData: PTypeData;
|
|
I, J: Integer;
|
|
AName, PropName, StringPropValue: string;
|
|
PropList: PPropList;
|
|
NumProps: Word;
|
|
PropObject: TObject;
|
|
begin
|
|
{ Playing with RTTI }
|
|
TypeInf := Component.ClassInfo;
|
|
AName := TypeInf^.Name;
|
|
TypeData := GetTypeData(TypeInf);
|
|
NumProps := TypeData^.PropCount;
|
|
|
|
GetMem(PropList, NumProps * SizeOf(Pointer));
|
|
|
|
try
|
|
GetPropInfos(TypeInf, PropList);
|
|
|
|
for I := 0 to NumProps - 1 do
|
|
begin
|
|
PropName := PropList^[I]^.Name;
|
|
|
|
PropTypeInf := PropList^[I]^.PropType^;
|
|
PropInfo := PropList^[I];
|
|
|
|
case PropTypeInf^.Kind of
|
|
tkString, tkLString:
|
|
//{ Ïåðåâîäèòü ñâîéñòâî Name íå ñëåäóåò }
|
|
{ .Name is not to be translated [translated] }
|
|
if PropName <> 'Name' then
|
|
begin
|
|
//{ Ïîëó÷åíèå çíà÷åíèÿ ñâîéñòâà è ïîèñê ïåðåâîäà â ñëîâàðå }
|
|
{ Retrieving the property's value and searching for translation in
|
|
dictionary [translated] }
|
|
StringPropValue := GetStrProp(Component, PropInfo);
|
|
SetStrProp(Component, PropInfo,
|
|
TranslateString(StringPropValue));
|
|
end;
|
|
tkClass:
|
|
begin
|
|
PropObject := GetObjectProp(Component, PropInfo); {, TPersistent}
|
|
|
|
if Assigned(PropObject) then
|
|
begin
|
|
//{ Äëÿ äî÷åðíèõ ñâîéñòâ-êëàññîâ âûçîâ ïðîñìîòðà ñâîéñòâ }
|
|
{ For children properties-classes calling iterate again [translated] }
|
|
if PropObject is TPersistent then
|
|
UpdateComponent(PropObject as TPersistent);
|
|
|
|
//{ Èíäèâèäóàëüíûé ïîäõîä ê íåêîòîðûì êëàññàì }
|
|
{ Specific handling of some certain classes [translated] }
|
|
if PropObject is TStrings then
|
|
begin
|
|
TStrings(PropObject).BeginUpdate;
|
|
try
|
|
for J := 0 to TStrings(PropObject).Count - 1 do
|
|
TStrings(PropObject)[J] :=
|
|
TranslateString(TStrings(PropObject)[J]);
|
|
finally
|
|
TStrings(PropObject).EndUpdate;
|
|
end;
|
|
end
|
|
else
|
|
if PropObject is TTreeNodes then
|
|
begin
|
|
TTreeNodes(PropObject).BeginUpdate;
|
|
try
|
|
for J := 0 to TTreeNodes(PropObject).Count - 1 do
|
|
TTreeNodes(PropObject).Item[J].Text :=
|
|
TranslateString(TTreeNodes(PropObject).Item[J].Text);
|
|
finally
|
|
TTreeNodes(PropObject).EndUpdate;
|
|
end;
|
|
end
|
|
else
|
|
if PropObject is TListItems then
|
|
begin
|
|
TListItems(PropObject).BeginUpdate;
|
|
try
|
|
for J := 0 to TListItems(PropObject).Count - 1 do
|
|
TListItems(PropObject).Item[J].Caption :=
|
|
TranslateString(TListItems(PropObject).Item[J].Caption);
|
|
finally
|
|
TListItems(PropObject).EndUpdate;
|
|
end;
|
|
end;
|
|
//{ Çäåñü ìîæíî äîáàâèòü îáðàáîòêó îñòàëüíûõ êëàññîâ }
|
|
{ And here may be added more specific handlers for certain other
|
|
classes [translated] }
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
FreeMem(PropList, NumProps * SizeOf(Pointer));
|
|
end;
|
|
end;
|
|
|
|
//{ Ïîèñê ïåðåâîäà äëÿ çàäàííîé ñòðîêè â ñëîâàðå }
|
|
{ Searching for translation of given line in dictionary [translated] }
|
|
|
|
function TJvgLanguageLoader.TranslateString(AText: string): string;
|
|
begin
|
|
if AText <> '' then
|
|
begin
|
|
if lofTrimSpaces in Options then
|
|
AText := Trim(AText);
|
|
if Assigned(FList) and (FList.IndexOfName(AText) <> -1) then
|
|
Result := FList.Values[AText]
|
|
else
|
|
Result := AText;
|
|
end
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
{$IFDEF USEJVCL}
|
|
{$IFDEF UNITVERSIONING}
|
|
initialization
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
|
|
finalization
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
{$ENDIF USEJVCL}
|
|
|
|
end.
|
|
|