On Fri, 2012-07-13 at 15:51 +0200, zeljko wrote:
> On Friday 13 of July 2012 15:49:37 Joost van der Sluis wrote:
> > I'm using the DefaultTranslator unit to translate my application,
> but I
> > would also like to switch to another language on-the-fly, thus
> without
> > restarting the application.
> I need that too atm :)
Try the attached patch for DefaultTranslator. With SetDefaultLang('nl')
it will switch the language on-the-fly (to Dutch in this case).
It will loop through all forms in screens and will change all properties
that are present in the .po-file.
Maybe it is an idea to apply this patch so that others can also use
this? Or should users write their own 'DefaultTranslator' unit? (Then
this one could be added to the Wiki as an example)
--
Met vriendelijke groeten,
Joost van der Sluis
CNOC Informatiesystemen en Netwerken
http://www.cnoc.nl
Index: defaulttranslator.pas
===================================================================
--- defaulttranslator.pas (revision 37902)
+++ defaulttranslator.pas (working copy)
@@ -33,11 +33,22 @@
uses
Classes, SysUtils, LResources, GetText, Controls, typinfo, FileUtil, LCLProc,
- Translations;
+ Translations, Forms;
type
- TDefaultTranslator = class(TAbstractTranslator)
+
+ { TUpdateTranslator }
+
+ TUpdateTranslator = class(TAbstractTranslator)
private
+ FStackPath: string;
+ procedure IntUpdateTranslation(AnInstance: TPersistent);
+ public
+ procedure UpdateTranslation(AnInstance: TPersistent);
+ end;
+
+ TDefaultTranslator = class(TUpdateTranslator)
+ private
FMOFile: TMOFile;
public
constructor Create(MOFileName: string);
@@ -46,7 +57,9 @@
PropInfo: PPropInfo; var Content: string); override;
end;
- TPOTranslator = class(TAbstractTranslator)
+ { TPOTranslator }
+
+ TPOTranslator = class(TUpdateTranslator)
private
FPOFile: TPOFile;
public
@@ -56,6 +69,8 @@
PropInfo: PPropInfo; var Content: string); override;
end;
+procedure SetDefaultLang(Lang: string);
+
implementation
uses
@@ -64,9 +79,9 @@
type
TPersistentAccess = class(TPersistent);
-function FindLocaleFileName(LCExt: string): string;
+function FindLocaleFileName(LCExt: string; Lang: string): string;
var
- Lang, T: string;
+ T: string;
i: integer;
function GetLocaleFileName(const LangID, LCExt: string): string;
@@ -176,12 +191,12 @@
begin
Result := '';
- Lang := '';
- for i := 1 to Paramcount - 1 do
- if (ParamStrUTF8(i) = '--LANG') or (ParamStrUTF8(i) = '-l') or
- (ParamStrUTF8(i) = '--lang') then
- Lang := ParamStrUTF8(i + 1);
+ if Lang = '' then
+ for i := 1 to Paramcount - 1 do
+ if (ParamStrUTF8(i) = '--LANG') or (ParamStrUTF8(i) = '-l') or
+ (ParamStrUTF8(i) = '--lang') then
+ Lang := ParamStrUTF8(i + 1);
//Win32 user may decide to override locale with LANG variable.
if Lang = '' then
@@ -225,19 +240,108 @@
if (csDesigning in Component.ComponentState) then
exit;
- if not (Sender is TReader) then
- exit;
- Reader := TReader(Sender);
- if Reader.Driver is TLRSObjectReader then
- Result := TLRSObjectReader(Reader.Driver).GetStackPath
- else
- Result := Instance.ClassName + '.' + PropInfo^.Name;
+ if (Sender is TReader) then
+ begin
+ Reader := TReader(Sender);
+ if Reader.Driver is TLRSObjectReader then
+ Result := TLRSObjectReader(Reader.Driver).GetStackPath
+ else
+ Result := Instance.ClassName + '.' + PropInfo^.Name;
+ end else if (Sender is TUpdateTranslator) then
+ Result := TUpdateTranslator(Sender).FStackPath + '.' + PropInfo^.Name;
Result := UpperCase(Result);
end;
var
lcfn: string;
+{ TUpdateTranslator }
+
+procedure TUpdateTranslator.IntUpdateTranslation(AnInstance: TPersistent);
+var
+ i,j: integer;
+ APropCount: integer;
+ APropList: PPropList;
+ APropInfo: PPropInfo;
+ TmpStr: string;
+ APersistentProp: TPersistent;
+ StoreStackPath: string;
+begin
+ APropCount := GetPropList(AnInstance.ClassInfo, APropList);
+ try
+ for i := 0 to APropCount-1 do
+ begin
+ APropInfo:=APropList^[i];
+ if Assigned(PPropInfo(APropInfo)^.GetProc) and
+ assigned(APropInfo^.PropType) and
+ IsStoredProp(AnInstance, APropInfo) then
+ case APropInfo^.PropType^.Kind of
+ tkSString,
+ tkLString,
+ tkAString: begin
+ TmpStr := '';
+ LRSTranslator.TranslateStringProperty(self,aninstance,APropInfo,TmpStr);
+ if TmpStr <>'' then
+ SetStrProp(AnInstance, APropInfo, TmpStr);
+ end;
+ tkclass: begin
+ APersistentProp := TPersistent(GetObjectProp(AnInstance, APropInfo, TPersistent));
+ if Assigned(APersistentProp) then
+ begin
+ if APersistentProp is TCollection then
+ begin
+ for j := 0 to TCollection(APersistentProp).Count-1 do
+ begin
+ StoreStackPath:=FStackPath;
+ FStackPath:=FStackPath+'.'+APropInfo^.Name+'['+inttostr(j)+']';
+ IntUpdateTranslation(TCollection(APersistentProp).Items[j]);
+ FStackPath:=StoreStackPath;
+ end;
+ end
+ else
+ begin
+ if APersistentProp is TComponent then
+ begin
+ if (csSubComponent in TComponent(APersistentProp).ComponentStyle) then
+ begin
+ StoreStackPath:=FStackPath;
+ FStackPath:=FStackPath+'.'+TComponent(APersistentProp).Name;
+ IntUpdateTranslation(APersistentProp);
+ FStackPath:=StoreStackPath;
+ end
+ end
+ else
+ begin
+ StoreStackPath:=FStackPath;
+ FStackPath:=FStackPath+'.'+APropInfo^.Name;
+ IntUpdateTranslation(APersistentProp);
+ FStackPath:=StoreStackPath;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ finally
+ freemem(APropList);
+ end;
+
+ if (AnInstance is TComponent) then
+ for i := 0 to TComponent(AnInstance).ComponentCount-1 do
+ begin
+ StoreStackPath:=FStackPath;
+ FStackPath:=FStackPath+'.'+TComponent(AnInstance).Components[i].Name;
+ IntUpdateTranslation(TComponent(AnInstance).Components[i]);
+ FStackPath:=StoreStackPath;
+ end;
+end;
+
+procedure TUpdateTranslator.UpdateTranslation(AnInstance: TPersistent);
+begin
+ FStackPath:=AnInstance.ClassName;
+ IntUpdateTranslation(AnInstance);
+end;
+
{ TDefaultTranslator }
constructor TDefaultTranslator.Create(MOFileName: string);
@@ -311,19 +415,19 @@
end;
end;
+procedure SetDefaultLang(Lang: string);
+
var
Dot1: integer;
LCLPath: string;
- LocalTranslator: TAbstractTranslator;
+ LocalTranslator: TUpdateTranslator;
+ i: integer;
-initialization
- //It is safe to place code here as no form is initialized before unit
- //initialization made
-
+begin
LocalTranslator := nil;
// search first po translation resources
try
- lcfn := FindLocaleFileName('.po');
+ lcfn := FindLocaleFileName('.po', Lang);
if lcfn <> '' then
begin
Translations.TranslateResourceStrings(lcfn);
@@ -345,7 +449,7 @@
begin
// try now with MO traslation resources
try
- lcfn := FindLocaleFileName('.mo');
+ lcfn := FindLocaleFileName('.mo', Lang);
if lcfn <> '' then
begin
GetText.TranslateResourceStrings(UTF8ToSys(lcfn));
@@ -366,9 +470,28 @@
end;
if LocalTranslator<>nil then
+ begin
+ if Assigned(LRSTranslator) then
+ LRSTranslator.Free;
LRSTranslator := LocalTranslator;
+ // Do not update the translations when this function is called from within
+ // the unit initialization.
+ if (Lang<>'') then
+ begin
+ for i := 0 to Screen.CustomFormCount-1 do
+ LocalTranslator.UpdateTranslation(Screen.CustomForms[i]);
+ end;
+ end;
+end;
+
+
+initialization
+ //It is safe to place code here as no form is initialized before unit
+ //initialization made
+ SetDefaultLang('');
+
finalization
- LocalTranslator.Free;
+ LRSTranslator.Free;
end.
--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus