zed 14 Posted March 23, 2023 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
Anders Melander 1813 Posted March 23, 2023 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
CTorres 0 Posted July 12 (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 July 12 by CTorres Share this post Link to post
Anders Melander 1813 Posted July 12 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
CTorres 0 Posted July 12 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
limelect 48 Posted July 21 (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 July 21 by limelect Share this post Link to post
Anders Melander 1813 Posted July 21 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): ...and then selecting the desired target languages: Share this post Link to post
aehimself 399 Posted July 21 @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
Anders Melander 1813 Posted July 21 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
limelect 48 Posted July 22 (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 July 22 by limelect Share this post Link to post
Anders Melander 1813 Posted July 22 2 hours ago, limelect said: But my main problem is simple. In your demo Am I suppose to see the translated text Specify the project Source language. Specify the current Target language. Enter the translations in the grid. 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
Attila Kovacs 631 Posted Monday at 09:36 AM (edited) So far, I’ve never had to deal with multilingualism, and now I need to implement a language that I not only don’t understand but can’t even comprehend its character set. I was thinking of hooking the TReader and sending certain properties to ChatGPT to translate them within a specific context and with a maximum length, then storing the result in a database. At runtime. Thoughts? By the way, why are you messing around with a Hunspell checker instead of hooking the program up to ChatGPT? It would translate everything in an instant, and with an extra command input, it could even be fine-tuned. Edited Monday at 09:48 AM by Attila Kovacs Share this post Link to post
Anders Melander 1813 Posted Monday at 11:10 AM 1 hour ago, Attila Kovacs said: So far, I’ve never had to deal with multilingualism, and now I need to implement a language that I not only don’t understand but can’t even comprehend its character set. I was thinking of hooking the TReader and sending certain properties to ChatGPT to translate them within a specific context and with a maximum length, then storing the result in a database. At runtime. Thoughts? If this is for a professional project then you should approach the problem like a professional; Either have the translations done by a translation bureau, a native speaker of the language, or use an online translation service. If on the other hand this is just for a hobby project then go ahead and experiment with your toy. Just don't post about it here, please. Start a new thread. 1 hour ago, Attila Kovacs said: By the way, why are you messing around with a Hunspell checker instead of hooking the program up to ChatGPT? It would translate everything in an instant, and with an extra command input, it could even be fine-tuned I'm using a spell checker because I need something that was actually designed for the task; Is fast, has reliable output and works even when the user is offline. Share this post Link to post
Robert_RR 0 Posted Monday at 05:03 PM Guys, I really need help!!! I'm using BTM to do the translations and the software is great, with lots of details. But I don't know how to incorporate the file generated after the translation into my software. Does anyone know of a tutorial, or could someone teach me how to do it? I've never worked with Deploying a Localized Application. Share this post Link to post
Anders Melander 1813 Posted Monday at 05:25 PM 3 minutes ago, Robert_RR said: I don't know how to incorporate the file generated after the translation into my software. Does anyone know of a tutorial, or could someone teach me how to do it? https://bitbucket.org/anders_melander/better-translation-manager/src/master/#markdown-header-deploying-a-localized-application Basically, you just place the generated language module(s) in the same folder as your exe file and that's it; When you run the application the Delphi RTL will take care of loading the correct module based on the Windows language settings. For example, let's say you have a Delphi project named foobar.dproj and a BTM project file named whatever-it_doesnt_matter.xlat. Your BTM project contains translations for Danish and German. The base language is English. When you compile your project with Delphi you get foobar.exe containing the English texts. When you build the language modules, using BTM, you get foobar.dan and foobar.ger. Place foobar.exe, foobar.dan, and foobar.ger in the same folder and run. That's pretty much all there is to it. If you want the language to be configurable (i.e. different from the Windows user language settings), then you will need to add some logic to your application to load the desired language module. Here's one way to do it: https://bitbucket.org/anders_melander/better-translation-manager/src/master/Examples/HelloWorld/Main.pas Share this post Link to post