UCT_24 0 Posted May 16 Hello, i am having trouble "localizing" VCL built-in dialogs. Generally, i think there is multi-language support for the VCL. Also, there are means of localizing custom forms and vcl controls at runtime. But i could not find documentation or examples on how i can have for example the buttons in a "Vcl.Forms.TApplication.MessageBox" displayed with english or german captions? The Captions vary when using the System settings, switching "Windows language", but i would like to switch language "at runtime" of the application, so, if you like. To be more precise: For example i call the MessageBox function and have it displaying one "OK" and one "CANCEL" button. I would like to make sure in application code that the Button Captions are displayed in english or german (independent of the windows language settings). The same applies for the VCL "Dialogs::MessageDlg" buttons. Buttons are added by "System::Uitypes::TMsgDlgBtn"-type idenifiers, but the resulting buttons on the form can not be localized in the described way. This should also apply for "shortcut" caption extensions. For example i add a menu with a TShortCut that is using a key identifier (extern DELPHI_PACKAGE System::Classes::TShortCut __fastcall ShortCut(System::Word Key, System::Classes::TShiftState Shift);). These ShortCuts are displayed on the UI as a "caption extension". But i do not know how to have them displayed according to language chosen at runtime. Is this maybe impossible to switch display language of such controls at runtime? And if possible, does anyone know how to achieve this? Thanks in advance and kind regards, Ulrich Share this post Link to post
Anders Melander 1815 Posted May 16 Button captions and such are defined by resourcestrings. For example, see Vcl.Consts.pas: resourcestring [...lots of strings...] SOKButton = 'OK'; SCancelButton = 'Cancel'; SYesButton = '&Yes'; SNoButton = '&No'; SHelpButton = '&Help'; SCloseButton = '&Close'; SIgnoreButton = '&Ignore'; SRetryButton = '&Retry'; SAbortButton = 'Abort'; SAllButton = '&All'; You can use any of of the many different localization solutions to have them translated. E.g. this one: https://bitbucket.org/anders_melander/better-translation-manager Share this post Link to post
UCT_24 0 Posted May 16 Many thanks for your reply, i will check this file. I have read about resource strings before, and i was sure that there are Resource Strings defined for all the standard dialogs. But how to switch between languages at runtime then (assumed i already have resource strings translated)? At the moment, as far as i can see, the VCL will consider the resource strings matching the windows language. Is there a specific function call to "force" a specific language/resource string mapping? Kind regards, ulrich Share this post Link to post
DelphiUdIT 187 Posted May 16 I use simply this, limited to common standard system strings, of course this is a skeleton ... form the Main program you can use it in this way: TTraduzione.ChangeValues('IT'); unit uTraduzione; interface uses WinApi.Windows, System.SysUtils, Vcl.Consts; Type TTraduzione = Class public class procedure SetResourceString(const xOldResourceString: PResStringRec; const xValueChanged: PChar); public class procedure ChangeValues(Lingua: string = ''); End; implementation class procedure TTraduzione.SetResourceString(const xOldResourceString: PResStringRec; const xValueChanged: PChar); var POldProtect: DWORD; PLostProtect: DWORD; begin VirtualProtect(xOldResourceString, SizeOf(xOldResourceString^), PAGE_READWRITE, @POldProtect); xOldResourceString^.Identifier := NativeUInt(xValueChanged); VirtualProtect(xOldResourceString, SizeOf(xOldResourceString^), POldProtect, @PLostProtect); end; class procedure TTraduzione.ChangeValues(Lingua: string = ''); begin if Lingua = 'IT' then begin //Carica la lingua italiana SetResourceString(@SMsgDlgYes, '&Si'); SetResourceString(@SMsgDlgWarning,'Attenzione'); SetResourceString(@SMsgDlgError, 'Errore'); SetResourceString(@SMsgDlgInformation, 'Informazione'); SetResourceString(@SMsgDlgConfirm , 'Conferma'); SetResourceString(@SMsgDlgNo , '&No'); SetResourceString(@SMsgDlgOK , 'OK'); SetResourceString(@SMsgDlgCancel , 'Annulla'); SetResourceString(@SMsgDlgHelp , '&Aiuto'); SetResourceString(@SMsgDlgHelpHelp , 'Aiuto'); SetResourceString(@SMsgDlgHelpNone , 'Nessun aiuto disponibile'); SetResourceString(@SMsgDlgAbort , '&Termina'); SetResourceString(@SMsgDlgRetry , '&Riprova'); SetResourceString(@SMsgDlgIgnore , '&Ignora'); SetResourceString(@SMsgDlgAll , '&Tutto'); SetResourceString(@SMsgDlgNoToAll , 'N&o a Tutto'); SetResourceString(@SMsgDlgYesToAll , 'Si a &Tutto'); SetResourceString(@SMsgDlgClose , '&Chiudi'); end else if Lingua = 'EN' then begin //Carica la lingua inglese SetResourceString(@SMsgDlgYes, '&Yes'); SetResourceString(@SMsgDlgWarning,'Warning'); SetResourceString(@SMsgDlgError, 'Error'); SetResourceString(@SMsgDlgInformation, 'Information'); SetResourceString(@SMsgDlgConfirm , 'Confirm'); SetResourceString(@SMsgDlgNo , '&No'); SetResourceString(@SMsgDlgOK , 'OK'); SetResourceString(@SMsgDlgCancel , 'Cancel'); SetResourceString(@SMsgDlgHelp , '&Help'); SetResourceString(@SMsgDlgHelpHelp , 'Help'); SetResourceString(@SMsgDlgHelpNone , 'No Help Available'); SetResourceString(@SMsgDlgAbort , '&Abort'); SetResourceString(@SMsgDlgRetry , '&Retry'); SetResourceString(@SMsgDlgIgnore , '&Ignore'); SetResourceString(@SMsgDlgAll , '&All'); SetResourceString(@SMsgDlgNoToAll , 'N&o to All'); SetResourceString(@SMsgDlgYesToAll , 'Yes to &All'); SetResourceString(@SMsgDlgClose , '&Close'); end else if Lingua = 'ES' then begin //Carica la lingua spagnola SetResourceString(@SMsgDlgYes, '&Si'); SetResourceString(@SMsgDlgWarning,'Advertencia'); SetResourceString(@SMsgDlgError, 'Error'); SetResourceString(@SMsgDlgInformation, 'Información'); SetResourceString(@SMsgDlgConfirm , 'Confirmar'); SetResourceString(@SMsgDlgNo , '&No'); SetResourceString(@SMsgDlgOK , 'OK'); SetResourceString(@SMsgDlgCancel , 'Cancelar'); SetResourceString(@SMsgDlgHelp , '&Ayuda'); SetResourceString(@SMsgDlgHelpHelp , 'Ayuda'); SetResourceString(@SMsgDlgHelpNone , 'No hay ayuda disponible'); SetResourceString(@SMsgDlgAbort , '&Termina'); SetResourceString(@SMsgDlgRetry , 'Intentar &otra vez'); SetResourceString(@SMsgDlgIgnore , '&Ignorar'); SetResourceString(@SMsgDlgAll , '&Todos'); SetResourceString(@SMsgDlgNoToAll , 'N&o a todo'); SetResourceString(@SMsgDlgYesToAll , 'S&i a todo'); SetResourceString(@SMsgDlgClose , '&Cerrar'); end else begin .................... .................... .................... end; end; 1 Share this post Link to post
Uwe Raabe 2064 Posted May 16 (edited) 18 minutes ago, UCT_24 said: At the moment, as far as i can see, the VCL will consider the resource strings matching the windows language. You can add a registry entry under HKEY_CURRENT_USER\SOFTWARE\Embarcadero\Locales for that. Of course that only works at application start, so no change at runtime possible. One tool supporting changing languages at runtime is Korzh Localizer. Edited May 16 by Uwe Raabe Share this post Link to post
UCT_24 0 Posted May 16 Thanks for your answers, i'll try that registry key. Switching language at program start might be enough if the language can be read from a configuration file. But, do i get this right, i have to add code to manipulate this registry key right at the entry point of the application? Or will it be necessarry to switch the registry key BEFORE the program is run, because VCL component initialization has already been done when i enter the main routine of the program? Thanks a lot so far and kind regards, Ulrich Share this post Link to post
Uwe Raabe 2064 Posted May 16 Another option could be calling SetLocaleOverride with the desired value. It just has to be done quite early as long as no resources are being loaded. Share this post Link to post
UCT_24 0 Posted May 16 Ok, so i think my best Option will be to try both and see what works better. I will keep you updated 🙂 Thanks again and kind regards, Ulrich Share this post Link to post
UCT_24 0 Posted May 22 Hello again, i tried to put a registry key in HKEY_CURRENT_USER\SOFTWARE\Embarcadero\Locales and took the existing keys as example. But using my .exe path as key and "en-GB" as Value (REG_SZ entry) does only affect some, but not all VCL dialogs. The "Vcl.Forms.TApplication.MessageBox" and the "FileChooser (not sure about the exact class name here)" are not affected by the registry key, but the "messageDlg" from the VCl and the Menu-Shortcut Captions are displayed as desired. I tried switching the language set for bds.exe, and this changes the display language of the bds.exe. Maybe i need to perform the steps to apply languages when compiling the application first? However, " SetLocaleOverride" Function does not seem to have an effect. Share this post Link to post
Uwe Raabe 2064 Posted May 22 15 minutes ago, UCT_24 said: The "Vcl.Forms.TApplication.MessageBox" and the "FileChooser (not sure about the exact class name here)" are not affected by the registry key These dialogs are not part of your application, but are provided by the operating system and thus follow the Windows settings. There is not much you can do about it. 17 minutes ago, UCT_24 said: I tried switching the language set for bds.exe, and this changes the display language of the bds.exe. The app BDSSetLang.exe found in teh Delphi bin folder has an option to change the Library language apart from the IDE language. This will use another set of resources when compiling your application. Share this post Link to post
UCT_24 0 Posted May 22 Hello, to your first reply, i was afraid so. However, it totally makes sense, unfortunately. Regarding the BDSSetLang, i will try this when i have the opportunity. Thanks a lot for your kind assistance, it helped me a lot. Kind regards, Ulrich Share this post Link to post