Jump to content
Anders Melander

ANN: Better Translation Manager released

Recommended Posts

No, I mean what should I do in my Test.exe to make it possible to load translations from some subfolder? I don't like idea to keep this files in the application root folder.

Share this post


Link to post
7 hours ago, zed said:

No, I mean what should I do in my Test.exe to make it possible to load translations from some subfolder? I don't like idea to keep this files in the application root folder.

Ah, I see. No, that isn't really supported, but I can see how that would be beneficial. I've created an issue for it: https://bitbucket.org/anders_melander/better-translation-manager/issues/39

 

Assuming you are using BTMs resource module load functions (amLocalization.Utils unit), you will have to modify the following function in the amLanguageInfo unit:

function LoadNewResourceModule(LocaleItem: TLanguageItem; var ModuleFilename: string): HModule; overload;

For example, change this:

ModuleFilename := TPath.ChangeExtension(Filename, '.'+FileType);

...to this (note that this hard codes the sub-folder name):

var Folder := TPath.Combine(TPath.GetDirectoryName(Filename), '.\lang');
ModuleFilename := TPath.Combine(Folder, TPath.GetFileNameWithoutExtension(Filename)+'.'+FileType);

 

If you are using the RTLs built-in loading mechanism then there isn't any way I can think of.

Share this post


Link to post
Posted (edited)

Hi,

 

First of all I wanted to thank Anders Melander for his application and for sharing it with the whole developer community.

 

I am posting here because I have encountered a problem when dynamically loading the language libraries generated with BTM in projects developed with newer versions of Delphi, and I was hoping someone could help me.

 

I've been using BTM for quite some time now and I developed the software under Delphi XE, here I have never had any problems. Things changed when I recently upgraded to more modern versions of Delphi (Delphi 11 and 12) and, after updating the corresponding BTM projects and generating the languages normally, when I changed at run time the language of my applications, the texts that come from resourcestrings were no longer translated.

 

All the DFM controls appear perfectly translated in the language I have selected within the application, but in those points where the text is defined dynamically from a resourcestring, they are always shown in the original language in which I defined them.

 

I load the language libraries with the reinit.pas unit and its LoadNewResourceModule, and I've never had any problem before with older versions of Delphi.

 

Does anyone know why it treats differently the DFM texts (which it shows perfectly translated) and the resourcestrings (which it doesn't translate at all) and what I could do to fix it?

 

Any help will be appreciated. Thanks!

 

------------- EDIT -------------

It always happens the same, after spending days trying to solve a problem without success, as soon as I ask for help I find the solution right under my nose.

I found this post (I don't know how I missed it earlier) on this very forum: 

 

It describes my same problem and gives a solution by calling ResStringCleanupCache before loading the language library. I have tried it and now everything works perfectly.

Thanks anyway and sorry for the inconvenience.

 

Edited by CTorres

Share this post


Link to post
13 minutes ago, CTorres said:

Does anyone know why it treats differently the DFM texts (which it shows perfectly translated) and the resourcestrings (which it doesn't translate at all) and what I could do to fix it?

The RTLs DFM and resourcestring load mechanisms are separate and, for the most part, completely different.

 

The RTL's resourcestring handling changed in a recent version of Delphi and, assuming your dynamic resource DLL loader doesn't take this into account, I suspect that this is the cause of your problem.

 

The problem is likely that the RTL is caching both the resolved resourcestrings and the resource module, so once a resource module has been loaded and a resourcestring has been resolved it will not be read from the resource module again. My guess is that since your dynamic resource module loader probably executes after the RTL has already loaded the default resource module, your module is ignored.

 

If you place a breakpoint in System.pas LoadResString and run your application you will be able to see the sausages being made. You should end up in DelayLoadResourceModule (via FindResourceHInstance) where the decision is made to reuse an already loaded resource module if there is one or load one if there isn't (FWIW, the DFM loader also goes through this function).

Once system.pas has done its thing, sysutils.pas replaces the default resourcestring loader with a caching string loader, so all resourcestrings resolved after that point will be cached.

 

If all my guessed are correct, the solution will be to modify the resource entry of the main module record (maybe your solution already does this). Something like this:

var Module: PLibModule := LibModuleList;
while (Module <> nil) do
begin
  if (Module.Instance = hInstance) then
  begin
    Module.ResInstance := TheModuleHandleOfYourResourceModule;
    break;
  end;
  Module := Module.Next;
end;

Note that this will not change the already cached resourcestrings. In order to do that you will need to call SysUtils.ResStringCleanupCache

 

 

If the above doesn't solve the problem for you I will need you to:

  • Create an issue at the bug tracker
  • Attach a minimal reproducible example

and I'll see if I can find a solution.

Share this post


Link to post

Thank you very much for your help, Anders.

Indeed, the problem is that it loaded both modules but it cached the first one, the one of the original language, and from there it ignored the one of the selected language.

I have solved it with the call to SysUtils.ResStringCleanupCache, thank you very much (updating the instance of the loaded module was already done before, but of course, with the resourcestrings already cached it had no effect).

 

Best regards and thanks for your time!

Share this post


Link to post
Posted (edited)

I have your demo In it HelloWorld.xlat

I do not seem to translate. How am I translating?

Your demo does not seem to show that

Edited by limelect

Share this post


Link to post
6 hours ago, limelect said:

I do not seem to translate. How am I translating?

Your question doesn't make sense. Please rephrase it.

 

You message, before you edited it, said "No HEBREW to translate". If you are asking how to add an additional target language, then that is done by clicking on the little settings button on the Language bar (yes, it's a bad UI, I know):

image.png.83152d6216a23af5d899ee612a4a42bc.png

 

...and then selecting the desired target languages:

image.thumb.png.6c2074f52d5ef3f0b58029b272d81535.png

Share this post


Link to post

@Anders Melander Is an auto-update feature planned for BTM in the future? That, and a filter to only show untranslated and/or changed entries would make BTM a perfect tool imo. Thank you very much for it!

Share this post


Link to post
33 minutes ago, aehimself said:

Is an auto-update feature planned for BTM in the future?

Not really but it's a very reasonable feature request. Please create an issue for it.

 

36 minutes ago, aehimself said:

a filter to only show untranslated and/or changed entries

I assume you mean a filter on the module list because you can hide already translated entries by filtering on State=Pending in the property list.

If so, please create an issue for this too.

Share this post


Link to post
Posted (edited)

@Anders Melander Ok I found the HEBREW

But my main problem is simple. In your demo

Am I suppose to see the translated text

 

It seems I do not understand how to use the source and the .xlat file

I have been using DKLang for many years

Can you elaborate on steps of new Delphiproject

 

I am also trying to change in your application the source lang from Hebrew to English and I cannot

Edited by limelect

Share this post


Link to post
2 hours ago, limelect said:

But my main problem is simple. In your demo

Am I suppose to see the translated text

  1. Specify the project Source language.
  2. Specify the current Target language.
  3. Enter the translations in the grid.

image.thumb.png.639e5cf57292e8ffc0611513ed5c2579.png

 

 

2 hours ago, limelect said:

It seems I do not understand how to use the source and the .xlat file

I don't know what you mean by "how to use the source".

The xlat file is BTM's translation project file; It contain the source texts and the translated texts for all selected target languages of the application being localized. BTM uses the information in this file to build the language modules (which are in fact just code-less DLLs containing the translated resourcestring and DFM resources) that are loaded at run-time by your application. See the Delphi help for info about how the Delphi localization system works (I believe I have some info at the project page too).

 

 

2 hours ago, limelect said:

Can you elaborate on steps of new Delphiproject

See: Getting started

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×