Componentes.Terceros.DevExp.../official/x.48/ExpressLibrary/Sources/cxLocalization.pas
2010-01-18 18:33:24 +00:00

826 lines
24 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ Express Cross Platform Library classes }
{ }
{ Copyright (c) 2000-2009 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSCROSSPLATFORMLIBRARY AND ALL }
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM }
{ ONLY. }
{ }
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
{ }
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
{ ADDITIONAL RESTRICTIONS. }
{ }
{********************************************************************}
unit cxLocalization;
{$I cxVer.inc}
interface
uses
Windows, Classes, Forms, SysUtils, cxClasses, IniFiles;
const
ANoActiveLanguage = 'English (Original translation)';
type
TcxLocalizerStorage = class;
TcxLocalizerStorageClass = class of TcxLocalizerStorage;
TcxLanguage = class(TCollectionItem)
private
FDictionary: TStrings;
FLocaleID: Cardinal;
function GetName: string;
procedure SetDictionary(AValue: TStrings);
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
function FindTranslation(const AResStringName: string; out AValue: string): Boolean;
procedure ResetValue(const AResStringName: string);
procedure SetTranslation(const AResStringName, AValue: string);
property Name: string read GetName;
property Dictionary: TStrings read FDictionary write SetDictionary;
property LocaleID: Cardinal read FLocaleID write FLocaleID;
end;
TcxLanguages = class(TCollection)
private
FActiveLanguage: Integer;
FCustomResStrings: TStrings;
FOnLanguagesChanged: TNotifyEvent;
FOwner: TPersistent;
procedure SetActiveLanguage(AValue: Integer);
procedure TranslateResString(const AResStringName: string; AResString: Pointer);
protected
function GetItem(Index: Integer): TcxLanguage;
function GetOwner: TPersistent; override;
function GetLocalizedString(const AResStringName: string; out AValue: string): Boolean;
procedure SetItem(Index: Integer; Value: TcxLanguage);
procedure Translate;
procedure Update(Item: TCollectionItem); override;
property ActiveLanguage: Integer read FActiveLanguage write SetActiveLanguage;
property OnLanguagesChanged: TNotifyEvent read FOnLanguagesChanged write FOnLanguagesChanged;
public
constructor Create(AOwner: TPersistent);
destructor Destroy; override;
function Add: TcxLanguage;
function GetLanguageByName(AName: string): Integer;
procedure SetCustomResStringOriginalValue(const AResStringName, AValue: string);
property CustomResStrings: TStrings read FCustomResStrings;
property Items[Index: Integer]: TcxLanguage read GetItem write SetItem; default;
end;
TcxLocalizerTranslateEvent = procedure(const AResStringName: string;
var AResStringValue: string; out AHandled: Boolean) of object;
TcxLocalizerStorageType = (lstResource, lstIni);
TcxLocalizer = class(TComponent)
private
FActive: Boolean;
FFileName: TFileName;
FLanguages: TcxLanguages;
FLoadedActive: Boolean;
FLoadedLanguage: string;
FStorage: TcxLocalizerStorage;
FStorageType: TcxLocalizerStorageType;
FOnTranslate: TcxLocalizerTranslateEvent;
function GetLanguage: string;
function GetLanguageIndex: Integer;
function GetLocale: Cardinal;
procedure InternalLoadFromStream(AStream: TStream);
function IsLanguageIndexValid: Boolean;
function IsLocaleStored: Boolean;
procedure RecreateStorage;
procedure SetActive(AValue: Boolean);
procedure SetFileName(AValue: TFileName);
procedure SetLanguage(AValue: string);
procedure SetLanguageIndex(AValue: Integer);
procedure SetLocale(AValue: Cardinal);
procedure SetStorageType(AValue: TcxLocalizerStorageType);
protected
procedure Clear;
function DoCustomTranslate(const AResStringName: string; out ALocalizedValue: string): Boolean;
function GetStorageClassType: TcxLocalizerStorageClass;
procedure LanguagesChanged(ASender: TObject);
procedure Loaded; override;
procedure LoadFromResource;
procedure UpdateDependentComponents;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
procedure LoadFromStream(AStream: TStream);
procedure LoadFromFile(const AFileName: TFileName = '');
procedure SaveToFile(const AFileName: TFileName{$IFDEF DELPHI12}; AIsAnsiSaveFormat: Boolean{$ENDIF});
procedure SaveToStream(AStream: TStream{$IFDEF DELPHI12}; AIsAnsiSaveFormat: Boolean{$ENDIF});
procedure Translate;
property LanguageIndex: Integer read GetLanguageIndex write SetLanguageIndex;
property Language: string read GetLanguage write SetLanguage;
property Languages: TcxLanguages read FLanguages;
published
property Active: Boolean read FActive write SetActive default False;
property FileName: TFileName read FFileName write SetFileName;
property Locale: Cardinal read GetLocale write SetLocale stored IsLocaleStored;
property StorageType: TcxLocalizerStorageType read FStorageType write SetStorageType default lstIni;
property OnTranslate: TcxLocalizerTranslateEvent read FOnTranslate write FOnTranslate;
end;
TcxLocalizerStorage = class(TPersistent)
private
{$IFDEF DELPHI12}
function GetEndcodingFromLocaleID(ALocaleID: Integer): TEncoding;
{$ENDIF}
public
procedure LoadFromStream(AStream: TStream; ALanguages: TcxLanguages);
procedure SaveToStream(AStream: TStream; ALanguages: TcxLanguages{$IFDEF DELPHI12}; AIsAnsiSaveFormat: Boolean{$ENDIF});
end;
implementation
uses
Math, Dialogs, Controls, dxCore;
const
ACustomResourceStrings = 'Custom Resource Strings';
type
TcxLocalizerDictionary = class(TStringList)
private
function GetValue(const Name: string): string;
procedure SetValue(const Name, Value: string);
{$IFNDEF DELPHI7}
function GetNameValueSeparator: Char;
function GetValueFromIndex(Index: Integer): string;
{$ENDIF}
protected
function CompareStrings(const S1, S2: string): Integer; override;
public
{$IFNDEF DELPHI7}
property NameValueSeparator: Char read GetNameValueSeparator;
property ValueFromIndex[Index: Integer]: string read GetValueFromIndex;
{$ENDIF}
property Values[const Name: string]: string read GetValue write SetValue;
end;
{ TcxLocalizerDictionary }
function TcxLocalizerDictionary.CompareStrings(const S1, S2: string): Integer;
var
AS1, AS2: string;
begin
AS1 := ExtractName(S1);
if AS1 = '' then
AS1 := S1;
AS2 := ExtractName(S2);
if AS2 = '' then
AS2 := S2;
Result := inherited CompareStrings(AS1, AS2);
end;
function TcxLocalizerDictionary.GetValue(const Name: string): string;
var
I: Integer;
begin
if Find(Name, I) then
Result := Copy(Get(I), Length(Name) + 2, MaxInt)
else
Result := '';
end;
procedure TcxLocalizerDictionary.SetValue(const Name, Value: string);
var
I: Integer;
AObject: TObject;
begin
BeginUpdate;
AObject := nil;
if Find(Name, I) then
begin
AObject := GetObject(I);
Delete(I);
end;
InsertItem(I, Name + NameValueSeparator + Value, AObject);
EndUpdate;
end;
{$IFNDEF DELPHI7}
function TcxLocalizerDictionary.GetNameValueSeparator: Char;
begin
Result := '=';
end;
function TcxLocalizerDictionary.GetValueFromIndex(Index: Integer): string;
begin
if Index >= 0 then
Result := Copy(Get(Index), Length(Names[Index]) + 2, MaxInt) else
Result := '';
end;
{$ENDIF}
{ TcxLanguage }
constructor TcxLanguage.Create(Collection: TCollection);
begin
inherited;
FDictionary := TcxLocalizerDictionary.Create;
TStringList(FDictionary).Sorted := True;
end;
destructor TcxLanguage.Destroy;
begin
FreeAndNil(FDictionary);
inherited;
end;
procedure TcxLanguage.Assign(Source: TPersistent);
begin
if Source is TcxLanguage then
begin
LocaleID := TcxLanguage(Source).LocaleID;
Dictionary := TcxLanguage(Source).Dictionary;
end
else
inherited;
end;
function TcxLanguage.FindTranslation(const AResStringName: string; out AValue: string): Boolean;
var
AIndex: Integer;
begin
Result := TStringList(FDictionary).Find(AResStringName, AIndex);
if Result then
AValue := TcxLocalizerDictionary(FDictionary).ValueFromIndex[AIndex]
else
AValue := '';
end;
procedure TcxLanguage.ResetValue(const AResStringName: string);
var
I: Integer;
begin
if TStringList(FDictionary).Find(AResStringName, I) then
FDictionary.Delete(I);
end;
procedure TcxLanguage.SetTranslation(const AResStringName, AValue: string);
begin
if AResStringName <> '' then
TcxLocalizerDictionary(FDictionary).Values[AResStringName] := AValue;
end;
function TcxLanguage.GetName: string;
begin
Result := Languages.NameFromLocaleID[LocaleID];
end;
procedure TcxLanguage.SetDictionary(AValue: TStrings);
begin
FDictionary.Assign(AValue)
end;
{ TcxLanguages }
constructor TcxLanguages.Create(AOwner: TPersistent);
begin
inherited Create(TcxLanguage);
FActiveLanguage := -1;
FOwner := AOwner;
FCustomResStrings := TcxLocalizerDictionary.Create;
TStringList(FCustomResStrings).Sorted := True;
end;
destructor TcxLanguages.Destroy;
begin
FCustomResStrings.Free;
inherited;
end;
function TcxLanguages.Add: TcxLanguage;
begin
Result := TcxLanguage(inherited Add);
end;
function TcxLanguages.GetLanguageByName(AName: string): Integer;
var
I: Integer;
begin
Result := -1;
for I := 0 to Count - 1 do
if Items[I].Name = AName then
begin
Result := I;
Break;
end;
end;
procedure TcxLanguages.SetCustomResStringOriginalValue(const AResStringName, AValue: string);
begin
if AResStringName <> '' then
TcxLocalizerDictionary(FCustomResStrings).Values[AResStringName] := AValue;
end;
function TcxLanguages.GetItem(Index: Integer): TcxLanguage;
begin
Result := TcxLanguage(inherited GetItem(Index));
end;
function TcxLanguages.GetOwner: TPersistent;
begin
Result := FOwner;
end;
function TcxLanguages.GetLocalizedString(const AResStringName: string; out AValue: string): Boolean;
begin
AValue := '';
Result := False;
if (0 <= ActiveLanguage) and (ActiveLanguage < Count) then
Result := Items[ActiveLanguage].FindTranslation(AResStringName, AValue);
end;
procedure TcxLanguages.SetItem(Index: Integer; Value: TcxLanguage);
begin
inherited SetItem(Index, Value);
end;
procedure TcxLanguages.Translate;
var
APreviousHandler: TdxLocalizationTranslateResStringEvent;
begin
cxClearResourceStrings;
APreviousHandler := dxResourceStringsRepository.OnTranslateResString;
dxResourceStringsRepository.OnTranslateResString := TranslateResString;
dxResourceStringsRepository.Translate;
dxResourceStringsRepository.OnTranslateResString := APreviousHandler;
end;
procedure TcxLanguages.Update(Item: TCollectionItem);
begin
if Assigned(FOnLanguagesChanged) then
FOnLanguagesChanged(Self);
end;
procedure TcxLanguages.SetActiveLanguage(AValue: Integer);
begin
if FActiveLanguage <> AValue then
FActiveLanguage := AValue;
end;
procedure TcxLanguages.TranslateResString(const AResStringName: string; AResString: Pointer);
var
ALocalizedValue: string;
begin
if TcxLocalizer(FOwner).DoCustomTranslate(AResStringName, ALocalizedValue) or
GetLocalizedString(AResStringName, ALocalizedValue) then
cxSetResourceString(AResString, ALocalizedValue);
end;
{ TcxLocalizer }
constructor TcxLocalizer.Create(AOwner: TComponent);
begin
inherited;
FLanguages := TcxLanguages.Create(Self);
FLanguages.OnLanguagesChanged := LanguagesChanged;
FStorageType := lstIni;
RecreateStorage;
end;
destructor TcxLocalizer.Destroy;
begin
FreeAndNil(FLanguages);
FreeAndNil(FStorage);
inherited;
end;
procedure TcxLocalizer.Assign(Source: TPersistent);
var
ALocalizer: TcxLocalizer;
begin
if Source is TcxLocalizer then
begin
ALocalizer := TcxLocalizer(Source);
FileName := ALocalizer.FileName;
StorageType := ALocalizer.StorageType;
Locale := ALocalizer.Locale;
end
else
inherited;
end;
procedure TcxLocalizer.LoadFromStream(AStream: TStream);
begin
Active := False;
InternalLoadFromStream(AStream);
end;
procedure TcxLocalizer.LoadFromFile(const AFileName: TFileName = '');
var
AFileStream: TFileStream;
begin
Active := False;
if AFileName <> '' then
FFileName := AFileName;
AFileStream := TFileStream.Create(FFileName, fmOpenRead or fmShareDenyNone);
try
InternalLoadFromStream(AFileStream);
finally
AFileStream.Free;
end;
end;
procedure TcxLocalizer.SaveToFile(const AFileName: TFileName{$IFDEF DELPHI12}; AIsAnsiSaveFormat: Boolean{$ENDIF});
var
AFileStream: TFileStream;
begin
if AFileName = '' then Exit;
AFileStream := TFileStream.Create(AFileName, fmCreate);
try
SaveToStream(AFileStream{$IFDEF DELPHI12}, AIsAnsiSaveFormat{$ENDIF});
finally
AFileStream.Free;
end;
if FileExists(AFileName) then
FFileName := AFileName;
end;
procedure TcxLocalizer.SaveToStream(AStream: TStream{$IFDEF DELPHI12}; AIsAnsiSaveFormat: Boolean{$ENDIF});
begin
FStorage.SaveToStream(AStream, Languages{$IFDEF DELPHI12}, AIsAnsiSaveFormat{$ENDIF});
end;
procedure TcxLocalizer.Translate;
begin
FLanguages.Translate;
UpdateDependentComponents;
end;
procedure TcxLocalizer.Clear;
begin
Languages.Clear;
Languages.CustomResStrings.Clear;
end;
function TcxLocalizer.DoCustomTranslate(const AResStringName: string; out ALocalizedValue: string): Boolean;
begin
Result := False;
if Assigned(FOnTranslate) then
begin
ALocalizedValue := dxResourceStringsRepository.GetOriginalValue(AResStringName);
FOnTranslate(AResStringName, ALocalizedValue, Result);
end;
end;
function TcxLocalizer.GetStorageClassType: TcxLocalizerStorageClass;
begin
Result := TcxLocalizerStorage;
end;
procedure TcxLocalizer.LanguagesChanged(ASender: TObject);
begin
LanguageIndex := Min(LanguageIndex, Languages.Count - 1);
end;
procedure TcxLocalizer.Loaded;
begin
inherited;
try
Active := FLoadedActive;
except
if csDesigning in ComponentState then
if Assigned(Classes.ApplicationHandleException) then
Classes.ApplicationHandleException(ExceptObject)
else
ShowException(ExceptObject, ExceptAddr)
else
raise;
end;
Language := FLoadedLanguage;
end;
procedure TcxLocalizer.LoadFromResource;
var
AStream: TStream;
begin
AStream := TResourceStream.Create(HInstance, 'CXLOCALIZATION', PChar('CXLOCALIZATION'));
try
LoadFromStream(AStream);
finally
AStream.Free;
end;
end;
procedure TcxLocalizer.UpdateDependentComponents;
begin
dxResourceStringsRepository.NotifyListeners;
end;
function TcxLocalizer.GetLanguage: string;
begin
if IsLanguageIndexValid then
Result := Languages[LanguageIndex].Name
else
Result := ANoActiveLanguage;
end;
function TcxLocalizer.GetLanguageIndex: Integer;
begin
Result := FLanguages.ActiveLanguage;
end;
function TcxLocalizer.GetLocale: Cardinal;
begin
if IsLanguageIndexValid then
Result := Languages[LanguageIndex].LocaleID
else
Result := 0;
end;
procedure TcxLocalizer.InternalLoadFromStream(AStream: TStream);
begin
FStorage.LoadFromStream(AStream, Languages);
FActive := True;
end;
function TcxLocalizer.IsLanguageIndexValid: Boolean;
begin
Result := (0 <= LanguageIndex) and (LanguageIndex < Languages.Count);
end;
function TcxLocalizer.IsLocaleStored: Boolean;
begin
Result := LanguageIndex <> -1;
end;
procedure TcxLocalizer.RecreateStorage;
begin
FStorage := GetStorageClassType.Create;
end;
procedure TcxLocalizer.SetActive(AValue: Boolean);
begin
if csLoading in ComponentState then
FLoadedActive := AValue
else
if FActive <> AValue then
begin
FActive := AValue;
if AValue then
if FStorageType = lstIni then
LoadFromFile
else
begin
if not (csDesigning in ComponentState) then
LoadFromResource;
end
else
Clear;
end;
end;
procedure TcxLocalizer.SetFileName(AValue: TFileName);
begin
if FFileName <> AValue then
begin
FFileName := AValue;
if not (csLoading in ComponentState) then
Active := False;
end;
end;
procedure TcxLocalizer.SetLanguage(AValue: string);
begin
if csLoading in ComponentState then
FLoadedLanguage := AValue
else
LanguageIndex := Languages.GetLanguageByName(AValue);
end;
procedure TcxLocalizer.SetLanguageIndex(AValue: Integer);
begin
AValue := Min(Max(AValue, -1), Languages.Count - 1);
if FLanguages.ActiveLanguage <> AValue then
begin
FLanguages.ActiveLanguage := AValue;
Translate;
end;
end;
procedure TcxLocalizer.SetLocale(AValue: Cardinal);
begin
Language := SysUtils.Languages.NameFromLocaleID[AValue];
end;
procedure TcxLocalizer.SetStorageType(AValue: TcxLocalizerStorageType);
begin
if FStorageType <> AValue then
begin
FStorageType := AValue;
if not (csLoading in ComponentState) then
Active := False;
end;
end;
{ TcxLocalizerStorage }
procedure TcxLocalizerStorage.LoadFromStream(AStream: TStream; ALanguages: TcxLanguages);
{$IFDEF DELPHI12}
function IsUnicode(AStream: TStream): Boolean;
var
ASize: Integer;
ABuffer: TBytes;
AEncoding: TEncoding;
begin
ASize := AStream.Size - AStream.Position;
SetLength(ABuffer, ASize);
AStream.Read(ABuffer[0], ASize);
AEncoding := nil;
TEncoding.GetBufferEncoding(ABuffer, AEncoding);
Result := AEncoding = TEncoding.Unicode;
end;
{$ENDIF}
procedure ReadSectionValues(AIniFile: TCustomIniFile; const ASectionName: string; AList: TStrings);
var
I: Integer;
AName, AValue: string;
begin
AIniFile.ReadSectionValues(ASectionName, AList);
AList.BeginUpdate;
try
for I := 0 to AList.Count - 1 do
begin
AValue := TcxLocalizerDictionary(AList).ValueFromIndex[I];
AValue := StringReplace(AValue, ' \n', #13#10, [rfReplaceAll, rfIgnoreCase]);
AValue := StringReplace(AValue, '\\n', '\n', [rfReplaceAll, rfIgnoreCase]);
Delete(AValue, 1, 1);
Delete(AValue, Length(AValue), 1);
AName := AList.Names[I];
TcxLocalizerDictionary(AList).Values[AName] := AValue;
end;
finally
AList.EndUpdate;
end;
end;
var
AList, ASections: TStringList;
AMemIniFile: TMemIniFile;
ASectionName: string;
ALanguage: TcxLanguage;
I: Integer;
{$IFDEF DELPHI12}
AEncoding: TEncoding;
AIsUnicode: Boolean;
AStartPos: Integer;
{$ENDIF}
begin
AMemIniFile := TMemIniFile.Create('');
AList := TStringList.Create;
ASections := TStringList.Create;
{$IFDEF DELPHI12}AStartPos := AStream.Position;{$ENDIF}
try
AList.LoadFromStream(AStream);
AMemIniFile.SetStrings(AList);
AMemIniFile.ReadSections(ASections);
{$IFDEF DELPHI12}
AStream.Position := AStartPos;
AIsUnicode := IsUnicode(AStream);
{$ENDIF}
for I := 0 to ASections.Count - 1 do
begin
ASectionName := ASections[I];
if ASectionName <> ACustomResourceStrings then
begin
ALanguage := ALanguages.Add;
ALanguage.LocaleID := StrToInt(ASectionName);
{$IFDEF DELPHI12}
if not AIsUnicode then
begin
AEncoding := GetEndcodingFromLocaleID(StrToInt(ASectionName));
try
AStream.Position := AStartPos;
AList.LoadFromStream(AStream, AEncoding);
AMemIniFile.SetStrings(AList);
finally
FreeAndNil(AEncoding);
end;
end;
{$ENDIF}
ReadSectionValues(AMemIniFile, ASectionName, ALanguage.Dictionary);
end
else
ReadSectionValues(AMemIniFile, ASectionName, ALanguages.CustomResStrings);
end;
finally
FreeAndNil(AList);
FreeAndNil(ASections);
FreeAndNil(AMemIniFile);
end;
end;
procedure TcxLocalizerStorage.SaveToStream(AStream: TStream;
ALanguages: TcxLanguages{$IFDEF DELPHI12}; AIsAnsiSaveFormat: Boolean{$ENDIF});
procedure WriteSection(AIniFile: TCustomIniFile; const ASectionName: string; AList: TStrings);
var
I: Integer;
AName, AValue: string;
begin
for I := 0 to AList.Count - 1 do
begin
AName := AList.Names[I];
AValue := AList.Values[AName];
AValue := StringReplace(AValue, '\n', '\\n', [rfReplaceAll, rfIgnoreCase]);
AValue := StringReplace(AValue, #13#10, ' \n', [rfReplaceAll, rfIgnoreCase]);
AValue := '"' + AValue + '"';
AIniFile.WriteString(ASectionName, AName, AValue);
end;
end;
var
AList: TStringList;
AMemIniFile: TMemIniFile;
{$IFDEF DELPHI12}AEncoding: TEncoding;{$ENDIF}
I: Integer;
begin
AMemIniFile := TMemIniFile.Create('');
AList := TStringList.Create;
try
for I := 0 to ALanguages.Count - 1 do
begin
WriteSection(AMemIniFile, IntToStr(ALanguages[I].LocaleID), ALanguages[I].Dictionary);
{$IFDEF DELPHI12}
if AIsAnsiSaveFormat then
begin
AEncoding := GetEndcodingFromLocaleID(ALanguages[I].LocaleID);
try
AMemIniFile.GetStrings(AList);
AMemIniFile.Clear;
AList.SaveToStream(AStream, AEncoding);
AList.Clear;
finally
FreeAndNil(AEncoding);
end;
end;
{$ENDIF}
end;
WriteSection(AMemIniFile, ACustomResourceStrings, ALanguages.CustomResStrings);
AMemIniFile.GetStrings(AList);
{$IFDEF DELPHI12}if AIsAnsiSaveFormat then AEncoding := nil else AEncoding := TEncoding.Unicode;{$ENDIF}
AList.SaveToStream(AStream{$IFDEF DELPHI12}, AEncoding{$ENDIF});
finally
FreeAndNil(AList);
FreeAndNil(AMemIniFile);
end;
end;
{$IFDEF DELPHI12}
function TcxLocalizerStorage.GetEndcodingFromLocaleID(ALocaleID: Integer): TEncoding;
var
ACodePage: Integer;
ABuffer: array [0..6] of Char;
begin
GetLocaleInfo(ALocaleID, LOCALE_IDEFAULTANSICODEPAGE, ABuffer, SizeOf(ABuffer));
ACodePage := StrToIntDef(ABuffer, GetACP);
Result := TEncoding.GetEncoding(ACodePage);
end;
{$ENDIF}
end.