| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- {******************************************************************************}
- { CnPack For Delphi/C++Builder }
- { 中国人自己的开放源码第三方开发包 }
- { (C)Copyright 2001-2016 CnPack 开发组 }
- { ------------------------------------ }
- { }
- { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
- { 改和重新发布这一程序。 }
- { }
- { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
- { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
- { }
- { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
- { 还没有,可访问我们的网站: }
- { }
- { 网站地址:http://www.cnpack.org }
- { 电子邮件:master@cnpack.org }
- { }
- {******************************************************************************}
- unit CnHashLangStorage;
- {* |<PRE>
- ================================================================================
- * 软件名称:CnPack 多语包
- * 单元名称:Hash 文本多语存储组件单元
- * 单元作者:CnPack开发组
- * 备 注:该单元实现了Hash TXT 多语存储组件类
- * 开发平台:PWin2000 + Delphi 5.0
- * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7
- * 本 地 化:该单元中的字符串均符合本地化处理方式
- * 单元标识:$Id$
- * 修改记录:2004.10.23 V1.2
- * 修改初始化文件的处理方式
- * 2003.12.13 V1.1
- * InternalInit 中增加对 DefaultFont 的读入处理
- * 2003.08.20 V1.0
- * 创建单元,实现功能
- ================================================================================
- |</PRE>}
- interface
- {$I CnPack.inc}
- uses
- SysUtils, Classes, Windows, IniFiles, Dialogs, FileCtrl, CnCommon,
- CnConsts, CnLangConsts, CnHashMap, CnWideStrings, CnLangStorage, CnIniStrUtils;
- type
- TCnCustomHashLangStorage = class;
- TCnHashStringIterator = class(TInterfacedObject, ICnLangStringIterator)
- private
- FHashStorage: TCnCustomHashLangStorage;
- FEof: Boolean;
- FBof: Boolean;
- FFrontPattern: WideString;
- FKey: WideString;
- FValue: WideString;
- public
- constructor Create(AHashStorage: TCnCustomHashLangStorage);
- destructor Destroy; override;
- procedure StartIterate(const FrontPattern: WideString = '');
- procedure Previous;
- procedure Next;
- procedure EndIterate;
- procedure GetCurrentKeyValue(var Key:WideString; var Value: WideString);
- function GetCurrentString: WideString;
- function GetEof: Boolean;
- function GetBof: Boolean;
- property Eof: Boolean read GetEof;
- property Bof: Boolean read GetBof;
- end;
- TCnHashLangLoadFile = procedure(Sender: TObject; AFileName: WideString;
- AList: TCnWideStringList) of object;
- TCnCustomHashLangStorage = class(TCnCustomLangFileStorage)
- private
- FHashMap: TCnWideStrToWideStrHashMap;
- FListLength: Integer;
- FIncSize: Integer;
- FOnLoadFile: TCnHashLangLoadFile;
- procedure SetIncSize(const Value: Integer);
- procedure SetListLength(const Value: Integer);
- protected
- procedure InitHashMap;
- procedure AddStringToHashMap(const Key: WideString; const Value: WideString);
- procedure InitFromAFile(const AFileName: WideString); override;
- procedure CreateCurrentLanguage; override;
- procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
- procedure DoLoadFile(AFileName: WideString; AList: TCnWideStringList);
- property HashMap: TCnWideStrToWideStrHashMap read FHashMap;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- class function GetLanguageFileExt: WideString; override;
- {* 返回多语言文件的扩展名.TXT }
- function GetString(Name: WideString; var Value: WideString): Boolean; override;
- {* 获得一语言条目的翻译后的字符串 }
- procedure GetNamesList(List: TStrings); override;
- {* 获得当前语言的所有语言条目名称列表 }
- function IsLanguageFile(const FileName: WideString): Boolean; override;
- {* 判断一文件是否合法的语言文件 }
- procedure SetString(Name, Value: WideString); override;
- {* 保存一语言条目,如存在则覆盖,否则新增 }
- function CreateIterator: ICnLangStringIterator; override;
- {* 获得遍历器,如果子类不支持遍历,则必须返回 nil}
- function LoadCurrentLanguage: Boolean; override;
- {* 从 TXT 文件中载入当前语言条目,为翻译字串做准备 }
- procedure SaveCurrentLanguage; override;
- {* 保存当前语言文件 }
- procedure ClearCurrentLanguage; override;
- {* 删除当前语言的所有翻译条目列表,同时也保存本语言 }
- published
- property StorageMode;
- {* 多语存储方式 }
- property LanguagePath;
- {* 语言文件存储的统一路径 }
- property FileName;
- {* 按文件存储时的统一多语文件名 }
- property Languages;
- {* 语言对象列表 }
- property ListLength: Integer read FListLength write SetListLength;
- {* 初始列表大小 }
- property IncSize: Integer read FIncSize write SetIncSize;
- {* 重分配时增加的大小 }
- property AutoDetect;
- {* LanguagePath 改变时是否自动检测语言 }
- property OnLoadFile: TCnHashLangLoadFile read FOnLoadFile write FOnLoadFile;
- {* 自定义加载文件事件 }
- end;
- TCnHashLangFileStorage = class(TCnCustomHashLangStorage)
- published
- property StorageMode;
- {* 多语存储方式 }
- property LanguagePath;
- {* 语言文件存储的统一路径 }
- property Languages;
- {* 语言对象列表 }
- property FileName;
- {* 按文件存储时的统一多语文件名 }
- property ListLength;
- {* 初始列表大小 }
- property IncSize;
- {* 重分配时增加的大小 }
- property AutoDetect;
- {* LanguagePath 改变时是否自动检测语言 }
- end;
- implementation
- {************************** TCnCustomHashLangStorage **************************}
- constructor TCnCustomHashLangStorage.Create(AOwner: TComponent);
- begin
- inherited;
- Self.FListLength := 1024;
- Self.FIncSize := 2;
- end;
- destructor TCnCustomHashLangStorage.Destroy;
- begin
- if Assigned(FHashMap) then
- FHashMap.Free;
- inherited;
- end;
- procedure TCnCustomHashLangStorage.DoLoadFile(AFileName: WideString;
- AList: TCnWideStringList);
- begin
- if Assigned(FOnLoadFile) then
- FOnLoadFile(Self, AFileName, AList)
- else
- AList.LoadFromFile(AFileName);
- end;
- procedure TCnCustomHashLangStorage.CreateCurrentLanguage;
- begin
- InitHashMap;
- end;
- function TCnCustomHashLangStorage.GetString(Name: WideString; var Value: WideString):
- Boolean;
- begin
- Result := False;
- if Assigned(FHashMap) then
- begin
- Result := FHashMap.Find(Name, Value);
- if Result then
- Value := StringReplace(Value, SCnBR, SCnCRLF, [rfReplaceAll, rfIgnoreCase])
- else
- Value := '';
- end;
- end;
- function TCnCustomHashLangStorage.LoadCurrentLanguage: Boolean;
- var
- List: TCnWideStringList;
- i, EPos: Integer;
- S: WideString;
- begin
- Result := True;
- InitHashMap;
-
- List := TCnWideStringList.Create;
- try
- // 子类也要检查设计期是否有指定路径,类似于 Ini 那个
- if (csDesigning in ComponentState) and (LanguagePath = '') and (DesignLangPath <> '') then
- S := IncludeTrailingBackslash(DesignLangPath) + GetCurrentLanguageFileName
- else
- S := IncludeTrailingBackslash(LanguagePath) + GetCurrentLanguageFileName;
- DoLoadFile(S, List);
- except
- Result := False;
- List.Free;
- Exit;
- end;
- for i := 0 to List.Count - 1 do
- begin
- S := List[i];
- EPos := Pos(DefEqual, S);
- if EPos > 0 then
- AddStringToHashMap(Copy(S, 1, EPos - 1), Copy(S, EPos + 1,
- Length(S) - EPos))
- else
- AddStringToHashMap(Copy(S, 1, EPos - 1), '');
- end;
- List.Free;
- end;
- procedure TCnCustomHashLangStorage.SaveCurrentLanguage;
- var
- Key, Value, aFileName: WideString;
- List: TCnWideStringList;
- begin
- if Assigned(FHashMap) then
- begin
- List := TCnWideStringList.Create;
- try
- FHashMap.StartEnum;
- while FHashMap.GetNext(Key, Value) do
- List.Add(Key + DefEqual + Value);
- List.Sort;
- // 设计期如果被赋值了设计期文件存储的目录,则存到此目录下
- if (csDesigning in ComponentState) and (LanguagePath = '') and (DesignLangPath <> '') then
- aFileName := IncludeTrailingBackslash(DesignLangPath) + GetCurrentLanguageFileName
- else
- aFileName := IncludeTrailingBackslash(LanguagePath) + GetCurrentLanguageFileName;
- if not ForceDirectories(_CnExtractFilePath(aFileName)) then
- raise ELanguageStorageError.Create(SCnCanNotCreateDir + _CnExtractFilePath(aFileName));
- List.SaveToFile(aFileName, wlfUtf8);
- finally
- List.Free;
- end;
- end;
- end;
- procedure TCnCustomHashLangStorage.SetString(Name, Value: WideString);
- var
- myValue: WideString;
- begin
- if Assigned(FHashMap) then
- begin
- if FHashMap.Find(Name, myValue) then
- FHashMap.Delete(Name);
- AddStringToHashMap(Name, StringReplace(Value, SCnCRLF, SCnBR, [rfReplaceAll, rfIgnoreCase]));
- end;
- end;
- procedure TCnCustomHashLangStorage.GetNamesList(List: TStrings);
- var
- Key, Value: WideString;
- begin
- if List <> nil then
- begin
- List.Clear;
- if Assigned(FHashMap) then
- begin
- FHashMap.StartEnum;
- while FHashMap.GetNext(Key, Value) do
- List.Add(Key);
- if List is TStringList then
- (List as TStringList).Sort;
- end;
- end;
- end;
- procedure TCnCustomHashLangStorage.ClearCurrentLanguage;
- begin
- InitHashMap;
- SaveCurrentLanguage;
- end;
- class function TCnCustomHashLangStorage.GetLanguageFileExt: WideString;
- begin
- Result := '.txt';
- end;
- function TCnCustomHashLangStorage.IsLanguageFile(
- const FileName: WideString): Boolean;
- var
- List: TCnWideStringList;
- begin
- Result := False;
- List := TCnWideStringList.Create;
- try
- DoLoadFile(FileName, List);
- if List.Count > 0 then
- Result := Copy(List[0], 1, Length(SystemNamePrefix + SCnLanguageID)) =
- SystemNamePrefix + SCnLanguageID;
- finally
- List.Free;
- end;
- end;
- procedure TCnCustomHashLangStorage.InitHashMap;
- begin
- if Assigned(FHashMap) then
- FreeAndNil(FHashMap);
- FHashMap := TCnWideStrToWideStrHashMap.Create(FListLength, FIncSize);
- end;
- procedure TCnCustomHashLangStorage.SetIncSize(const Value: Integer);
- begin
- if Value > 0 then
- FIncSize := Value;
- end;
- procedure TCnCustomHashLangStorage.SetListLength(const Value: Integer);
- begin
- if Value > 0 then
- FListLength := Value;
- end;
- function TCnCustomHashLangStorage.CreateIterator: ICnLangStringIterator;
- begin
- Result := TCnHashStringIterator.Create(Self);
- end;
- procedure TCnCustomHashLangStorage.InitFromAFile(const AFileName: WideString);
- var
- List: TCnWideStringList;
- begin
- List := TCnWideStringList.Create;
- try
- with Languages.Add do
- begin
- LanguageFileName := _CnExtractFileName(_CnChangeFileExt(AFileName, ''));
- DoLoadFile(AFileName, List);
- try
- LanguageID := StrToIntDef(List.Values[SystemNamePrefix + SCnLanguageID], 0);
- except
- LanguageID := 0;
- end;
- if LanguageID <> 0 then
- begin
- LanguageName := List.Values[SystemNamePrefix + SCnLanguageName];
- Author := List.Values[SystemNamePrefix + SCnAuthor];
- AuthorEmail := List.Values[SystemNamePrefix + SCnAuthorEmail];
- if List.Values[SystemNamePrefix + SCnDefaultFont] <> '' then
- StringToFont(List.Values[SystemNamePrefix + SCnDefaultFont], DefaultFont);
- end
- else
- begin
- Self.FCurrentLanguageIndex := -1;
- Self.Languages.Delete(Index);
- end;
- end;
- finally
- List.Free;
- end;
- end;
- procedure TCnCustomHashLangStorage.GetComponentInfo(var AName, Author,
- Email, Comment: string);
- begin
- AName := SCnHashLangStorageName;
- Author := SCnPack_LiuXiao;
- Email := SCnPack_LiuXiaoEmail;
- Comment := SCnHashLangStorageComment;
- end;
- procedure TCnCustomHashLangStorage.AddStringToHashMap(const Key,
- Value: WideString);
- begin
- FHashMap.Add(Key, Value);
- end;
- { TCnHashStringIterator }
- constructor TCnHashStringIterator.Create(AHashStorage: TCnCustomHashLangStorage);
- begin
- inherited Create;
- FHashStorage := AHashStorage;
- end;
- destructor TCnHashStringIterator.Destroy;
- begin
- inherited;
- end;
- procedure TCnHashStringIterator.EndIterate;
- begin
- // Do Almost NOTHING.
- FKey := '';
- FValue := '';
- end;
- function TCnHashStringIterator.GetBof: Boolean;
- begin
- Result := FBof;
- end;
- procedure TCnHashStringIterator.GetCurrentKeyValue(var Key, Value: WideString);
- begin
- Key := FKey;
- Value := FValue;
- end;
- function TCnHashStringIterator.GetCurrentString: WideString;
- begin
- Result := FKey + DefEqual + FValue;
- end;
- function TCnHashStringIterator.GetEof: Boolean;
- begin
- Result := FEof;
- end;
- procedure TCnHashStringIterator.Next;
- begin
- if FHashStorage.FHashMap <> nil then
- begin
- repeat
- FEof := not FHashStorage.FHashMap.GetNext(FKey, FValue);
- until FEof or (FFrontPattern = '') or (Pos(FFrontPattern, FKey) = 1);
- end
- else
- FEof := True;
- end;
- procedure TCnHashStringIterator.Previous;
- begin
- raise ELanguageStorageError.Create('Previous operation NOT supported.');
- end;
- procedure TCnHashStringIterator.StartIterate(const FrontPattern: WideString);
- begin
- Assert(FHashStorage <> nil);
- if FHashStorage.FHashMap <> nil then
- begin
- FHashStorage.FHashMap.StartEnum;
- FFrontPattern := FrontPattern;
- repeat
- FEof := not FHashStorage.FHashMap.GetNext(FKey, FValue);
- until FEof or (FFrontPattern = '') or (Pos(FFrontPattern, FKey) = 1);
- FBof := FEof;
- end;
- end;
- end.
|