|
|||
|
.NET, Delphi, ... - Sisulizer Localization Tool Support > Technical Support (You need to be registered at the forum to write) > Bugs and Quirks in Sisulizer > Is it possible to turn off the "Copy all resources" option at all?
|
| Moderated by: Renate.Reinartz, Markus.Kreisel, Jaakko.Salmenius, Ilkka.Salmenius |
|
||||||||||||||||
| Is it possible to turn off the "Copy all resources" option at all? - Bugs and Quirks in Sisulizer - Technical Support (You need to be registered at the forum to write) - .NET, Delphi, ... - Sisulizer Localization Tool Support | |||||||||||||||||
| Author | Post | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|||||||||||||||||
|
ogiesen Member
|
I am currently in the process of migrating a project from Daniel Wischnewski's Delphi Project Localizer (which cannot handle binaries produced by Delphi 2010 and later) to Sisulizer. The former produced resource DLLs in a proprietary format (or at least with a proprietary file extension). These always only contained the resources that were actually translated. For everything else it implemented a fallback to the host binary's own resource block. In our case, because, for historical reasons, we only work directly with resource strings, not with forms or other resources, this meant that these resource DLLs were really small (between 40kb and 100kb each). Now with Sisulizer I've basically got everything working the way I want it (including runtime switching between languages using a custom language picker instead of the one in LaDialog) but now my resource DLLs are each more than thirty times their former size! Even in compressed form this increases the download size of our shareware application significantly... I found that I can get the same small resource DLLs when I disable the option to "Copy all resources" but then the program won't run because it couldn't find its forms and other resources (also see this question on StackOverflow: http://stackoverflow.com/q/10549976/9784 - it took me quite a while to figure out what was really going on). ...which for me prompts the question why it is even possible to deactivate that option at all... Also, is there a way to have Sisulizer also fall back to the host binary's own resource block for resources not contained in the resource DLLs? Or essentially any other way to reduce the size of the resource DLLs? Cheers, Oliver
|
||||||||||||||||
| |||||||||||||||||
| |||||||||||||||||
|
Janusz Grzybek Super Moderator
|
Hello,I found that I can get the same small resource DLLs when I disable the option to "Copy all resources" but then the program won't run because it couldn't find its forms and other resources I tested behavior of this feature with our VCL sample located in Sisulizer user directory\Vcl\Delphi\Converter\ and our example application works correctly (fallback works), when resource DLL contains only stringtable (I excluded forms in SLP). Could you upload to us your Delphi exe file (packed as zip) via Private Upload feature? We'll have a look st your file. Here is article info our upload system: http://www.the-localization-tool.com/?p=808 Best regards, Janusz [code]
____________________ http://www.sisulizer.com - Three simple steps to localize |
||||||||||||||||
| |||||||||||||||||
|
|||||||||||||||||
|
ogiesen Member
|
Janusz Grzybek wrote:I tested behavior of this feature with our VCL sample located in Sisulizer user directoryVclDelphiConverter and our example application works correctly (fallback works), when resource DLL contains only stringtable (I excluded forms in SLP). Whoops, OK, that's good news then. Seems I was a bit quick at drawing conclusions then... Could you upload to us your Delphi exe file (packed as zip) via Private Upload feature? We'll have a look st your file. I'll see what I can do. Please note that the file in question is not an EXE but a COM-DLL (also see the SO question linked in my original message for more details). Also, the "main form" it fails to load is actually a data module descendant (from the Add-in-Express framework). To test, you can simply pass the DLL to regsvr32.exe while a resource DLL for the current default locale is in the same directory. I'll see if I can produce a small sample project. Probably not today, though... Cheers, Oliver
|
||||||||||||||||
| |||||||||||||||||
| |||||||||||||||||
|
Janusz Grzybek Super Moderator
|
Hi Olivier,I'll see what I can do. Please note that the file in question is not an EXE but a COM-DLL (also see the SO question linked in my original message for more details). Also, the "main form" it fails to load is actually a data module descendant (from the Add-in-Express framework). It could make difference. I'm not Delphi developer, so I'll forward it to Ilkka (our VCL guru Janusz
____________________ http://www.sisulizer.com - Three simple steps to localize |
||||||||||||||||
| |||||||||||||||||
|
|||||||||||||||||
|
ogiesen Member
|
Thanks! I have now uploaded a minimal sample project exhibiting the problem. Hope this helps and looking forward to your (or Ilkka's) comments. Happy towel day everyone! Cheers, Oliver
|
||||||||||||||||
| |||||||||||||||||
| |||||||||||||||||
|
Ilkka.Salmenius Administrator
|
Hi Oliver, Thank you for your files. I reproduced the error you described. However when I tried to reproduce it with my sample I could not. What I did I wrote a simple Delphi application that gets the UI text from resource strings. The I used Sisulizer to create resource DLL that only contain string resources. The size of the DLL was minimal. About 17 kB when the the size with all resources was 350 kB. When I ran my application it worked just all right. VCL correctly used form resources of the EXE when there was no form resource in DLL. This must be related to your sample and/or the Delphi version you use. 1) What Delphi do you use? 2) Can you send me the full source code of the sample (the simplest one) you sent us. Best regards, Ilkka
____________________ http://www.sisulizer.com - Three simple steps to localize |
||||||||||||||||
| |||||||||||||||||
|
|||||||||||||||||
|
ogiesen Member
|
Hi Ilkka, I'm using Delphi XE2 with Update 4 and Hotfix 1 (32bit for now). The full source code for the simple example was already included in the DummyApp.zip archive I sent (the second upload from me). Please let me know if I should upload again. Edit: Sorry, I just noticed that previously I had in fact not uploaded the DummyApp.zip file I mentioned above but just the original Dummy.zip again. I have now (hopefully) uploaded the correct file. Hope this helps. Kind regards, Oliver Last edited on Tue May 29th, 2012 09:02 am by ogiesen |
||||||||||||||||
| |||||||||||||||||
| |||||||||||||||||
|
ogiesen Member
|
Ilkka, have you been able to make any progress with this? Did you receive the sample I uploaded on Tuesday? Cheers, Oliver
|
||||||||||||||||
| |||||||||||||||||
|
|||||||||||||||||
|
Ilkka.Salmenius Administrator
|
I am working on this. Ilkka
____________________ http://www.sisulizer.com - Three simple steps to localize |
||||||||||||||||
| |||||||||||||||||
| |||||||||||||||||
|
ogiesen Member
|
Hi Ilkka, FWIW: I can still reproduce the problem with the latest Sisulizer build. Do you already know whether this is more likely caused by a configuration error on my end or a bug in Sisulizer? Could you maybe send me the sample that you produced which does not exhibit the problem so I could compare the differences myself? I expect our product to RTM before the end of the month and I'd prefer not to increase the size of the download package unnecessarily... Cheers, Oliver
|
||||||||||||||||
| |||||||||||||||||
|
|||||||||||||||||
|
Ilkka.Salmenius Administrator
|
Hi Oliver, Sorry about this delay. I debugged VCL source code and noticed that the logic has been changed (don't know excatly when). Previously form loading was done such way that it first used the current resource intance (that was the handle of loaded resource DLL if any). If that failed the VCL used the main resource instance (that is the handle of the EXE itself). Unfortunately the current VCL does not work on this way any more. If there is a loaded resource DLL VCL expects that it contains all form resources. So unchecking Copy all resources will break a Delphi application. However with little bit extra code you can get it working. The catch it that whenever Delphi tries to read the form resources the current resource intance handle must point to the EXE itself. When VCL application starts it tries to locate the default language (e,g, language that matches the UI of your OS). If it find such resource DLL VCL loads it and updates the current resource instance handle. Fortunately Sisulizer's VCL code contains code that can change it. Here is your code that I modified little bit. uses LaResource; resourcestring SLabelCaption = 'Original Caption from resourcestring constant, set in code'; function GetDefaultLocale: String; var buffer: array[0..260] of Char; begin if (GetModuleFileName(LibModuleList.Instance, buffer, SizeOf(buffer)) > 0) then Result := GetLocaleOverride(buffer) else Result := ''; end; procedure TForm21.FormCreate(Sender: TObject); begin // Before accessing resource string we temporary load a new resource DLL LoadNewResourceFile(GetDefaultLocale); Label1.Caption := SLabelCaption; LoadNewResourceFile(''); end; initialization // This unloads any resource DLL automatically loaded by VCL DisableResourceDllUse; end. I hope this will help you. Ilkka
____________________ http://www.sisulizer.com - Three simple steps to localize |
||||||||||||||||
| |||||||||||||||||
| |||||||||||||||||
|
ogiesen Member
|
Wow, that is a real bummer... Why did they ever remove the fallback functionality?! The code I sent was merely the simplest possible project that would exhibit the problem and there your workaround sure seems straightforward enough. I'm pretty sure however that shoehorning this into our actual production code (containing numerous forms and data modules as well as the ability to switch languages at runtime) will probably be a really significant effort... I think I'd seriously consider patching the VCL instead to reestablish the previous behaviour... What was the Delphi version that you originally tested this with where the fallback was still working and where can I find the relevant VCL code to look at? Is it in the Forms unit? Or Classes or System? Cheers and thanks for pinning this down. Oliver
|
||||||||||||||||
| |||||||||||||||||
|
|||||||||||||||||
|
Ilkka.Salmenius Administrator
|
When we wrote the initial Sisulizer VCL code Delphi 7 was the most recent version. 7 still contained fallback. You can get XE2 working also by modifing System.Classes.pas function InitInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean; function InitComponent(ClassType: TClass): Boolean; begin Result := False; if (ClassType = TComponent) or (ClassType = RootAncestor) then Exit; Result := InitComponent(ClassType.ClassParent); Result := InternalReadComponentRes(ClassType.ClassName, FindResourceHInstance(FindClassHInstance(ClassType)), Instance) or Result; >> Add here. It result is False then try to get the from from EXE's instance if not Result then Result := InternalReadComponentRes(ClassType.ClassName, FindExeHInstance(FindClassHInstance(ClassType)), Instance) or Result; >> You need to write FindExeHInstance that return the Module.Instance instead of Module.ResInstance Something like this function FindExeHInstance(Instance: HINST): HINST; var CurModule: PLibModule; begin CurModule := LibModuleList; while CurModule <> nil do begin if (Instance = CurModule.Instance) or (Instance = CurModule.CodeInstance) or (Instance = CurModule.DataInstance) then begin Result := CurModule.Instance; Exit; end; CurModule := CurModule.Next; end; Result := Instance; end; Wait a moment. I will try this. Best regards, Ilkka
____________________ http://www.sisulizer.com - Three simple steps to localize |
||||||||||||||||
| |||||||||||||||||
| |||||||||||||||||
|
Ilkka.Salmenius Administrator
|
Here is how you get to done in XE2 1) Copy System.Classes.pas from VCL source code into the project directory 2) Add that System.Classes.pas into your Delphi project. This makes Delphi to use it instead of the standard System.Classes.pas 3) Locale the following code and add those lines that I have marked with //Ilkka function InitInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean; //Ilkka function FindOriginalHInstance(Instance: HINST): HINST; var CurModule: PLibModule; begin CurModule := LibModuleList; while CurModule <> nil do begin if (Instance = CurModule.Instance) or (Instance = CurModule.CodeInstance) or (Instance = CurModule.DataInstance) then begin Result := CurModule.Instance; Exit; end; CurModule := CurModule.Next; end; Result := Instance; end; //Ilkka function InitComponent(ClassType: TClass): Boolean; begin Result := False; if (ClassType = TComponent) or (ClassType = RootAncestor) then Exit; Result := InitComponent(ClassType.ClassParent); Result := InternalReadComponentRes(ClassType.ClassName, FindResourceHInstance(FindClassHInstance(ClassType)), Instance) or Result; //Ilkka if not Result then Result := InternalReadComponentRes(ClassType.ClassName, FindOriginalHInstance(FindClassHInstance(ClassType)), Instance) or Result; //Ilkka end; var LocalizeLoading: Boolean; begin GlobalNameSpace.BeginWrite; // hold lock across all ancestor loads (performance) try LocalizeLoading := (Instance.ComponentState * [csInline, csLoading]) = []; if LocalizeLoading then BeginGlobalLoading; // push new loadlist onto stack 4) Recompile you project and now it should work with minimal resource DLLs. Ilkka
____________________ http://www.sisulizer.com - Three simple steps to localize |
||||||||||||||||
| |||||||||||||||||
|
|||||||||||||||||
|
ogiesen Member
|
OK, thanks, I'll give that a try. BTW: While you were writing this I literally took a trip down to the archive to retrieve our physical copy of Delphi 7 from a stack of unlabelled moving boxes... (hadn't really expected that to happen any time soon I then loaded up the two copies of Classes.pas in WinMerge to see how Delphi 7 implemented the fallback. Interestingly, except for whitespace, the code of InitInheritedComponent (including InitComponent) has not changed at all between Delphi 7 and XE2... seems the fallback must have been handled somewhere else at that time... (I haven't located it yet). Thanks again! I'll keep you posted. P.S.: I haven't tried yet, but what about other types of resources that I did not translate and that are consequently not included in my resource DLLs when I uncheck "Copy all" (e.g. resource strings in third-party libraries like the JEDI Code Library). Will Delphi XE2 still fall back to the originals for those? Cheers, Oliver
|
||||||||||||||||
| |||||||||||||||||
| |||||||||||||||||
|
Ilkka.Salmenius Administrator
|
I tested with Delphi 7 and it caused the same error. It seems that I was wrong an manybe the fallback has never been there. That makes sense because it would not make any sence that Borland/CodeGear/Embacadero would have removed it. Ilkka
____________________ http://www.sisulizer.com - Three simple steps to localize |
||||||||||||||||
| |||||||||||||||||
|
|||||||||||||||||
|
ogiesen Member
|
Hmm, what version did you use then when the fallback did (seem to) work (rf. your post from 26 May)? Or was that a test case error? Cheers, Oliver
|
||||||||||||||||
| |||||||||||||||||
| |||||||||||||||||
|
Ilkka.Salmenius Administrator
|
I used XE2. The difference was the in my first sample the application did not initially load a resource DLL but used the original resources. The error occurs only then application creates a form in the situation where there is a resource DLL loaded. Ilkka
____________________ http://www.sisulizer.com - Three simple steps to localize |
||||||||||||||||
| |||||||||||||||||
|
|||||||||||||||||
|
ogiesen Member
|
Right. I think I've got it working now. There was a bug in your suggested code, though: It didn't work with form inheritance when one of the ancestor forms also had a DFM resource. This is how my local InitComponent looks now:
P.S.: Instead of copying all of Classes.pas I used code hooking to patch InitInheritedComponent in isolation (based on code from Andreas Hausladen's VCLFixPack). Cheers and thanks again for helping me figure this out, Oliver
|
||||||||||||||||
| |||||||||||||||||
| Current time is 04:27 am | |
| .NET, Delphi, ... - Sisulizer Localization Tool Support > Technical Support (You need to be registered at the forum to write) > Bugs and Quirks in Sisulizer > Is it possible to turn off the "Copy all resources" option at all? | |
Sisulizer software localization tool - Three simple steps to localize