Delphi Localization and Internationalization |
Delphi (Wikipedia) and C++Builder (Wikipedia) are popular development tools for Windows, macOS, Linux, iOS, and Android. It is one of the best environments for localization. The reason is the structural user interface resource format (form file), very easy-to-use resource strings, excellent support for Unicode, and the possibility to compile everything into a single executable file. Soluling localization tool supports Delphi and C++Builder. All Delphi and C++Buider versions from Delphi 2.0 to most recent Delphi version are supported.
Using Soluling has several benefits. First is that it is based on the standard Delphi internationalization that includes using resource strings and RTL's I18N functions. The second is that you do not have to add any localization components to your forms or use any proprietary I18N code. We even wrote Soluling application in Delphi.
The following chapters describe the Delphi localization step by step.
The end of the document contains links to get the full source code of the samples. After reading this document, we recommend reading a tutorial about how to use Soluling.
Delphi has two frameworks. They are VCL and FireMonkey. Both frameworks have two main resource formats: forms and strings.
Framework | Description |
---|---|
VCL is the traditional Delphi framework that works only on Windows. You can compile the same project into 32-bit and 64-bit. Originally VCL was 16-bit (Delphi 1) but soon evolved into 32-bit (Delphi 2). Starting at Delphi XE2, VCL supports both 32-bit and 64-bit. The primary localization method is the binary localization. In addition, the project localization can be used. |
|
FireMonkey is a new cross-platform Delphi framework. It supports Windows, Linux, macOS, iOS, and Android. The components are similar to VCL, but some component names are different, and many properties are also different. FireMonkey does not support resource DLLs on mobile platforms (Android and iOS). If you target to mobile platforms, use the project localization. If you only target to Windows and macOS you can also use the binary localization. |
Delphi applications are written in Delphi language (Wikipedia) and compiled to a native executable file or files. Depending on the framework, the primary localization method is different. The available methods are:
When localizing VCL applications you don't need source codes but only the compiled application file(s).
After you have internationalized your application, create a new Soluling project, and select your original application (.exe
) or library (.dll
) file. Soluling adds the file into the project and extracts resources (e.g., forms and strings) from the file. If your application uses packages files (.bpl
) that have forms or string, add them to the project too. Translate the project and let Soluling to build the output files. Here you have two choices: localized files or resource DLL files.
Read more from How to localize Delphi applications.
A localized application or library file is the default build output. For each language in the project, Soluling creates one localized application file that is identical to the original application, except the resources are in a different language. So if you have an EXE file, you will get a set of EXE files. For example, the German EXE file will be in de subdirectory (e.g., de\Project1.exe
), and the French EXE will be in fr subdirectory (e.g., fr\Project1.exe
). If your project has several output platforms such as WIN32 and WIN64 add only one of those into your Soluling project. Then add the other files as platform files into the added file. Use Platform files frame of source dialog to add the platform files.
Soluling can also create resource libraries. VCL has built-in support for resource libraries. A resource library is a dynamic library (e.g., DLL) that contains only resources, no code. The file extension of the resource library is the language code, and the pathname is the same as the original file. For example, if you have Project1.exe
, then the German resource library is Project1.de
, and the French resource library is Project1.fr
.
You can make Soluling create localized application files or localized resource libraries or both. Read more about resource files.
If your Delphi project has several platforms or configurations, you will have multiple output files. If you add a platform or configuration, you might have to add the new output files into the Soluling project manually. All this might be frustrating and easy to forget. Fortunately, there is a simpler way. You don't add any application or library file into your Soluling project, but you add a Delphi project group file (.groupproj
). Soluling will then automatically locate the output files of the project and adds the output files into the project. If you modify your Delphi project such a way that there will be new output files, Soluling will automatically add those (unless you explicitly exclude them).
Mobile platforms of FireMonkey do not support resource DLLs. In addition, FireMonkey applications are mostly mobile application where one package has to support multiple languages. This makes it impossible to use binary localization. Instead, Soluling uses a special multilingual resource that is linked into your application. The resource contains localized forms, strings, and other resources such as images and audio data.
After you have internationalized your application, create a new Soluling project file, and select Delphi project file (.dproj
). Soluling adds the file into the project, finds all source code and form files of the project and extract resources (e.g., forms and strings) from the files. Translate the project and build the output file. The output file is a single multilingual resource file (NtLangRes.ntres
) that contains the form, strings, and other resources in the languages you have in the Soluling project file. Add this resource file as custom RCDATA resource into your Delphi project. Choose Project | Resource and Images from Delphi.
Make sure the resource identifier is NtLangRes. Add the NtResource unit, call _T function for each form, and compile your project. Now it is multilingual and enabled for the runtime language change. Project localization can also be used in VCL projects (Delphi XE or later). You also have a choice to deploy the resource file as a standalone file.
Read more from How to localize Delphi FireMonkey applications.
Soluling contains a third option to localize Delphi applications or part of the application: form files. You can add any form file (.dfm
or .fmx
) into a Soluling project. When scanning, the form data is scanned in the same way as the form would be part of a binary or project file. However, this is not the recommended way to localize a Delphi application. Use it only if you need to have localized form files. When localizing the complete applications, use either the binary localization or project localization.
It may seem confusing that Soluling supports two different localization methods for Delphi. We would like to have only one method, binary, but with mobile FireMonkey it is not possible. This is because mobile FireMonkey platforms do not have a resource library concept. All application code and resource must be in the single application file. The fact is that most customers need a multilingual deployment for their mobile applications. This is why we developed our resource format to store localized forms, strings, and images and to embed that resource file as a custom resource inside the application file.
Internationalization is a process where you enable your application for localization.
The most important part is to remove hardcoded strings.
Delphi has a built-in feature for this in Delphi language: resourcestring. You can use it if you use the binary localization with any Delphi version, or you use the project localization with Delphi 10.4 (Sydney) or later.
str := 'Hello world';
becomes to
resourcestring SHelloWorldMessage = 'Hello world'; ... str := SHelloWorldMessage;
Try to give a meaningful name for the resource string name. By default, the translator can only see the string name and the value. So SHelloWorldString
is a better name than SStr1
. If you want to pass more information to the translator, you can add comments to resource strings.
resourcestring SHelloWorldMessage = 'Hello world'; // loc This is a comment
Learn more about resource string comments.
When using the project localization with Delphi 10.3 or earlier, you cannot use a resource string feature. Instead, you wrap hard coded strings around _T function (in NtResource.pas).
str := 'Hello world';
becomes to
str := _T('Hello world');
You can also use Translate instead of _T. They are the same.
str := Translate('Hello world');
You can give an id for the string by passing a second parameter to the function.
str := _T('Hello world', 'HelloWorldMessage');
This makes it possible to add more than one "Hello world" strings and even translate them differently.
As with resource strings, you can add resource string comments.
str := _T('Hello world'); // loc This is a comment
Form files are the main resource files in a Delphi application. Each form is stored in a separate file. It uses is a text file format or optionally a binary file formal. Form files are embedded in the application file as a binary resource. VCL uses .dfm
file extension. FireMonkey uses .fmx
file extension. Even the file extension is different, both files use a similar file format. When Soluling localizes a form, it makes a full copy of the original form and then translates the selected properties. The properties are selected based on the scan property rules.
Delphi's class library, VCL, has built-in support to load a resource DLL when starting. By default, the available resource DLLs must locate on the same directory as the application, and the file name part must be the same. However, with Soluling's API, you can make your application load resource DLLs from any directory. The file extension of each resource DLL is the ISO language tag or Windows language code of the language the resource DLL uses. If the application is Project1.exe
, then the German resource DLL is Project1.de
, and German (Germany) resource DLL is Project.de-DE
.
Delphi attempts to load resources in the following order, stopping when it finds one:
In addition it is possible to disable resource DLLs.
First, Delphi looks if the system registry contains information about what resource DLL to load. This information is called the locale override. Delphi looks from following registry keys in order, stopping when it finds one:
Order | Key | Notes |
---|---|---|
1. | HKEY_CURRENT_USER\Software\Embarcadero\Locales | Delphi XE and later |
2. | HKEY_LOCAL_MACHINE\Software\Embarcadero\Locales | Delphi XE and later |
3. | HKEY_CURRENT_USER\Software\CodeGear\Locales | Delphi 2009 and later |
4. | HKEY_LOCAL_MACHINE\Software\CodeGear\Locales | Delphi 2009 and later |
5. | HKEY_CURRENT_USER\Software\Borland\Locales | |
6. | HKEY_CURRENT_USER\Software\Borland\Delphi\Locales |
If the application finds such an entry, it loads a resource DLL matching data of the entry. For example, if we have an application created by Delphi XE or later and the application file is C:\NT\Deploy\Samples\Delphi\Sport\Project1.exe
, then default place, where the locale override is written, is shown in the following picture.
If our application is D:\NT\Deploy\Samples\Delphi\Sport\Project1.exe
, then Delphi finds that de
extension should be used. It is going to look for D:\NT\Deploy\Samples\Sport\Project1.de
resource DLL file. If the resource DLL file is found, then Delphi uses resources of that file.
If no entry is found from the registry or the file matching the entry value does not exist, then the application is going to look for file matching the default locale. How this is done depends on the Delphi version that was used to compile the application.
The default locale is the user interface language of the operating system. It can not be changed without installing a new operating system or installing a multilingual operating system. If you want that your application still works like an application compiled with Delphi 2009 or older, you have to add NtInitialLocale into your application such way that its initialization party is called before application loads any resources. The right place is to add it as the first unit in the uses section of the program file.
program LanguageSwitch; uses NtInitialLocale, Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.Run; end.
NtInitialLocale is located on <data-dir>\Library\Delphi\NtInitialLocale.pas.
If you want to see in more detail how VCL choose the language look for <delphi-dir>\Source\Win32\rtl\sys\System.pas
and look for LoadResourceModule
function. It performs the resource DLL loading.
The default locale is the default locale of the user. This setting is specified in Regional and Language sheet of Control Panel.
If the user default locale is German (Germany), the application is going to look for Project1.de-DE
. If that is not found, then the application looks for a country neutral resource. In this case, if Project1.de
is found, the application uses that.
If the original language is not English and you run your application on a Windows which languages matches the original language of your application (e.g., originally German application on a German Windows), and you have an English resource DLL (e.g., Project1.en), the application will start in English. This is because there is no resource DLL matching the default languages (i.e., the languages of the OS) VCL will use an English resource DLL if any. To fix this, you have to add the following lines in the initialization of your main unit.
initialization TNtBase.SetInitialLocale(lsSettings, 'de'); end.
The above code sets the default language to German, and on a German Windows unloads the English resource DLL that VCL has loaded by default.
If the application can not find any of the above resource DLLs, it will use the original resources of the application or library file. Our sample application will use the resources of Project1.exe
.
There is no direct way to disable Delphi's build-in resource loading. If there is a matching resource DLL, the application will load it. The easiest way to disable using them is to remove the resource DLL file(s). If you want to keep them but not use them, there is a way to unload the loaded resource DLLs. This makes it possible to disable resource DLLs. To disable them, call TNtResource.DisableResourceDlls
function. The function must be called before the application creates any forms. A good place for that is the initialization part of the main unit.
initialization TNtResource.DisableResourceDlls; end.
See <data-dir>\Samples\Delphi\IgnoreResourceDll
sample.
By default Delphi's RTL expects resource DLL files to locate in the same directory as the application or library files. For example, if your application is in C:\Samples\Project1.exe
, then the German resource file should be in C:\Samples\Project1.de
. If you want to store the resource DLL on a different directory, you have to use TNtBase.SetResourceDllDir
method. You need to call this function before any form gets created. A good place would be the .dpr
file.
program CustomDir; uses NtBase, Vcl.Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} begin // By default resource DLL directory is the same as the application dir. // if you want to use some other directory set the resource DLL directory before calling Initialize or CreateForm. TNtBase.SetResourceDllDir('Output'); Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.Run; end.
The above code sets the resource DLL directory to be the Output sub directory of the application directory. The function also loads the resource DLL matching the initial language.
See <data-dir>\Samples\Delphi\CustomDir
sample.
Delphi has a built-in feature to use resource DLLs. This makes it possible to deploy the same application file (.exe
or .dll
) with different resource DLLs and still be able to run the application in the language needed. When a VCL application starts, VCL looks for available resource DLLs from the same directory where the application file is located. If VCL can find a matching file, it uses resources of the resource DLL instead of the original application file. For example, if your application is Project1.exe
, it can have German and French resource DLLs: Project1.de
and Project1.fr
. If you start the application on German Windows VCL will use resource data of Project1.de
instead of resource data of Project1.exe
.
Soluling extends VCL's resource DLLs by providing applications to perform runtime language change. This makes it possible to start the application in one language and later change the language on run time as many times as needed. Soluling's runtime language change is very fast and flicker-free. It does not require you to add any components to the forms. You only have to use Soluling to create resource DLLs and include one or two Soluling units to your project.
Soluling can either created localized files or localized resource DLLs for your Delphi application or library. By default, it creates localized files. You need to change the output format. Right-click the source name on the project tree to open the source dialog and select the Output sheet. In Output files group check Language checkbox.
By default, the localized resource DLLs contain all the same resources as the original application or library, even if the resources have not been localized. You can make your resource DLL files smaller by unchecking Include all resources in output file checkbox. This makes Soluling to add only those resource items that have been localized.
When you use the project localization, the output file is always NtLangRes.ntres
. It is a file that contains localized forms, strings, and images. In order to use it you need to add the file as a custom RT_RCDATA resource. Read how to do this.
Soluling contains functions that let you change the language of a VCL application on run time. <data-directory>\Library\Delphi
contains the Delphi units. NtLocalization.pas
, NtTranslator.pas
, and NtLanguageDlg.pas
are the main units. NtLocalization.pas
contains the functions for accessing resource data, NtTranslator.pas
contains a class that translates forms, and NtLanguageDlg.pas
contains a dialog that shows possible resource DLL language. Users can select the one he or she likes to switch on. Use TNtLanguageDialog.Select
in NtLanguageDlg.pas
to show a language dialog and switch on a new language. The functions show a dialog where the user can select the language, and after selection, it turns on the new language by loading the new resource DLL and reloading existing forms. The functions work with any Delphi 5 and later. In addition, there are several Nt*Translator.pas
units that extend TNtTranslator
, providing translations of complex and binary properties of certain components.
Adding runtime language change is very easy. At a minimum, it only requires that you make Soluling to create resource DLLs instead of localized files, and you add two lines of code into your application (shown in bold typeface).
implementation uses NtLanguageDlg; procedure TForm1.Language1Click(Sender: TObject); begin TNtLanguageDialog.Select('en'); end;
The first parameter (optional, default is 'en') in the Select function specifies the original language of the application. The original language is the language that you used in the forms and menu when you wrote the application. When you run the application and choose File | Language menu, the following dialog will be shown (assuming you have Project1.de
, Project1.fi
, and Project1.ja
resource DLLs).
Select a new language and press, OK. It is simple like that! If you want to use your own user interface to show available languages and way to choose a new one you can use the functions in NtBase.pas
to get list of available languages and finally set a new language active.
Form translation requires little bit more explanation. TNtLanguage.Select
calls TNtTranslator.SetNew
function that performs the resource loading. It loads the resource DLL of the selected language (e.g. Project1.de
). After loading new resources it translates all existing forms. It is very important to understand what happens here. Soluling reads the form data from localized resource DLL and assigns all properties of every component on every form. This means that after the process all components and properties of all forms have the values that the localized resource DLL contains. If you application contains any dynamic property (e.g. value set on run time) you have to update them after language change. If you used OnCreate
to initialize the dynamic properties call the event again. Note that now the resourcestring values contain value in different language so you can use them in the same way as in your original code. Let's have an example.
<data-dir>\Samples\Delphi\VCL/LangaugeSwitch
contains a simple application using resource DLLs. FormShow event calls UpdateItems that initializes the dynamic property values.
procedure TForm1.FormShow(Sender: TObject); begin UpdateItems; end; procedure TForm1.UpdateItems; resourcestring SSample = 'This is another sample'; begin Label2.Caption := SSample; end;
When the application has been started, the form no longer is in the design time state. The design time state is the state that exists in the DFM file (e.g., form data). The caption of the label has been changed on run time. When a language change occurs, Soluling automatically updates the static properties (e.g., those that exist on the form data) but does not change dynamic properties. This is why you have to set them again.
The following code changes the language and translates dynamic properties.
procedure TForm1.Button1Click(Sender: TObject); begin if TNtLanguageDialog.Select then UpdateItems(); end;
TNtLanguageDialog.Select
changes the language and UpdateItems
resets the dynamic properties using the new language. This might seem a bit complicated, but in most cases, your language change routine is on the main menu or the main form. In a situation like that, you only have one form existing at that moment, so you only have to take care of resetting the dynamic properties of that form. All forms that you create after language change will automatically use the new language.
If you have lots of code that calculate the location and size of the component on runtime, it might be difficult to redo those actions after language change. In a case like that, it might be easier to disable translation of all other property types but strings. Read more about that in the Fine tuning runtime language change chapter below.
A final note. Delphi IDE will add form creation code in the initialization section of the application for each form that you add to the project. You better keep only the main form there and create all other forms yourself at the moment when they are first needed.
program Project1; ... begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end.
<data-dir>\Library\Delphi
contains the full source code of all Soluling functions, and <data-dir>\Samples\Delphi
contains several sample applications showing how to make localized and multilingual Delphi applications.
The advantage of the resource DLL localization is that you can set the initial language and even change the language on runtime. The disadvantage is you now have several files to deploy: application executable and the resource DLLs. It is not like a standard Delphi application where you can compile everything as a single EXE file. Fortunately, Soluling has a solution for this. It is to embed the resource DLLs as a custom resource inside your application EXE. When the application is started for the first time, the Soluling code in the application extracts the resource DLLs from the resource into files into the same folder where your application exists.
<data-dir>\Samples\Delphi\VCL\SingleFileDeployment
TNtTranslator
can translate all basic properties such as string, integer, color, etc. However, it can not translate binary properties and some complex properties of certain components. To translate also those properties, TNtTranslator
uses extensions. They are add-ons to TNtTranslator
and provide translations of binary and complex properties. There are several module classes, one for each type of component. The following table contains the module components.
Class name | Unit | Description |
---|---|---|
TNtStringsTranslator |
NtTranslator |
Translates properties whose type is TStrings or derived. This extension is automatically included whenever you add either NtTranslator or NtLanguageDlg unit into your application. |
TNtImageTranslator |
NtImageTranslator |
Translates images such as Picture property of TImage control. |
TNtListViewTranslator |
NtListViewTranslator |
Translates list items of TListView control and derived. |
TNtTreeViewTranslator |
NtTreeViewTranslator |
Translates tree nodes of TTreeView control and derived. |
TShortcutItemsTranslator |
NtShortcutItemsTranslator |
Translates the shortcut items of DevExpress's TdxShortcutList control and derived. |
TVirtulTreeTranslator |
NtVirtualTreeTranslator |
Translates the columns of TVirtualTree control and derived. |
To take module in use, just add its unit to the uses clause somewhere in the application. The following piece of code implements runtime language switch and adds a module for TTreeView
component.
implementation uses NtLanguageDlg, NtTreeViewTranslator; procedure TForm1.Button1Click(Sender: TObject); begin TNtLanguageDialog.Select; end; end.
<data-dir>\Samples\Delphi\LanguageSwitch
shows how to use translator extensions.
You can easily implement your extension if needed for your components or 3rd party components that you use. See the source code of Soluling's extensions to learn how to write them. If you create your module, you have to register it. Call NtExtensions.Register
function in NtTranslator.pas
. A good place for that is the initialization part of your extension unit.
type TMyTranslator = class(TNtTranslatorExtension) ... initialization NtTranslatorExtensions.Register(TMyTranslator); end.
There are several ways you can control what forms, components, and properties are translated.
This is the easiest way to control what to translate because it is done on the Soluling application and not Soluling VCL units. In most cases, you can exclude resource types and/or any data types from your project. In that case, Soluling does not localize those resources or data types when creating localized resource DLLs.
NtTranslator.pas unit contains NtEnabledProperties variable.
var NtEnabledProperties: TTypeKinds;
It stores types that TNtTranslator
should translate. By default, it is an empty set that means that every property is translated no matter its type. Because this includes Left
, Top
, Width
, Height
, and Picture
properties, it might be that during the runtime language change, you will see some flickering. In such a case, you can enable only string types. A good place for that is the initialization part of the main unit.
initialization NtEnabledProperties := [tkString, tkLString, tkWString]; end.
In addition to giving you a flicker-free language change, it speeds up translation time. However, if you disable translation of integer properties, TNtTranslator
does not update Left
, Top
, Width
, and Height
properties. This will disable any layout change done by your translator (e.g., in the case where translation did not fit original space).
NtTranslator unit contains the following events.
var NtBeforeTranslate: TNtBeforeTranslateEvent; NtAfterTranslate: TNtAfterTranslateEvent;
TNtTranslator
calls NtBeforeTranslate
event every time before assigning a value to a property. The event contains a cancel parameter. It the event set this to True TNtTranslator
does not set the property value but remains as it was. The following lines contain a sample event that disables translations of the Label2
component.
procedure BeforeTranslate( host: TComponent; obj: TObject; propertyInfo: PPropInfo; const currentValue: Variant; var newValue: Variant; var cancel: Boolean); begin cancel := obj = Form1.Label2; end;
If you want to modify the value to be set, change the value in the newValue
parameter. If you want to disable translation of the property, set cancel to True. You register the event my assigning it to the global NtBeforeTranslate
variable. A good place for that is the initialization part of the main unit.
initialization NtBeforeTranslate := BeforeTranslate; end.
TNtTranslator
calls NtAfterTranslate
event every time after it has assigned a value to a property. Because these events are called before and after every property, the events are called several even thousands of items. This is why it is important to keep the event functions as fast as possible to prevent runtime language change to slow down too much. Of course, if you do not use events at all (e.g., do not assign the event variables), there is no speed penalty.
Whenever you get data from a database, you will have a field object (TField or inherited). It contains FieldName property that specifies the DB field where the data is got from, and DisplayLabel property that is used, for example, in the grid’s column header. Unfortunately, Delphi makes an optimization here. If the DisplayLabel property value is the same as FieldName property, Delphi does not save DisplayLabel value to the form data. If it is not there, Soluling can not localize it. So you have two options.
"Name"
as the FieldName but "Name "
as the DisplayLabel. Now the properties differ, and Delphi will save them both."NAME"
as the FieldName but "Name "
as the DisplayLabel. GitHub and <data-dir>\Samples\Delphi\VCL\Sport
contains a multilingual database sample that shows how to localize database field captions.
<data-dir>\Samples\Delphi\VCL\Menu
contains a sample that shows how to perform runtime language switch of short-cut text of menu items.
VCL's common dialogs and message boxes are not real Delphi components but wrap around the common dialogs and message boxes of the operating system itself. This is why they can not be localized, but they always appear in the same language as the operating system itself.
<data-dir>\Library\Delphi
contains Vcl.chm and Fmx.chm API documentation file.
Standard Delphi code uses a Format function to create composite format strings. It is not plural, gender, or select enabled, but fortunately, Soluling contains a multi-pattern enabled Format function for Delphi. The function support plural, gender, and select patterns.
If you use standard Format function, you might have something like this
str := Format('%d files', [fileCount]);
Replace '%d files'
with '{plural, {one {%d file} other {%d files}}'
and make that string a resource string and give it SMessagePlural name. Replace Format with Soluling's TMultiPattern.Format function. The modified code is
resourcestring SMessagePlural = '{plural, {one {%d file} other {%d files}}'; //loc 0: Amount of files ... str := TMultiPattern.Format(SMessagePlural, fileCount, [fileCount]);
TMultiPattern.Format function is found in <data-dir>\Library\Delphi\NtPattern.pas
.
See following samples:
Technology | Sample directory |
---|---|
VCL | <data-dir>\Samples\Delphi\VCL\Patterns |
FireMonkey | <data-dir>\Samples\Delphi\FMX\Patterns |
Both VCL and FireMonkey contain file dialogs that you can use to select a file to be opened and specify the file to be saved. The dialog contains Filter property that specifies file typed shown in the file type combo box.
dialog := TOpenDialog.Create(nil); dialog.Filter := 'All supported files (*.xml;*.ini)|*.xml;*.ini|XML files (*.xml)|*.xml|Ini files (*.ini)|*.ini';
The format of the string is quite complicated. It contains the description text separator with file mask(s). There can be several of these pairs. If you place the above string into a string resource, the translator will see it as it is
All supported files (*.xml;*.ini)|*.xml;*.ini|XML files (*.xml)|*.xml|Ini files (*.ini)|*.ini
It may be that the translator will miss one | character or enter one extra. Either one is fatal, and your application will crash if the invalid localized file string is used. This is why it is better to use Soluling's file dialog filter format class.
dialog := TOpenDialog.Create(nil); filter := TNtDialogFilter.Create; filter.Supported('All supported files'); filter.Add('XML files', 'xml'); filter.Add('Ini files', 'ini'); dialog.Filter := filter.Value; filter.Free;
This will expose translator three plain strings: "All supported files," "XML files," and "Ini files." They are easy to translate, and a translator cannot enter invalid values. If you don't want to use or cannot use the file dialog filter format class, use the file dialog filter validation to check if any of the filter translations are invalid.
Soluling.DialogFilter class is found from <data-dir>\Library\Delphi\NtDialog.pas
. See following samples:
Technology | Sample directory |
---|---|
VCL | <data-dir>\Samples\Delphi\VCL\FileDialog |
FireMonkey | <data-dir>\Samples\Delphi\FMX\FileDialog |
Delphi resource string file (.drc
) is used to get unique and immutable context values for resource strings. When the Delphi compiler compiles a resource string, it stores the string value as a standard Windows string resource and assigns an id for the resource string. If you add new resourcestrings into the application, modify exiting, or delete strings, the compiler will assign most resource strings new ids. This can cause loss of translations or even replacing existing translations with other translations. To prevent this, specify a DRC file name so Soluling can use it to assign immutable ids for resource strings. The resource string id will change only if the programmer intentionally changes the resource string variable name. The file extension of DRC files use is .drc (e.g. C:\Samples\Release\Win32\Project1.drc
).
You can localize a Delphi binary file without specifying a DRC file, but it is not recommended. Including the DRC context method, there are two other methods:
Context method | Description |
---|---|
Use DRC file | Soluling uses the DRC file to get unique and immutable resource strings context values. This option is effective only if a DRC file has been specified. If not, resource ids are used. This is the recommended method. |
String value | Soluling uses string values as context values. This is safe, even if you modify and recompile your application. However, if the application has the same text in two or more resource strings, this method brings only one row to the project file. So all instances of the same text will share the same row, and you can no longer translate them differently. |
Resource id | Soluling uses resource ids as context values. This is potentially dangerous because the Delphi compiler may change the resource strings ids next time you compile your project. Even Soluling makes everything to resynch changed ids correctly; this may cause to loss of existing translations, or even mixing two existing translations. Both errors are very hard to locate and fix. |
Because both alternative context methods have their limitations and dangers, it is very much recommended to specify a DRC file. To create a DRC file, start Delphi, choose Project | Options | Linking, and check Output resource string .drc file checkbox. If you use Delphi XE or older, select Detailed in the Map file selection.
If you use platform files, you must use DRC files.
For example, let's look at Sample.pas that has the following resource string.
resourcestring SHello = 'Hello World';
The following table shows how the context is generated in each context method.
Context method | Context | String |
---|---|---|
Use DRC file | Sample.SHello |
Hello World |
String value | Hello World |
Hello World |
Resource id | 4095.65512 |
Hello World |
As you can see, the resource id context id does not give any meaningful information (4095.65512) for the translator. The string value method also does not give any additional information compared to the string value ("Hello World" vs. "Hello World"). Using the DRC file method gives some extra information (Sample.SHello) in addition to the string value.
We recommend you do not use filenames that are the same expect one is having and underline and another is having a period, because they both map exactly the same in the DRC file.
File name | Resourcestring identifier | DRC data |
---|---|---|
Sample_Test.pas | SValue | Sample_Test_SValue |
Sample.Test.pas | SValue | Sample_Test_SValue |
Delphi has a very easy-to-use resource string mechanism. However, it does not let you enter any comments for the string. Most often, translators would need an extra comment to translate the string properly. Soluling has a solution for this. You can add comments into your source code inside a comment next to the resource string.
When Soluling scans your Delphi application is first reads the resource items from the compiled file (.exe
or .dll
) and then resource string comments you have added from the source code files (.pas
).
The following sample shows how to add a comment.
resourcestring SHello = 'Hello World'; // loc This is a comment
The above lines of code specify, "This is a comment" comment for SHello resource string.
The following sample shows how to add a comment with multiple lines. Use \n to mark a new line.
resourcestring SHello = 'Hello %s'; // loc Hello text \n %s: name of the user
The following line has a resource string tag that contains a comment ("Clicking this button closes the form") and sets the maximum length to 200 pixels:
resourcestring
SMsg = 'Click to close the form'; //slz MaxPixels=100 Clicking this button closes the form
Using resource string comments is optional. If you use them, you have to make sure your Delphi source has the Delphi project file specifies, and you have turned on source code scanning. Use the Project file sheet to do this.
The following sample shows how to add a comment.
str = _T('Hello World'); // loc This is a comment
The above lines of code specify "This is a comment" comment for the "Hello World" string.
Unlike with binary localization, you don't have to turn on comment scanning. It is always on.
See <data-dir>\Samples\Delphi\VCL\Comments
sample to see how to use comments.
Soluling uses scan rules to specify what components and properties are localized and how they are localized. Form resources are the most important resource type of Delphi applications. You use the Delphi IDE to create and edit forms. Each form is stored in a standalone form file (.dfm
or .fmx
). By default, a form file is a text file that contains the components and their properties in a structural format. Here a sample form, Unit1.dfm
, that contains a label, a button, and a query. Let's look a form in Delphi's form designer.
If you open Unit1.dfm
on a text editor, you will see that it contains several property values, one value on each line.
object Form1: TForm1 Left = 0 Top = 0 Caption = 'Form' ClientHeight = 172 ClientWidth = 328 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object Label1: TLabel Left = 8 Top = 8 Width = 74 Height = 13 Caption = 'This is a sample' end object Button1: TButton Left = 136 Top = 80 Width = 75 Height = 25 Caption = '&Get' TabOrder = 0 end object ADOQuery1: TADOQuery
Parameters = <>
SQL.Strings = (
'SELECT * FROM Values')
Left = 104
Top = 64
end
end
When Delphi compiles an application, it adds each form as a resource inside the application. The following picture shows the resources of a typical Delphi application.
Form resources are stored in the RC Data resource type. Each resource has the same name as the form itself but in capital letters. So TForm1 (Unit1.dfm
) becomes TFORM1. The resource data is not the same as in the DFM file but the more compact binary format. If you view the form resource data in a binary editor, you will see the following bytes.
You can see that it contains the same properties as Unit1.dfm but in a binary format. Compared to the textual DFM file, the form resource takes less space and is faster to process. Soluling reads and writes this binary form resource.
The original form file, Unit1.dfm
, contains all the properties of the form. However, most of them are not needed to be translated. In most cases, you only want to translate most of the strings and a few other properties. For example, in some cases, you also want to change the width, height, or position of the form. In that case, you could "translate," for example, ClientWidth
or ClientHeight
properties. Soluling uses scan rules to control what property is localized and what not.
The rules work such a way that by default, all string typed properties are localized, and all other properties are not localized. This method picks up the following string properties.
Property | Value |
---|---|
Caption | Form |
Font.Name | Tahoma |
Label1.Caption | This is a sample |
Button1.Caption | &Get |
ADOQuery1.SQL.Strings | SELECT * FROM Values |
All three Caption
properties should be translated. However, Font.Name
should not unless on very few circumstances. SQL statement should not be localized. To make this possible, Delphi's scan property rules can contain exception rules. They specify those string type properties that are not localized (remember by default all string typed properties are localized). By default, the rules contain exceptions for all those VCL properties that should not be localized. For example.
Component name | Property name |
---|---|
* | *Font.Name |
TADOQuery | SQL.Strings |
The first rule excludes from all components all property names that end with Font.Name
. The second rule excludes SQL.Strings
property of TADOQuery.
Note! The component name is the component type name. For example, VCL's label control's type name is TLabel. The property name, however, is the name that is used in the DFM file. Sometimes this differs from the name used in Object Inspector. For example, the property to store TADOQuery's SQL has just SQL name in Object Inspector but SQL.Strings in DFM. You must use the later (SQL.Strings).
To localize images, fonts or colors you have to either add a rule for each property or turn localization of each type on. Right-click the source in the project tree and choose Options. Select the Data types sheet. It contains three radio buttons for each data type. Check the Yes radio button for data types you want to localize and click OK. Next time you scan, the new resource types are scanned.
Note! Turning a data type localization on will localize all properties having that data type unless there is an exclude rule of that property. Use scan rules to turn on the localization of a specific property.
See following sample: <data-dir>\Samples\Delphi\VCL\Image
These properties are scanned, but by default, they are not visible in the translation grid. You can turn them visible by checking the Coordinate data type in the grid filter. You can also use the visual editor to change the size and position properties.
Some components use a custom binary format to store property data. This is not recommended, but because the feature is there, some components still use it. The drawback of custom binary property is that it can contain data in any format. Unlike the standard DFM format, custom binary properties do not contain data in a standard format. Each component uses its property format. The format can only be localized if Soluling knows the format and contains a dedicated parser for that format. We have implemented a dedicated parser for most common binary properties, such as items of TTreeView
and TListView
. The full list of formats is shown here.
You can see what property uses a binary format by viewing the DFM file. A binary property contains hexadecimal data inside { and } characters. The following sample form contains a TTreeView
component with Items.NodeData
property that uses a custom binary format.
object TreeView1: TTreeView
Left = 8
Top = 24
Width = 193
Height = 129
Indent = 19
TabOrder = 0
Items.NodeData = {
0303000000240000000000000000000000FFFFFFFFFFFFFFFF00000000000000
000100000001034F006E006500240000000000000000000000FFFFFFFFFFFFFF
FF00000000000000000000000001034F006E0065002400000000000000000000
00FFFFFFFFFFFFFFFF0000000000000000000000000103540077006F00280000
000000000000000000FFFFFFFFFFFFFFFF000000000000000000000000010554
006800720065006500}
end
If you have a component that uses a proprietary binary property format that is not one in this list, you have two choices. The first one is not to set the property on design time but set it on run time using string values from resource strings. This works with any component. Another is to ask us to implement a binary parser for the property. If the component is popular and we can easily get the full source code of the component, it is more likely that we will implement a parser for the component.
It is very rare that you need to localize another kinds of properties than shown above. If you do, Soluling can handle it. Other property types such as enumerations and numbers are not localized unless you add them to the scan rules.
The default scan rules contain exclude-rules for all standard VCL components and the following 3rd party component:
If you use some other 3rd party components, you may need to add some exclude-rules, and if the component uses binary properties, you need to add some localize-rules.
3rd party components are just like the standard Delphi components shipped with Delphi. All components are ultimately inherited from TComponent
, and they contain published properties that are stored in the form file of the owner form. Soluling has been designed to localize any kind of forms and data modules. Applications use the scan rules to select what properties to scan. Even the built-in scanning mechanism can properly parse all form data, some 3rd party components might have some issues.
The first potential issue is that the component does not write the property data into a form resource file. If it is not in the form resource file, Soluling can not localize it. If a property value does not appear in your project, even you have a proper scan rule, check that your form resource file contains the value. Then check that the scanning rules include the property and do not exclude it.
Another potential issue is that the property is correctly written, but it does not use the standard data type but uses a proprietary binary format. Soluling can correctly read many binary format but if the format is unknown to Soluling, it can not parse it but ignorers the property. You have two choices here. The first one is to contact us and provide a sample that we can use. If the component is widely used and we can have full source code of the component (e.g., the component vendor has sent it to us), we can implement a parser for that specific format. Another solution is not to set the property value on design time but runtime. That way, you can store data into standard string resources and use that data to set the proprietary property. Soluling can localize the standard string resources.
Some 3rd party components have issues with certain locales. They might work correctly when the locale is English but may fail in Japanese. So we want to test all major 3rd party components. The following list contains the 3rd party component libraries we have tested and found localizable.
Component library | Notes |
---|---|
DevExpress VCL Components | |
InfoPower | |
Konopka Signature VCL/Raize controls | You can get Konopka Signature VCL control from GetIt Package Manager |
QuickReport | |
TeeChart | |
TMS VCL UI Pack |
Even if the above list does not contain the component library, you can still use Soluling to localize your application. If your component library is not on the above list, please contact the library vendor and ask them to join our 3rd party component program.
The visual form editor for Delphi forms is a full editor that has two purposes. First, it gives you the visual context of the strings. Secondly, it can be used to move and resize the controls on the form.
If you want to move or resize a control, use the mouse to select it. Then use either the mouse or keyboard to move or resize the selected item. If you use the mouse, drag the component to move it. To resize, drag one of its trackers. To move using the keyboard, press the Ctrl+arrow key. To resize, press the Shift+arrow key.
Even Soluling does not have an editor for FireMonkey, Soluling can localize all FireMonkey applications.
Soluling's VCL form editor uses the native VCL components to show forms. Soluling.exe does not contain the code for al 3rd party components. Soluling contains code for standard VCL controls, Raize/Konopka signature, JAM Shell Controls, and TMS VCL UI Pack. This means that the editor uses those controls when needed but tries to emulate other 3rd party components using the mappings rules. If there is no rule for a specific component and the mapping cannot be automatically detected from the component class name, the editor shows a yellow box at the place of the component.
The editor shows all the standard VCL, Raize/Konpka Signature, and TMS UI Pack controls visually in the same way they would appear in the application when running it. However, if you use other 3rd party controls or your own controls, the editor tries to map them to the nearest VCL controls. You can also map them manually. If not mapped, the editor shows only the type of control and the position and size of the control. For example, the following form contains a standard TLabel that is shown normally and a custom TMyLabel that is shown as a yellow box.
This lets you move and resize all 3rd party controls even the editor does not fully render them.
One of the most powerful features of Delphi is visual form inheritance. It lets you apply OOP to the user interfaces. Unfortunately, the DFM file format does not have information about the ancestor form. Soluling tries to find the ancestor by analyzing your EXE/DLL/BPL file. However, if it cannot detect the ancestor, you will see the inherited form like this.
Soluling can also get the ancestor forms by scanning your source code. To turn this on by checking Scan source code to find resource string comments and parent form class check box in the Source code scanning sheet.
Note! Soluling reads the .dpr file so make sure you have added all your forms and frames to the .dpr file.
If you don't want to turn on the source code scanning and you want the editor to show the content right, you have to select the ancestor form manually. Click on the right mouse the form node in the project tree and choose Select Ancestor. Then choose the ancestor of the list. If the ancestor of your form in a Delphi package file (.bpl), then you have to first add the package file to your Soluling project.
The above Soluling project contains two sources: PackageFormApplication.exe
and FormsPackage.bpl
. The package contains the base form, TBaseForm
. The application contains a form, TDerivedForm
, that inherits from the TBaseForm
.
By default Soluling's form editor removes the data properties from the forms it loads. This is done because the translator's computer most likely does not have the database and its libraries installed. If you have the database and the necessary libraries, you can turn off the data property removing from VCL settings (Options | Platforms | VCL | VCL).
Depending on your target operating system Delphi compiler creates different application files. The following table contains the file formats used by all supported operating systems:
Operating system | Application and library file format | Application file extension | Library file extension | Notes |
---|---|---|---|---|
Windows 32-bit | 32-bit PE file | .exe | .dll | |
Windows 64-bit | 64-bit PE file | .exe | .dll |
Even the application file formats differ from each other, the resource data inside all files is the same. All files contain a form, string, image, etc. resources. When scanning, Soluling reads the resource data and when building Soluling writes the resource data.
In addition to multiple platforms, a Delphi project can also contain multiple configurations. There are used to specify different compiler options (e.g., Debug and Release). If you have both multiple platforms and configurations, the total number of output files is the product of platform count and configuration count. For example, if you have Debug and Release configuration and Win32 and Win64 platforms, you end up to four output files.
Each output file has an individual DRC file (.drc). When you add a platform file into a source, Soluling will automatically detect the location of the DRC file. If that fails, you have to enter the DRC file manually. You can not localize a Delphi application having more than one output file without using DRC files.
Most reporting components for Delphi use forms or data modules to configure reports. This makes them compatible with forms, and Soluling's from parser scans and localizes them just like any other form or data module. ReportBuilder also uses external file format .rtm that uses the same format as .dfm. If you want to localize external reports file, just add each .rtm file into your project.
Most cases, translations are longer than original strings. That may cause some controls in your forms to overlap and some text in the controls to truncate. It may be difficult to manually detect these, especially because some control may be created and/or moved on runtime. Therefore Soluling offers two methods to detect the layout problems.
Soluling's validations contain three validations to check the layout. They are:
Another method is to use temporal checker code in your application. Use the TLayoutChecker class to check your forms once you run your application automatically. The checker writes check results with screenshots that contain problem areas highlighted in the Checker subdirectory.
All you have to do is to call the LayoutChecker.Check
function for all your forms. A good place to call it is the OnActivate
event.
procedure TForm1.FormActivate(Sender: TObject); begin NtLayoutChecker.Check(Self); end;
LayoutChecker object is found from <data-dir>\Library\Delphi\NtChecker.pas
. You need to use Delphi XE2 or later to use TLayoutChecker
. If your application uses a localized resource DLL, then the output is written into a language-specific subdirectory of TLayoutChecker.OuputDir
. For example, if your application is C:\Files\Sample\Win32\Debug\Project1.exe
, then the default output directory is C:\Files\Sample\Win32\Debug\Checker
and the German output directory is C:\Files\Sample\Win32\Debug\Checker\de
.
See following samples:
Technology | Sample directory |
---|---|
VCL | <data-dir>\Samples\Delphi\VCL\Checker |
FireMonkey | <data-dir>\Samples\Delphi\FMX\Checker |
By default, Soluling sets the Font.Charset
property of the localized forms to match the character set of the target language. We need this for some control to render the text correctly. However, sometimes this might have strange side effects such as Anchor property having no effect. If this happens, turn the Font.Charset
updating off.
Soluling contains a rich internationalization API for Delphi. It contains classes for runtime language switch, layout checking, and for many other cases that help you write better-internationalized code. The full source code of API is found from <data-dir>\Library\Delphi
directory or on GitHub. API documentation is found from <data-dir>\Library\Delphi\VCL.chm
.
Soluling supports VCL applications made in C++Builder. The localization process is identical to Delphi.
You can use Delphi's resourcestring with C++Builder. First add a Delphi unit to your C++Builder project and write the resourcestrings into that unit. For example, Strings.pas
.
resourcestring SMessage = 'This is a sample'; //loc Some comment
Compile the project. C++Builder compiler creates a matching .hpp file (e.g, Strings.hpp
). Include that file into the C++ unit that uses the resource string. Use the resource string.
Label2->Caption = System::LoadResourceString(&Strings::_SMessage);
Finally, turn on the .drc file creation by adding -GD linker option.
Of course, you can use the standard C++ string table resource strings but using the above method is generally easier and makes it possible to add comments to the resource strings.
If you want to use Soluling's I18N functions (<data-dir>\Library\Delphi\Nt*.pas
) in C++Builder follow these instructions:
<data-dir>\Library\Delphi\NtVcl.dpk
. Remember to compile both 32-bit and 64-bit targets. This will create NtVcl.a
, NtVcl.bpi
, NtVcl.dcp
and NtVcl.bpl
files.<data-dir>\Samples\CBuilder\Driving\Localized
and <data-dir>\Samples\CBuilder\Driving\Multilingual
samples.<data-dir>\Samples\Delphi
contains Delphi samples in two directories: VCL and FMX.
<data-dir>\Samples\CBuilder\VCL
contains C++Builder samples.
GitHub and <data-dir>\Samples\Delphi\VCL contains following Delphi VCL samples:
Directory | Description | Notes | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Driving | Shows how to localize a Delphi application.
|
Try this first! |
||||||||||||||
ActiveLanguage | Shows how to use TNtLanguageDialog and runtime language switch. | Runtime language switch | ||||||||||||||
Audio | Shows how to use localized sound and audio resources. | |||||||||||||||
Checker | Shows how to add layout checker into your applications. | |||||||||||||||
Comments | Shows how to add resource comments. | |||||||||||||||
CustomDir | Shows how to use resource DLLs that do not locate on the same directory as the application file. | |||||||||||||||
CustomSelect | Shows how to build your own user interface to show available languages and to select a new language. | Runtime language switch | ||||||||||||||
DualLanguage | Shows how to implement an application where some part of the user interface uses different language than the rest. | Runtime language switch | ||||||||||||||
FileDialog | Shows how to internationalize filter of file dialog in a smarter way. | |||||||||||||||
Font | Shows how to localize fonts. | |||||||||||||||
Forms | Shows how to virutal form inheritance to make localization easier. | Runtime language switch | ||||||||||||||
Format | Shows how to localize composite format strings that use Format function. | Runtime language switch | ||||||||||||||
IgnoreResourceDll | Shows how to disable resource DLLs. | |||||||||||||||
Image | Shows how to localize images. | |||||||||||||||
ImageList | Shows how to localize images in the image list. | |||||||||||||||
IME | Shows how to use input method editors. | |||||||||||||||
Japanese | Shows how to do if the original language is Japanese instead of English. | Runtime language switch | ||||||||||||||
LanguageParam | Shows how to set initial language using a command line parameter. | Runtime language switch | ||||||||||||||
LanguageSwitch | Shows how to perform runtime language switch on an application using images, tree views, and list views. | Runtime language switch | ||||||||||||||
Layout | Shows how to use layout containers. | |||||||||||||||
Menu | Shows how to perform runtime language switch on application using menu shortcuts. | |||||||||||||||
MessageDlg | Shows how to localize message dialogs. | |||||||||||||||
Multi | Shows how to localize a RAD Studio project group. | |||||||||||||||
Original | Shows how to use a custom original language. | Runtime language switch | ||||||||||||||
Package | Shows how to localize packages, either your custom ones or VCL's standard packages such as vclXXX.bpl . |
|||||||||||||||
Patterns | Shows how to create grammatically correct multi patterns such as plural, gender and select enabled messages. Contains following projects:
|
Runtime language switch | ||||||||||||||
Resize | Shows how to use resize controls in the localized forms. | |||||||||||||||
Resources | Shows how to localize custom XML, JSON, SVG, INI, etc resources. | |||||||||||||||
SingleFileDeploy | Shows how to create a single EXE application that contains resource DLLs inside the EXE in custom resources. | Runtime language switch | ||||||||||||||
Sport | Shows how to localize user interface and data the application uses. Contains following projects:
|
Runtime language switch | ||||||||||||||
StringArray | Shows how to replace resource string arrays when using runtime language switch. | Runtime language switch | ||||||||||||||
Version | Shows how to check that the version number of the application and resource DLLs match. | |||||||||||||||
3rdParty | Shows how to localize and check application using some of the 3rd party controls. Contains following projects:
|
You need to have each 3rd party control installed. Runtime language switch |
All samples are written in Delphi 11.3 Alexandria and tested as 32-bit and 64-bit. If you use a very old Delphi version, you might need to modify the application slightly. Samples contain pre-compiled EXE files. VCL root directory contains the RAD Studio group project file that contains most of the samples. Driving, Multi, Package, Patterns, and Sport directories contain several samples, and this is why they all contain their own group project files.
GitHub and <data-dir>\Samples\Delphi\FMX contains following Delphi FireMonkey samples:
Directory | Description | Notes | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Driving | Shows how to localize a Delphi application.
|
Try this first! | ||||||||||||
ActiveLanguage | Shows how to use TNtLanguageDialog and runtime language switch. | Runtime language switch | ||||||||||||
Comments | Shows how to add resource comments. | |||||||||||||
CustomSelect | Shows how to build your own user interface to show available languages and to select a new language. | Runtime language switch | ||||||||||||
LanguageSwitch | Shows how to perform runtime language switch on an application that contains images, tree views, and list views. | Runtime language switch | ||||||||||||
Patterns | Shows how to create grammatically correct multi patterns such as plural, gender and select enabled messages. Contains following projects:
|
|||||||||||||
TreeView | Shows how to localize tree and list views. |
All samples are written in Delphi 11.3 Alexandria and tested in Windows, macOS, Linux, iOS, and Android. If you use a very old Delphi version, you might need to modify the application slightly. Samples contain pre-compiled EXE files. FMX root directory contains the RAD Studio group project file that contains most of the samples. Driving and Patterns directories contain several samples, and this is why they all contain their own group project files
GitHub and <data-dir>\Samples\CBuilder\VCL contains following C++Builder VCL samples:
Directory | Description | Notes | ||||||
---|---|---|---|---|---|---|---|---|
Driving | Shows how to localize a Delphi application.
|
Try this first! |
||||||
Inherited | Shows how to use visual form inheritance. | |||||||
LanguageSwitch | Shows how to perform runtime language switch on an application using images, tree views, and list views. | Runtime language switch | ||||||
SimpleRC | Shows how to use traditional .rc file based resource strings. | |||||||
Simple | Shows how to use .pas file based string resources. This is much easier than the .rc file method. |
All samples are written in Delphi 11.3 Alexandria and tested in Windows. If you use a very old C++Builder version, you might need to modify the application slightly. Samples do not contain pre-compiled EXE files. You need to first compile the samples. VCL root directory contains the RAD Studio group project file that contains most of the samples. Driving directory contains several samples, and this is why it contains its own group project files.
Soluling can localize Delphi application and library files (.exe
, .dll
, .bpl
) when using the binary localization, Delphi projects (.dproj
) when using the project localization, Delphi project group files (.groupproj
), and Delphi form files (.dfm
or .fmx
). Read the process paragraph to figure out what is the right method for you.
You can configure how to localize your Delphi application or library by selecting the item in the project tree, right-clicking, and choosing the Options menu. A source dialog appears that lets you edit the options. This source uses the following option sheets.
Note! When you add a Delphi created EXE, DLL or BPL file into your project, Soluling will use the binary localization.
You can configure how to localize your Delphi project file by selecting the item in the project tree, right-clicking, and choosing the Options menu. A source dialog appears that lets you edit the options. This source uses the following option sheets.
Note! When you add a Delphi project file into your project, Soluling will use the project localization.
You can configure how to localize your Delphi project group file by selecting the item in the project tree, right-clicking, and choosing the Options menu. A source dialog appears that lets you edit the options. This source uses the following option sheets.
When you add a Delphi project file into your project Soluling will automatically add a sub-node that is a Delphi application or library file source, and initializes the source using properties of the selected Delphi project file.
You can configure how to localize your Delphi form file by selecting the item in the project tree, right-clicking, and choosing the Options menu. A source dialog appears that lets you edit the options. This source uses the following option sheets.
Note! Use form localization only if you need to create localized form files. If you want to localize a Delphi application, select a binary file or project file.