Support forum of the software localization tool Sisulizer


.NET, Delphi, ... - Sisulizer Localization Tool Support Home

Get in contact with the makers of Sisulizer.
Our forum is open for all questions around Sisulizer from customers and prospects.
Don't hesitate to register and ask. The Sisulizer team will answer ASAP.

Search     Help Home Sisulizer Website Download
Search by username
Not logged in - Login | Register 

 Moderated by: Renate.Reinartz, Markus.Kreisel, Sisusupport, Ilkka.Salmenius
New Topic Reply Printer Friendly
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
AuthorPost
 Posted: Thu May 24th, 2012 01:58 pm
PM Private Upload Quote Reply
ogiesen
Member
 

Joined: Wed May 9th, 2012
Location:  
Posts: 13
Status: 
Offline
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

Back To Top PM Private Upload Quote Reply

 Posted: Thu May 24th, 2012 02:28 pm
PM Private Upload Quote Reply
Janusz Grzybek
Super Moderator


Joined: Fri Dec 1st, 2006
Location: Zabrze, Poland
Posts: 3234
Status: 
Offline
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
Back To Top PM Private Upload Quote Reply

 Posted: Thu May 24th, 2012 02:46 pm
PM Private Upload Quote Reply
ogiesen
Member
 

Joined: Wed May 9th, 2012
Location:  
Posts: 13
Status: 
Offline
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

Back To Top PM Private Upload Quote Reply

 Posted: Thu May 24th, 2012 02:56 pm
PM Private Upload Quote Reply
Janusz Grzybek
Super Moderator


Joined: Fri Dec 1st, 2006
Location: Zabrze, Poland
Posts: 3234
Status: 
Offline
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
Back To Top PM Private Upload Quote Reply

 Posted: Fri May 25th, 2012 02:27 pm
PM Private Upload Quote Reply
ogiesen
Member
 

Joined: Wed May 9th, 2012
Location:  
Posts: 13
Status: 
Offline
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

Back To Top PM Private Upload Quote Reply

 Posted: Sat May 26th, 2012 03:49 am
PM Private Upload Quote Reply
Ilkka.Salmenius
Administrator


Joined: Wed Aug 8th, 2007
Location: Tokyo, Japan
Posts: 1466
Status: 
Offline
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
Back To Top PM Private Upload Quote Reply

 Posted: Tue May 29th, 2012 08:31 am
PM Private Upload Quote Reply
ogiesen
Member
 

Joined: Wed May 9th, 2012
Location:  
Posts: 13
Status: 
Offline
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

Back To Top PM Private Upload Quote Reply

 Posted: Fri Jun 1st, 2012 07:50 am
PM Private Upload Quote Reply
ogiesen
Member
 

Joined: Wed May 9th, 2012
Location:  
Posts: 13
Status: 
Offline
Ilkka,

have you been able to make any progress with this? Did you receive the sample I uploaded on Tuesday?

Cheers,

Oliver

Back To Top PM Private Upload Quote Reply

 Posted: Sat Jun 2nd, 2012 02:51 am
PM Private Upload Quote Reply
Ilkka.Salmenius
Administrator


Joined: Wed Aug 8th, 2007
Location: Tokyo, Japan
Posts: 1466
Status: 
Offline
I am working on this.

Ilkka



____________________
http://www.sisulizer.com - Three simple steps to localize
Back To Top PM Private Upload Quote Reply

 Posted: Mon Jun 11th, 2012 12:15 pm
PM Private Upload Quote Reply
ogiesen
Member
 

Joined: Wed May 9th, 2012
Location:  
Posts: 13
Status: 
Offline
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

Back To Top PM Private Upload Quote Reply

 Posted: Mon Jun 11th, 2012 09:32 pm
PM Private Upload Quote Reply
Ilkka.Salmenius
Administrator


Joined: Wed Aug 8th, 2007
Location: Tokyo, Japan
Posts: 1466
Status: 
Offline
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
Back To Top PM Private Upload Quote Reply

 Posted: Tue Jun 12th, 2012 10:49 am
PM Private Upload Quote Reply
ogiesen
Member
 

Joined: Wed May 9th, 2012
Location:  
Posts: 13
Status: 
Offline
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

Back To Top PM Private Upload Quote Reply

 Posted: Tue Jun 12th, 2012 11:18 am
PM Private Upload Quote Reply
Ilkka.Salmenius
Administrator


Joined: Wed Aug 8th, 2007
Location: Tokyo, Japan
Posts: 1466
Status: 
Offline
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
Back To Top PM Private Upload Quote Reply

 Posted: Tue Jun 12th, 2012 11:30 am
PM Private Upload Quote Reply
Ilkka.Salmenius
Administrator


Joined: Wed Aug 8th, 2007
Location: Tokyo, Japan
Posts: 1466
Status: 
Offline
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
Back To Top PM Private Upload Quote Reply

 Posted: Tue Jun 12th, 2012 12:09 pm
PM Private Upload Quote Reply
ogiesen
Member
 

Joined: Wed May 9th, 2012
Location:  
Posts: 13
Status: 
Offline
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

Back To Top PM Private Upload Quote Reply

 Posted: Tue Jun 12th, 2012 12:57 pm
PM Private Upload Quote Reply
Ilkka.Salmenius
Administrator


Joined: Wed Aug 8th, 2007
Location: Tokyo, Japan
Posts: 1466
Status: 
Offline
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
Back To Top PM Private Upload Quote Reply

 Posted: Tue Jun 12th, 2012 01:39 pm
PM Private Upload Quote Reply
ogiesen
Member
 

Joined: Wed May 9th, 2012
Location:  
Posts: 13
Status: 
Offline
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

Back To Top PM Private Upload Quote Reply

 Posted: Tue Jun 12th, 2012 01:44 pm
PM Private Upload Quote Reply
Ilkka.Salmenius
Administrator


Joined: Wed Aug 8th, 2007
Location: Tokyo, Japan
Posts: 1466
Status: 
Offline
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
Back To Top PM Private Upload Quote Reply

 Posted: Wed Jun 13th, 2012 01:07 pm
PM Private Upload Quote Reply
ogiesen
Member
 

Joined: Wed May 9th, 2012
Location:  
Posts: 13
Status: 
Offline
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:
function InitComponent(AClassType: TClass): Boolean;
var
lClassHInstance: HINST;
begin
Result := False;
if (AClassType = TComponent) or (AClassType = ARootAncestor) then Exit;
Result := InitComponent(AClassType.ClassParent);
lClassHInstance := FindClassHInstance(AClassType);
Result := InternalReadComponentRes(AClassType.ClassName, FindResourceHInstance(lClassHInstance), AInstance)
or InternalReadComponentRes(AClassType.ClassName, FindOriginalHInstance(lClassHInstance), AInstance)
or Result;
end;
(BTW: how did you manage to post properly indented code here earlier?)

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

Back To Top PM Private Upload Quote Reply

Current time is 05:58 pm  
.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?



WowUltra modified by Sisulizer Copyright © 2007-09 by Jim Hale - Based on WowBB Copyright © 2003-2006 Aycan Gulez

Sisulizer software localization tool - Three simple steps to localize