Q: How to translate TDBGrid columns captions?
Q: How to translate strings declared in RESOURCESTRING section?
Q: Why some of my string constants don’t appear in found strings form when translating sources?
Q: How to translate InfoPower’s DBGrid component?
Q: How to skip some source hard-coded strings from translation?
Q: How I can have internationalized dialog boxes?
Q: Why do I get garbage when I switch the language to Japanese (Chinese)?
Q: I am using C++Builder. How do I translate string tables coded in .rc and .rh files?
Q: How to translate captions in TActionMainMenuBar and TActionToolBar?
Q: How to translate arrays of strings?
Q: How to modify button widths in standard dialogs?
Q: Are TsiLang components compatible with IntraWeb?
Q: Is it possible to translate menu shortcuts?
Q: How to translate forms used inside 3rd party components?
Q: Why TDBNavigator hints are not translated at start-up?
Q: Why Developer Express components translations are displayed incorrect under XP Themes enabled?
Q: How to detect OS default lanaguge and switch to it?
Q: How to properly load translations from file at run-time?
Q: Main menu gets white background after language switching
Q: “Unit siComp was compiled with a different version of System.RTLVersion”
Q: After upgrading to version 6.3 and later, escape sequences are not processed under C++.
Q: Can’t build project for iOS target platform.
Q: Can’t build any FireMonkey project with TsiLang components.
Q: Registered version setup crashes on Windows Server platform.
Q: How to make TsiLang message boxes “styled” when VCL Style applied.
Q: How to translate TDBGrid columns captions?
A: For translating database grids just add all fields to the respective data-set and use TsiLang “DisplayLabels” property to translate display label for each field. In grid “Columns” property do not set “Title” sub-property it will be overwritten by field’s “DisplayLabel” property. Or you can translate them using Collections property of TsiLang.
Q: How to translate strings declared in RESOURCESTRING section?
A: Just use the same technique as for CONST section and change keyword RESOURCESTRING to CONST.
Q: Why some of my string constants don’t appear in found strings form when translating sources?
A: The following declaration of string constant:
const
constname = 'stringvariable';
should be changed to:
const
constname = 'stringvariable';
Q: How to translate InfoPower’s DBGrid component?
A: For translating InfoPower’s DBGrid component: use “Multilines” property of TsiLang and translate grid’s “Selected” property. Note: Be careful with this property translation, be sure to keep the format and places of tabulation TAB character.
Q: How to translate nested properties like InfoPower’s wwIntl1.SearchDialog.SearchByHint, Report Builder’s ppReport1.PrinterSetup.DocumnetName?
A: You should use TsiLangs ExtendedTranslations property.
Q: How to skip some source hard-coded strings from translation?
A: In TsiLang Components Suite v4.9.6 there is introduced new source translation tags: {TSI:IGNORE}
, {TSI:IGNORE ON}
and {TSI:IGNORE OFF}
to inform TsiLang Expert that these lines should be skipped for translation.
Q: How I can have internationalized dialog boxes?
A: Just use the respective methods of TsiLang components. All standard dialog box functions like MessageDlg(), ShowMessage(), InputBox() are re-implemented in TsiLang to provide internationalization support.
Q: Why do I get garbage when I switch the language to Japanese (Chinese)?
A: You might need to install Japanese (or any other non-Western) locale support and/or set your system’s default locale to Japanese. To do that go to Control Panel|Regional Options|General tab. Make sure the check box related to your locale is checked, then hit the Set Default button to set the related locale as system’s default. Note that this only works on NT platforms. This applies for OLD OS and IDE versions!
Q: I am using C++Builder. How do I translate string tables coded in .rc and .rh files?
A: We recommend you the following workaround:
1. Declare a new function for loading strings from resources, for ex.:
AnsiString LoadStr2(
int
Ident);
2. Add the body of the functions as follows:
extern
PACKAGE AnsiString
__fastcall
LoadStr2(
int
Ident) { TResStringRec ResRec; ResRec.module = (
long
*) &HInstance; ResRec.ident = Ident;
return
(LoadResString(&ResRec)); }
3. Replace LoadtStr() calls to LoadStr2() calls in all your units.
4. Compile your application.
5. Run TsiLang Resource Strings Import Wizard (available from TsiLang Expert’s Tools|Wizards menu) and import all strings from your executable that need to be translated.
6. All these strings (selected in wizard) will be imported into TsiLang and will be available for translation.
7. Enter the translations for these strings and re-build the project.
Q: How to translate captions in TActionMainMenuBar and TActionToolBar?
A: Usually every TActionClientItem is linked to a corresponding TAction which provides string data for its clients. TsiLang components maintain Action’s string properties such as Caption or Hint, so all visual controls linked to the Action are updated when the active language is changed.
However, those TActionClientItems that are not linked with any action, for example top-level items of TActionMainMenuBar, have no published string properties and cannot be handled directly. For such TActionClientItems we would recommend the following trick:
- For every TActionClientItem without a TAction create a “fake” Action and link them. For example, if your TActionMainMenuBar has a top-level menu item ‘File’, create a new action FileFile1, set its .Caption property to ‘File’, and link them.
- Enter translation data for this Action in the Translation Editor.
- If an action has no event handler it is permanently disabled, so set the OnUpdate event handler of all “fake” actions to a procedure like this:
... procedure TForm1.FakeActionUpdate(Sender: TObject); begin TAction(Sender).Enabled := True; end; ...
Demo project could be downloaded from http://www.sicomponents.com/soft/ActionManager.zip
Q: How to translate arrays of strings?
A: If you are using data structures like the below:
const str1 = 'My String constant 1'; str2 = 'My String constant 2'; str3 = 'My String constant 3'; StrArr: array[0..2] of string = (str1, str2, str3);
You need to replace the StrArr declaration with the following one:
StrArr: array[0..2] of PString = (@str1, @str2, @str3);
Also, all references in code on the array’s elements like
...StrArr[Index]...
must be replaced with the:
...StrArr[Index]^...
Q: How to modify button widths in standard dialogs?
A: Unfortunately, there is no easy way to do this. But may be you can hack this by writing something like this in OnShow
event of for example siFindDialog:
procedure TForm1.siFindDialog1Show(Sender: TObject); var hnd: THandle; R: TRect; begin with siFindDialog1 do begin if (siLang = nil) or (siLang.Language <> 'Dutch') then Exit; GetWindowRect(Handle, R); SetWindowPos(Handle, 0, 0, 0, R.Right - R.Left + 26, R.Bottom - R.Top, SWP_NOMOVE or SWP_NOZORDER); hnd := GetDlgItem(Handle, 1); SetWindowPos(hnd, 0, 0, 0, 100, 23, SWP_NOMOVE or SWP_NOZORDER); hnd := GetDlgItem(Handle, IDCANCEL); SetWindowPos(hnd, 0, 0, 0, 100, 23, SWP_NOMOVE or SWP_NOZORDER); end; end;
Q: Are TsiLang components compatible with IntraWeb?
A: Yes, you can use TsiLang components in IntraWeb applications in the same way as in usual VCL/CLX applications. The demo project could be downloaded from http://www.sicomponents.com/soft/IW_SiLang.zip
Q: Is it possible to translate menu shortcuts?
A: Yes, although it requires some tricks. Find the details at our forum…
Q: How to translate forms used inside 3rd party components?
A: There are two possible cases:
- 3rd party forms use resource strings for visible UI elements:
Just use Resource Strings Import Wizard to import used resource strings into your TsiLang component. In order to be able to control 3rd party forms Font and Charset used to display under each language you can use TScreen.OnActiveFormChange event. For example:
TForm1 =
class
(TForm)
{…}
procedure
FormCreate(Sender: TObject);
private
{ Private declarations }
procedure
OnFormChange(Sender: TObject);
{…}
end
;
{…}
procedure
TForm1.FormCreate(Sender: TObject);
begin
Screen.OnActiveFormChange := OnFormChange;
end
;
procedure
TForm1.OnFormChange(Sender: TObject);
begin
if
(Screen.ActiveForm <>
nil
)
and
(Screen.ActiveForm <> Self)
then
Screen.ActiveForm.Font.Assign(Self.Font);
end
;
- 3rd party forms use hard-coded strings for UI elements:
You will have to place TsiLang on each 3rd party form, add this form to your project and translate it as it would be usual form from your project.
Q: Why TDBNavigator hints are not translated at start-up?
A: There is a small bug (or as designed) in TDBNavigator component. To fix it you may use the following sample code:
procedure
TForm1.FormCreate(Sender: TObject);
begin
DBNavigator1.Hints.CommaText := siLang1.GetStringValue(@siLang1.MultiLines, 'DBNavigator1.Hints', siLang1.ActiveLanguage);
end
;
Q: Why Developer Express components translations are displayed incorrect under XP Theme enabled?
A: When the XP Theme enabled Developer Express components convert AnsiString to WideString using application default locale. You can fix this by changing application’s thread locale on language changing event. For example:
procedure
TForm1.siLang1ChangeLanguage(Sender: TObject);
begin
if
siLang1.ActiveLanguage = 1
then
SetThreadLocale(LANG_ENGLISH)
else
SetThreadLocale(LANG_JAPANESE);
end
;
Q: How to detect OS default language and switch to it?
A: SysLocale global variable could be used in the later versions of Delphi and C++Builder:
procedure
TForm1.FormCreate(Sender: TObject);
begin
if
SysLocale.PriLangID = LANG_ENGLISH
then
siLangDispatcher1.ActiveLanguage := 1
else
if
SysLocale.PriLangID = LANG_GERMAN
then
siLangDispatcher1.ActiveLanguage := 2
else
if
SysLocale.PriLangID = LANG_FRENCH
then
siLangDispatcher1.ActiveLanguage := 3
else
siLangDispatcher1.ActiveLanguage := 1;
end
;
Also you can use WinAPI to detect OS default language:
procedure
TForm1.FormCreate(Sender: TObject);
var
LangID: DWORD;
begin
LangID := GetUserDefaultLangID;
case
Byte(LangID
and
$03FF)
of
LANG_ENGLISH: siLangDispatcher1.ActiveLanguage := 1; LANG_GERMAN: siLangDispatcher1.ActiveLanguage := 2; LANG_FRENCH: siLangDispatcher1.ActiveLanguage := 3;
else
siLangDispatcher1.ActiveLanguage := 1;
end
;
Q: How to properly load translations from file at run-time?
A: In order to load translations from file at run-time and be sure that all forms will load it correctly you must assign FileName property of dispatcher component and call LoadAllFromFile() method:
procedure
TForm1.FormCreate(Sender: TObject);
begin
// Setting FileName property ensures that forms created later // will load this file as well
siLangDispatcher1.FileName := "YourSILorSIBFileName.SIL";
// Calling LoadAllFromFile() ensures that all // already created forms load this file
siLangDispatcher1.LoadAllFromFile(siLangDispatcher1.FileName);
end
;
Also you may consider reading useful article “Creating Multilanguage Applications Translated by Users“.
Q: Main menu gets white background after language switching
A: Sometimes under Windows XP with themes enabled the main menu background becomes white after changing languages. This is known as the XP bug and as workaround could be used as follows:
- Set Images property to nil before switching language
- Switch active language
- Restore the value of Images property
The following Delphi code demonstrates this:
MainMenu1.Images :=
nil
; siLangDispatcher.ActiveLanguage :=
(computed value)
; MainMenu1.Images := ImageList1;
Q: “Unit siComp was compiled with a different version of System.RTLVersion”
A: It looks like you don’t have all update and service packs installed into Delphi 6. Please install all available service and update packs (including RTLUpdate 3) because TsiLang package was compiled with all latest packs installed.
Q: After upgrading to version 6.3 and later, escape sequences are not processed under C++.
A: This was the price to have single packages for Delphi and C++Builder. If you use only C++Builder you can fix this by adding {$DEFINE BCB} at the first line of SI.INC file and re-build TsiLang packages. If you need to use both Delphi and C++Builder or you don’t have Full Source edition, or you don’t want to re-build TsiLang packages then you will need to set siLang_Def_UsedInCpp global variable declared in siComp.hpp to true in your C++ projects right after Application->Initialize(); call.
Q: Can’t build project for iOS target platform.
A: Compiled units (DCU) are provided ONLY for Win32, Win64, Android and OSX32 platforms. iOS DCUs are generated for iOSSimulator target. So if you need to build your projects for other target platforms you will need to re-build your project using sources of TsiLang Components Suite units.
Q: Can’t build any FireMonkey project with TsiLang components.
A: FMX global conditional define is required to build TsiLang units under FireMonkey projects. If you just link pre-compiled TsiLang units to your FireMonkey project this define is not required.

Q: Registered version setup crashes on Windows Server platform.
A: If you get a crash during installing registered version of TsiLang Components Suite on Windows Server platform please turn OFF the Data Execution Prevention (DEP) OS’s setting. DEP is ON by default on Windows Server platforms and this may cause a crash during install.
Q: How to make TsiLang message boxes “styled” when VCL Style applied.
A: When you use VCL Styles to apply styles to your RAD studio applications the message boxes displayed by TsiLang are not styled in case the UseTaskDialog property of TsiLang is set to True. To prevent this you can just set this property to False, but in case you would like to have message boxes based on Task Dialog when no application style is active, you can use the following trick:
- We set the UseTaskDialog property to True by default.
- Upon application active form change (inside the Screen.OnActiveFormChange event) we check if it is styled and then set this property to False.
The following code sample demonstrates this:
procedure TForm1.ScreenFormChange(Sender: TObject); procedure ProcessActiveForm(AForm: TCustomForm); var I: Integer; begin for I := 0 to AForm.ComponentCount - 1 do if AForm.Components[I] is TsiCustomLang then begin TsiCustomLang(AForm.Components[I]).UseTaskMsgDlg := StyleServices(AForm).IsSystemStyle; Exit; end; end; begin if Screen.ActiveCustomForm <> nil then ProcessActiveForm(Screen.ActiveCustomForm); end;