📄 gnugettext.pas
字号:
if Assigned(cm.SpecialHandler) then
raise EGGProgrammingError.Create ('You cannot ignore a class property for a class that has a handler set.');
if not cm.PropertiesToIgnore.Find(propertyname,idx) then
cm.PropertiesToIgnore.Add(propertyname);
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('Globally, the '+propertyname+' property of class '+IgnClass.ClassName+' is being ignored.');
{$endif}
exit;
end;
if IgnClass.InheritsFrom(cm.HClass) then begin
// This is the place to insert this class
cm:=TClassMode.Create;
cm.HClass:=IgnClass;
cm.PropertiesToIgnore.Add(propertyname);
TP_GlobalClassHandling.Insert(i,cm);
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('Globally, the '+propertyname+' property of class '+IgnClass.ClassName+' is being ignored.');
{$endif}
exit;
end;
end;
cm:=TClassMode.Create;
cm.HClass:=IgnClass;
cm.PropertiesToIgnore.Add(propertyname);
TP_GlobalClassHandling.Add(cm);
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('Globally, the '+propertyname+' property of class '+IgnClass.ClassName+' is being ignored.');
{$endif}
end;
procedure TGnuGettextInstance.TP_Ignore(AnObject: TObject;
const name: string);
begin
TP_IgnoreList.Add(uppercase(name));
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('On object with class name '+AnObject.ClassName+', ignore is set on '+name);
{$endif}
end;
procedure TGnuGettextInstance.TranslateComponent(AnObject: TComponent;
const TextDomain: string);
var
comp:TGnuGettextComponentMarker;
begin
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('======================================================================');
DebugWriteln ('TranslateComponent() was called for a component with name '+AnObject.Name+'.');
{$endif}
comp:=AnObject.FindComponent('GNUgettextMarker') as TGnuGettextComponentMarker;
if comp=nil then begin
comp:=TGnuGettextComponentMarker.Create (nil);
comp.Name:='GNUgettextMarker';
comp.Retranslator:=TP_CreateRetranslator;
TranslateProperties (AnObject, TextDomain);
AnObject.InsertComponent(comp);
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('This is the first time, that this component has been translated. A retranslator component has been created for this component.');
{$endif}
end else begin
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('This is not the first time, that this component has been translated.');
{$endif}
if comp.LastLanguage<>curlang then begin
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('ERROR: TranslateComponent() was called twice with different languages. This indicates an attempt to switch language at runtime, but by using TranslateComponent every time. This API has changed - please use RetranslateComponent() instead.');
{$endif}
{$ifdef mswindows}
MessageBox (0,'This application tried to switch the language, but in an incorrect way. The programmer needs to replace a call to TranslateComponent with a call to RetranslateComponent(). The programmer should see the changelog of gnugettext.pas for more information.','Error',MB_OK);
{$else}
writeln (stderr,'This application tried to switch the language, but in an incorrect way. The programmer needs to replace a call to TranslateComponent with a call to RetranslateComponent(). The programmer should see the changelog of gnugettext.pas for more information.');
{$endif}
end else begin
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('ERROR: TranslateComponent has been called twice, but with the same language chosen. This is a mistake, but in order to prevent that the application breaks, no exception is raised.');
{$endif}
end;
end;
comp.LastLanguage:=curlang;
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('======================================================================');
{$endif}
end;
procedure TGnuGettextInstance.TranslateProperty (AnObject:TObject; PropInfo:PPropInfo; TodoList:TStrings; const TextDomain:string);
var
ppi:PPropInfo;
ws: WideString;
old: WideString;
compmarker:TComponent;
obj:TObject;
Propname:string;
begin
PropName:=PropInfo^.Name;
try
// Translate certain types of properties
case PropInfo^.PropType^.Kind of
tkString, tkLString, tkWString:
begin
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('Translating '+AnObject.ClassName+'.'+PropName);
{$endif}
if PropInfo^.PropType^.Kind<>tkWString then
old := ansi2wideDTCP(GetStrProp(AnObject, PropName))
else
old := GetWideStrProp(AnObject, PropName);
{$ifdef DXGETTEXTDEBUG}
if old='' then
DebugWriteln ('(Empty, not translated)')
else
DebugWriteln ('Old value: "'+old+'"');
{$endif}
if (old <> '') and (IsWriteProp(PropInfo)) then begin
if TP_Retranslator<>nil then
(TP_Retranslator as TTP_Retranslator).Remember(AnObject, PropName, old);
ws := dgettext(textdomain,old);
if ws <> old then begin
ppi:=GetPropInfo(AnObject, Propname);
if ppi<>nil then begin
SetWideStrProp(AnObject, ppi, ws);
end else begin
DebugWriteln ('ERROR: Property disappeared: '+Propname+' for object of type '+AnObject.ClassName);
end;
end;
end;
end { case item };
tkClass:
begin
obj:=GetObjectProp(AnObject, PropName);
if obj<>nil then begin
if obj is TComponent then begin
compmarker := TComponent(obj).FindComponent('GNUgettextMarker');
if Assigned(compmarker) then
exit;
end;
TodoList.AddObject ('',obj);
end;
end { case item };
end { case };
except
on E:Exception do
raise EGGComponentError.Create ('Property cannot be translated.'+sLineBreak+
'Add TP_GlobalIgnoreClassProperty('+AnObject.ClassName+','''+PropName+''') to your source code or use'+sLineBreak+
'TP_Ignore (self,''.'+PropName+''') to prevent this message.'+sLineBreak+
'Reason: '+e.Message);
end;
end;
procedure TGnuGettextInstance.TranslateProperties(AnObject: TObject; textdomain:string='');
var
TodoList:TStringList; // List of Name/TObject's that is to be processed
DoneList:TStringList; // List of hex codes representing pointers to objects that have been done
i, j, Count: integer;
PropList: PPropList;
UPropName: string;
PropInfo: PPropInfo;
compmarker,
comp:TComponent;
cm,
currentcm:TClassMode; // currentcm is nil or contains special information about how to handle the current object
ObjectPropertyIgnoreList:TStringList;
objid, Name:string;
begin
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('----------------------------------------------------------------------');
DebugWriteln ('TranslateProperties() was called for an object of class '+AnObject.ClassName+' with domain "'+textdomain+'".');
{$endif}
if textdomain='' then
textdomain:=curmsgdomain;
if TP_Retranslator<>nil then
(TP_Retranslator as TTP_Retranslator).TextDomain:=textdomain;
DoneList:=TStringList.Create;
TodoList:=TStringList.Create;
ObjectPropertyIgnoreList:=TStringList.Create;
try
TodoList.AddObject('', AnObject);
DoneList.Sorted:=True;
ObjectPropertyIgnoreList.Sorted:=True;
ObjectPropertyIgnoreList.Duplicates:=dupIgnore;
ObjectPropertyIgnoreList.CaseSensitive:=False;
DoneList.Duplicates:=dupError;
DoneList.CaseSensitive:=True;
while TodoList.Count<>0 do begin
AnObject:=TodoList.Objects[0];
Name:=TodoList.Strings[0];
TodoList.Delete(0);
if (AnObject<>nil) and (AnObject is TPersistent) then begin
// Make sure each object is only translated once
Assert (sizeof(integer)=sizeof(TObject));
objid:=IntToHex(integer(AnObject),8);
if DoneList.Find(objid,i) then begin
continue;
end else begin
DoneList.Add(objid);
end;
ObjectPropertyIgnoreList.Clear;
// Find out if there is special handling of this object
currentcm:=nil;
// First check the local handling instructions
for j:=0 to TP_ClassHandling.Count-1 do begin
cm:=TObject(TP_ClassHandling.Items[j]) as TClassMode;
if AnObject.InheritsFrom(cm.HClass) then begin
if cm.PropertiesToIgnore.Count<>0 then begin
ObjectPropertyIgnoreList.AddStrings(cm.PropertiesToIgnore);
end else begin
// Ignore the entire class
currentcm:=cm;
break;
end;
end;
end;
// Then check the global handling instructions
if currentcm=nil then
for j:=0 to TP_GlobalClassHandling.Count-1 do begin
cm:=TObject(TP_GlobalClassHandling.Items[j]) as TClassMode;
if AnObject.InheritsFrom(cm.HClass) then begin
if cm.PropertiesToIgnore.Count<>0 then begin
ObjectPropertyIgnoreList.AddStrings(cm.PropertiesToIgnore);
end else begin
// Ignore the entire class
currentcm:=cm;
break;
end;
end;
end;
if currentcm<>nil then begin
ObjectPropertyIgnoreList.Clear;
// Ignore or use special handler
if Assigned(currentcm.SpecialHandler) then begin
currentcm.SpecialHandler (AnObject);
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('Special handler activated for '+AnObject.ClassName);
{$endif}
end else begin
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('Ignoring object '+AnObject.ClassName);
{$endif}
end;
continue;
end;
Count := GetPropList(AnObject, PropList);
try
for j := 0 to Count - 1 do begin
PropInfo := PropList[j];
if not (PropInfo^.PropType^.Kind in [tkString, tkLString, tkWString, tkClass]) then
continue;
UPropName:=uppercase(PropInfo^.Name);
// Ignore properties that are meant to be ignored
if ((currentcm=nil) or (not currentcm.PropertiesToIgnore.Find(UPropName,i))) and
(not TP_IgnoreList.Find(Name+'.'+UPropName,i)) and
(not ObjectPropertyIgnoreList.Find(UPropName,i)) then begin
TranslateProperty (AnObject,PropInfo,TodoList,TextDomain);
end; // if
end; // for
finally
if Count<>0 then
FreeMem (PropList);
end;
if AnObject is TStrings then begin
if ((AnObject as TStrings).Text<>'') and (TP_Retranslator<>nil) then
(TP_Retranslator as TTP_Retranslator).Remember(AnObject, 'Text', (AnObject as TStrings).Text);
TranslateStrings (AnObject as TStrings,TextDomain);
end;
// Check for TCollection
if AnObject is TCollection then begin
for i := 0 to (AnObject as TCollection).Count - 1 do begin
// Only add the object if it's not totally ignored already
if not Assigned(currentcm) or not AnObject.InheritsFrom(currentcm.HClass) then
TodoList.AddObject('',(AnObject as TCollection).Items[i]);
end;
end;
if AnObject is TComponent then begin
for i := 0 to TComponent(AnObject).ComponentCount - 1 do begin
comp:=TComponent(AnObject).Components[i];
if (not TP_IgnoreList.Find(uppercase(comp.Name),j)) then begin
// Only add the object if it's not totally ignored or translated already
if not Assigned(currentcm) or not AnObject.InheritsFrom(currentcm.HClass) then begin
compmarker := comp.FindComponent('GNUgettextMarker');
if not Assigned(compmarker) then
TodoList.AddObject(uppercase(comp.Name),comp);
end;
end;
end;
end;
end { if AnObject<>nil };
end { while todolist.count<>0 };
finally
FreeAndNil (todolist);
FreeAndNil (ObjectPropertyIgnoreList);
FreeAndNil (DoneList);
end;
FreeTP_ClassHandlingItems;
TP_IgnoreList.Clear;
TP_Retranslator:=nil;
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('----------------------------------------------------------------------');
{$endif}
end;
procedure TGnuGettextInstance.UseLanguage(LanguageCode: string);
var
i,p:integer;
dom:TDomain;
l2:string[2];
begin
{$ifdef DXGETTEXTDEBUG}
DebugWriteln('UseLanguage('''+LanguageCode+'''); called');
{$endif}
if LanguageCode='' then begin
LanguageCode:=GGGetEnvironmentVariable('LANG');
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('LANG env variable is '''+LanguageCode+'''.');
{$endif}
{$ifdef MSWINDOWS}
if LanguageCode='' then begin
LanguageCode:=GetWindowsLanguage;
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('Found Windows language code to be '''+LanguageCode+'''.');
{$endif}
end;
{$endif}
p:=pos('.',LanguageCode);
if p<>0 then
LanguageCode:=copy(LanguageCode,1,p-1);
{$ifdef DXGETTEXTDEBUG}
DebugWriteln ('Language code that will be set is '''+LanguageCode+'''.');
{$endif}
end;
curlang := LanguageCode;
for i:=0 to domainlist.Count-1 do begin
dom:=domainlist.Objects[i] as TDomain;
dom.SetLanguageCode (curlang);
end;
l2:=lowercase(copy(curlang,1,2));
if (l2='en') or (l2='de') then curGetPluralForm:=GetPluralForm2EN else
if (l2='hu') or (l2='ko') or (l2='zh') or (l2='ja') or (l2='tr') then curGetPluralForm:=GetPluralForm1 else
if (l2='fr') or (l2='fa') or (lowercase(curlang)='pt_br') then curGetPluralForm:=GetPluralForm2FR else
if (l2='lv') then curGetPluralForm:=GetPluralForm3LV else
if (l2='ga') then curGetPluralForm:=GetPluralForm3GA else
if (l2='lt') then curGetPluralForm:=GetPluralForm3LT else
if (l2='ru') or (l2='cs') or (l2='sk') or (l2='uk') or (l2='hr') then curGetPluralForm:=GetPluralForm3RU else
if (l2='pl') then curGetPluralForm:=GetPluralFor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -