mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-05 02:56:03 +02:00
LazUtils: Add GetLanguageID function to Translations unit. It returns a record with language code (in ISO 639-1 or ISO 639-2) and country code (in ISO 3166) for current system locale.
Implementation is based on GetLanguageIDs procedure from GetText unit, but is rewritten to have the following properties: 1. Language and country codes are returned in ISO formats on Windows. 2. Unix locale identifier is properly parsed and language/country codes are properly extracted. 3. Don't assume that language code is always two-letter (ISO 639-1), it can have bigger length (e. g. three letters, like in ISO 639-2). 4. Return locale ID in a record type. This will allow to return additional fields in backwards-compatible manner. Currently it contains language ID, language code and country code.
This commit is contained in:
parent
04381be2cc
commit
bb19283344
@ -24,23 +24,21 @@
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
Example 2: Load the current language file using the GetLanguageIDs function
|
Example 2: Load the current language file using the GetLanguageID function:
|
||||||
of the gettext unit in the project lpr file:
|
|
||||||
|
|
||||||
uses
|
uses
|
||||||
...
|
...
|
||||||
Translations, LCLProc;
|
Translations;
|
||||||
|
|
||||||
procedure TranslateLCL;
|
procedure TranslateLCL;
|
||||||
var
|
var
|
||||||
PODirectory, Lang, FallbackLang: String;
|
PODirectory: String;
|
||||||
|
LangID: TLanguageID;
|
||||||
begin
|
begin
|
||||||
PODirectory:='/path/to/lazarus/lcl/languages/';
|
PODirectory:='/path/to/lazarus/lcl/languages/';
|
||||||
Lang:='';
|
LangID := GetLanguageID;
|
||||||
FallbackLang:='';
|
|
||||||
LCLGetLanguageIDs(Lang,FallbackLang); // in unit LCLProc
|
|
||||||
Translations.TranslateUnitResourceStrings('LCLStrConsts',
|
Translations.TranslateUnitResourceStrings('LCLStrConsts',
|
||||||
PODirectory+'lclstrconsts.%s.po',Lang,FallbackLang);
|
PODirectory+'lclstrconsts.%s.po',LangID.LanguageID,LangID.LanguageCode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -49,11 +47,6 @@
|
|||||||
Application.CreateForm(TForm1, Form1);
|
Application.CreateForm(TForm1, Form1);
|
||||||
Application.Run;
|
Application.Run;
|
||||||
end.
|
end.
|
||||||
|
|
||||||
Note for Mac OS X:
|
|
||||||
The supported language IDs should be added into the application
|
|
||||||
bundle property list to CFBundleLocalizations key, see
|
|
||||||
lazarus.app/Contents/Info.plist for example.
|
|
||||||
}
|
}
|
||||||
unit Translations;
|
unit Translations;
|
||||||
|
|
||||||
@ -69,6 +62,12 @@ uses
|
|||||||
AvgLvlTree, StringHashList;
|
AvgLvlTree, StringHashList;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
TLanguageID = record
|
||||||
|
LanguageID: string; //Language ID is combined of LanguageCode and CountryCode (example: 'en_US')
|
||||||
|
LanguageCode: string; //ISO 639-1 or 639-2 language code (example: 'en' or 'eng')
|
||||||
|
CountryCode: string; //ISO 3166 country code (example: 'US' or 'USA')
|
||||||
|
end;
|
||||||
|
|
||||||
TStringsType = (
|
TStringsType = (
|
||||||
stLrj, // Lazarus resource string table in JSON format
|
stLrj, // Lazarus resource string table in JSON format
|
||||||
stRst, // FPC resource string table (before FPC 2.7.1)
|
stRst, // FPC resource string table (before FPC 2.7.1)
|
||||||
@ -189,6 +188,8 @@ var
|
|||||||
// if you don't use UTF-8, install a proper widestring manager and set this
|
// if you don't use UTF-8, install a proper widestring manager and set this
|
||||||
// to false.
|
// to false.
|
||||||
|
|
||||||
|
function GetLanguageID: TLanguageID;
|
||||||
|
|
||||||
function GetPOFilenameParts(const Filename: string; out AUnitName, Language: string): boolean;
|
function GetPOFilenameParts(const Filename: string; out AUnitName, Language: string): boolean;
|
||||||
function FindAllTranslatedPoFiles(const Filename: string): TStringList;
|
function FindAllTranslatedPoFiles(const Filename: string): TStringList;
|
||||||
|
|
||||||
@ -218,6 +219,11 @@ const
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
{$IFDEF Windows}
|
||||||
|
uses
|
||||||
|
Windows;
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
function IsKey(Txt, Key: PChar): boolean;
|
function IsKey(Txt, Key: PChar): boolean;
|
||||||
begin
|
begin
|
||||||
if Txt=nil then exit(false);
|
if Txt=nil then exit(false);
|
||||||
@ -434,6 +440,99 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function GetLanguageID: TLanguageID;
|
||||||
|
{$IFDEF Windows}
|
||||||
|
procedure GetLanguage;
|
||||||
|
var
|
||||||
|
UserLCID: LCID;
|
||||||
|
|
||||||
|
function RetrieveLocaleInfo(InfoType: LCTYPE; var Info: string): longint;
|
||||||
|
var
|
||||||
|
Buffer: {$IFDEF Wince}WideString{$ELSE}AnsiString{$ENDIF};
|
||||||
|
begin
|
||||||
|
Info := '';
|
||||||
|
Result := GetLocaleInfo(UserLCID, InfoType, nil, 0);
|
||||||
|
if Result <> 0 then
|
||||||
|
begin
|
||||||
|
Buffer := '';
|
||||||
|
SetLength(Buffer, Result);
|
||||||
|
Result := GetLocaleInfo(UserLCID, InfoType, @Buffer[1], Result);
|
||||||
|
if Result <> 0 then
|
||||||
|
Info := Copy(Buffer, 1, Length(Buffer) - 1); //the last char is #0, omit it
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
UserLCID := GetUserDefaultLCID;
|
||||||
|
|
||||||
|
RetrieveLocaleInfo(LOCALE_SISO639LANGNAME, Result.LanguageCode);
|
||||||
|
RetrieveLocaleInfo(LOCALE_SISO3166CTRYNAME, Result.CountryCode);
|
||||||
|
end;
|
||||||
|
{$ELSE}
|
||||||
|
procedure GetLanguage;
|
||||||
|
var
|
||||||
|
i, CurItemStart, CurItemLength: SizeInt;
|
||||||
|
FinishedParsing, IsDelimiter: boolean;
|
||||||
|
CurItemType, EnvVarContents: string;
|
||||||
|
begin
|
||||||
|
EnvVarContents := GetEnvironmentVariable('LC_ALL');
|
||||||
|
if Length(EnvVarContents) = 0 then
|
||||||
|
begin
|
||||||
|
EnvVarContents := GetEnvironmentVariable('LC_MESSAGES');
|
||||||
|
if Length(EnvVarContents) = 0 then
|
||||||
|
begin
|
||||||
|
EnvVarContents := GetEnvironmentVariable('LANG');
|
||||||
|
if Length(EnvVarContents) = 0 then
|
||||||
|
exit; // no language defined via environment variables
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//Parse locale identifier. For reference its full syntax:
|
||||||
|
//Current: `language[_territory[.codeset]][@modifier]`
|
||||||
|
//Possible in future: `language[_territory][.codeset][@modifier]`
|
||||||
|
i := 1;
|
||||||
|
CurItemStart := 1;
|
||||||
|
CurItemType := 'L'; // Language is the first item in locale identifier
|
||||||
|
FinishedParsing := false;
|
||||||
|
while (i <= Length(EnvVarContents)) and (not FinishedParsing) do
|
||||||
|
begin
|
||||||
|
IsDelimiter := EnvVarContents[i] in ['_', '.', '@'];
|
||||||
|
if IsDelimiter or (i = Length(EnvVarContents)) then
|
||||||
|
begin
|
||||||
|
CurItemLength := i - CurItemStart;
|
||||||
|
// If the last string char is not delimiter, it belongs to current item, so adjust its length
|
||||||
|
if not IsDelimiter then
|
||||||
|
inc(CurItemLength);
|
||||||
|
case CurItemType of
|
||||||
|
'L': Result.LanguageCode := Copy(EnvVarContents, CurItemStart, CurItemLength);
|
||||||
|
'_': Result.CountryCode := Copy(EnvVarContents, CurItemStart, CurItemLength);
|
||||||
|
'.': ; // We don't need codeset currently
|
||||||
|
end;
|
||||||
|
CurItemType := EnvVarContents[i];
|
||||||
|
// We don't use modifier currently, but know that it is the last in locale identifier
|
||||||
|
if CurItemType = '@' then
|
||||||
|
FinishedParsing := true;
|
||||||
|
CurItemStart := i + 1;
|
||||||
|
end;
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result := Default(TLanguageID);
|
||||||
|
GetLanguage;
|
||||||
|
|
||||||
|
if Result.LanguageCode = '' then
|
||||||
|
begin
|
||||||
|
Result.LanguageCode := 'en';
|
||||||
|
Result.CountryCode := 'US';
|
||||||
|
end;
|
||||||
|
Result.LanguageID := Result.LanguageCode;
|
||||||
|
if Result.CountryCode <> '' then
|
||||||
|
Result.LanguageID := Result.LanguageID + '_' + Result.CountryCode;
|
||||||
|
end;
|
||||||
|
|
||||||
function GetPOFilenameParts(const Filename: string; out AUnitName, Language: string): boolean;
|
function GetPOFilenameParts(const Filename: string; out AUnitName, Language: string): boolean;
|
||||||
var
|
var
|
||||||
NameWithoutExt, Ext: string;
|
NameWithoutExt, Ext: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user