{
pascalx.lang.locale — поддержка локализаций.
Copyright © 2021, 2026 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или изменять
её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
}
unit pascalx.lang.locale;
{$MODE DELPHI}
interface
{%region} uses
pascalx.lang,
pascalx.io.charset.basiclatin;
{%endregion}
{$TYPEINFO ON}
{$CALLING REGISTER}
const UNIT_NAME = 'pascalx.lang.locale';
{%region} type
Locale = class;
Locale = class(&Object)
private
class var instance: Locale;
public
class procedure register(inst: Locale); static;
class function getInstance(): Locale; static;
private
fldLocaleId: AnsiString;
fldAliasIds: AnsiString_Array1d;
public
constructor create(const localeId: AnsiString; const aliasIds: AnsiString_Array1d);
procedure aliasIdsCopyInto(const dst: AnsiString_Array1d; offset: int = 0);
function isDigit(character: uchar): boolean; virtual;
function isLowerCase(character: uchar): boolean; virtual;
function isUpperCase(character: uchar): boolean; virtual;
function toLowerCase(character: uchar): uchar; virtual;
function toUpperCase(character: uchar): uchar; virtual;
function orderOf(character: uchar): int; virtual;
function compare(const str1, str2: UnicodeString): int; virtual;
function isLocaleId(const localeId: AnsiString): boolean;
function aliasIds(): AnsiString_Array1d;
published
property localeId: AnsiString read fldLocaleId;
end;
{%endregion}
implementation
{$CALLING REGISTER}
{%region Locale }
class procedure Locale.register(inst: Locale);
begin
if inst = nil then begin
raise NullPointerException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer.argument'), [ CoAnsiString.create('inst') ]));
end;
if instance <> nil then begin
raise SecurityException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'security'));
end;
instance := inst;
end;
class function Locale.getInstance(): Locale;
begin
if instance = nil then begin
instance := Locale.create('default', nil);
end;
result := instance;
end;
constructor Locale.create(const localeId: AnsiString; const aliasIds: AnsiString_Array1d);
label
continue_label0;
var
ali: int;
alj: int;
sourcesLength: int;
aliasesLength: int;
aliasInstance: AnsiString;
aliasesData: AnsiString_Array1d;
aliasesCopy: AnsiString_Array1d;
begin
inherited create();
aliasesLength := length(aliasIds);
aliasesData := &Array.newAnsiString1d(aliasesLength);
sourcesLength := aliasesLength;
aliasesLength := 0;
for ali := 0 to sourcesLength - 1 do begin
aliasInstance := aliasIds[ali];
if (aliasInstance.length <= 0) or (aliasInstance = localeId) then goto continue_label0;
for alj := 0 to aliasesLength - 1 do if aliasInstance = aliasesData[alj] then goto continue_label0;
aliasesData[aliasesLength] := aliasInstance;
inc(aliasesLength);
continue_label0:
end;
if aliasesLength <> length(aliasesData) then begin
aliasesCopy := &Array.newAnsiString1d(aliasesLength);
&Array.copyStrings(aliasesData, 0, aliasesCopy, 0, aliasesLength);
aliasesData := aliasesCopy;
end;
fldLocaleId := localeId;
fldAliasIds := aliasesData;
end;
procedure Locale.aliasIdsCopyInto(const dst: AnsiString_Array1d; offset: int);
var
aliasIds: AnsiString_Array1d;
begin
aliasIds := fldAliasIds;
&Array.copyStrings(aliasIds, 0, dst, offset, length(aliasIds));
end;
function Locale.isDigit(character: uchar): boolean;
begin
result := BasicLatin.isDigit(character);
end;
function Locale.isLowerCase(character: uchar): boolean;
begin
result := BasicLatin.isLowerCase(character);
end;
function Locale.isUpperCase(character: uchar): boolean;
begin
result := BasicLatin.isUpperCase(character);
end;
function Locale.toLowerCase(character: uchar): uchar;
begin
result := BasicLatin.toLowerCase(character);
end;
function Locale.toUpperCase(character: uchar): uchar;
begin
result := BasicLatin.toUpperCase(character);
end;
function Locale.orderOf(character: uchar): int;
begin
result := BasicLatin.orderOf(character);
end;
function Locale.compare(const str1, str2: UnicodeString): int;
var
index: int;
order1: int;
order2: int;
length1: int;
length2: int;
begin
length1 := str1.length;
length2 := str2.length;
for index := 1 to CoInt.min(length1, length2) do begin
order1 := orderOf(str1[index]);
order2 := orderOf(str2[index]);
if order1 <> order2 then begin
result := order1 - order2;
exit;
end;
end;
result := length1 - length2;
end;
function Locale.isLocaleId(const localeId: AnsiString): boolean;
var
index: int;
aliasIds: AnsiString_Array1d;
begin
if fldLocaleId = localeId then begin
result := true;
exit;
end;
aliasIds := fldAliasIds;
for index := 0 to length(aliasIds) - 1 do if aliasIds[index] = localeId then begin
result := true;
exit;
end;
result := false;
end;
function Locale.aliasIds(): AnsiString_Array1d;
var
length: int;
aliasIdsData: AnsiString_Array1d;
aliasIdsCopy: AnsiString_Array1d;
begin
aliasIdsData := fldAliasIds;
length := system.length(aliasIdsData);
aliasIdsCopy := &Array.newAnsiString1d(length);
&Array.copyStrings(aliasIdsData, 0, aliasIdsCopy, 0, length);
result := aliasIdsCopy;
end;
{%endregion}
{%region} finalization
Locale.instance.free();
{%endregion}
end.