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 Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus