?
Solved

Localisation in Delphi

Posted on 2011-05-03
38
Medium Priority
?
611 Views
Last Modified: 2012-05-11
I have started localizing a Delphi application.
It is developed in a french belgium environment.
I have started translating it in UK english
After compiling the project, I now have the .exe file and also a .eng
I understand that the .eng will be used if my settings are ENG
But can I test it without having each time to change my locale settings ?
Also, inside my program, how can I get the locale settings so that I can adapt some processing as well ?
Thanks
0
Comment
Question by:LeTay
  • 14
  • 14
  • 5
  • +2
38 Comments
 
LVL 3

Expert Comment

by:KoenVandemoortel
ID: 35513339
I use this function to find out the user's language:
function GetSysLangName: string; // language id. from registry
begin
case SysLocale.PriLangID of
   7: result:='Deutsch';
   9: result:='English';
  10: result:='Español';
  12: result:='Français';
  16: result:='Italiano';
  19: result:='Nederlands';
  else result:='Other';
  end;
end;

Open in new window

0
 

Author Comment

by:LeTay
ID: 35513375
Thanks Koen
But my main question is how to have the exe run with the ENG locale settings without having to change it on my compouter (for test purposes)
0
 
LVL 3

Expert Comment

by:KoenVandemoortel
ID: 35513544
Why don't you use a conditional define? Set it in the project options.  For the final compiliation you remove it in the options and leave it in the code.
function GetSysLangName: string; // language id. from registry
begin
{$IFDEF TEST}
result:='English';
{$ELSE}
case SysLocale.PriLangID of
   7: result:='Deutsch';
   9: result:='English';
  10: result:='Español';
  12: result:='Français';
  16: result:='Italiano';
  19: result:='Nederlands';
  else result:='Other';
  end;
{$ENDIF}
end;

Open in new window

0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 22

Expert Comment

by:8080_Diver
ID: 35513862
Or, perhaps better yet, pass an argument to the application ("yourappname.exe english" or "yourappname.exe german") and, in the conditional compile directive test that instead of the SysLocale.PriLandID.  If you want to run the app from the IDE, you can pass the parameter quite easily; however, it also gives you the ability to pass it on a commandline (e.g. from a shortcut).

I am providing a function I created in order to have the equivalent of a CASE statement but for strings:
function StringCase (const Sought       : string;
                     const CaseOptions  : array of string): Integer;
(******************************************************************************
 **                                                                          **
 ** Function:     StringCase                                                 **
 **                                                                          **
 ** Purpose:      This function compares the 'Sought' string to each of the  **
 **               strings in the 'CaseOptions' array and returns either the  **
 **               NDX of the matching CaseOption or a negative one (-1)      **
 **               indicating that the 'Sought' string was not found.         **
 **                                                                          **
 ** Parameters:                                                              **
 **               Sought      - The string to be matched                     **
 **               CaseOptions - An array of possible matching strings        **
 **                                                                          **
 ** Result:                                                                  **
 **               -1  - Default result, indicating no match was found        **
 **               NDX - The (zero based) index of the matching string        **
 **                                                                          **
 ** Exceptions:                                                              **
 **                                                                          **
 ** Author:       Ralph D. Wilson II                                         **
 **                                                                          **
 ** Date Created: 2005-01-10                                                 **
 **                                                                          **
 ** Revision History                                                         **
 **     Date      Initials   Modification                                    **
 **  01/10/2005    RDWII     Initial code created.                           **
 **                                                                          **
 ******************************************************************************)
var
  NDX: Integer;
begin
  Result:= Low(CaseOptions) - 2; // Set the default return parameter
  NDX :=  Low(CaseOptions) - 1;
  while (NDX < High(CaseOptions)) AND (Result  < NDX) do
  begin
    Inc(NDX);
    if  (Sought = CaseOptions[NDX])
    then begin
      Result  :=  NDX;
    end;
  end; {while}
end; {function}

Open in new window



function GetSysLangName: string; // language id. from registry
begin
{$IFDEF TEST}
Case StringCase(ParamStr[1], ['dutch','english','german','spanish','french','italian','nederlands']) of
   1: result:='Deutsch';
   2: result:='English';
   3: result:='Español';
   4: result:='Français';
   5: result:='Italiano';
   6: result:='Nederlands';
  else result:='Other';
  end;
{$ELSE}
case SysLocale.PriLangID of
   7: result:='Deutsch';
   9: result:='English';
  10: result:='Español';
  12: result:='Français';
  16: result:='Italiano';
  19: result:='Nederlands';
  else result:='Other';
  end;
{$ENDIF}
end;

Open in new window

0
 

Author Comment

by:LeTay
ID: 35513884
Well ....
Do I have to understand taht your GetSysLangName is replacing another GetSysLangName that would get the real value from Windows ?
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35513954
No, the conditional compikle directive would require you to deine it in order to use the first part (i.e. the part that does not get the value from Windows) and, if the directive is not defined, then the value is obtained from Windows.

The code (which needs to be placed before the {#$IFDEF . . . line) to activate the use of the no-Windows values would be:
{$DEFINE TEST}

Open in new window

0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35513967
Oh, yeah, you can also add TEST to the Conditional defines (found at Project/Options on the Directories/Conditionals tab).
0
 

Author Comment

by:LeTay
ID: 35513997
Okay
If I understand well, this conditional is finally a kink of trick to have for example in test mode, the program (says myprogram.exe) using the locale myprogram.ENG ?
0
 
LVL 3

Expert Comment

by:KoenVandemoortel
ID: 35514129
yes
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35514214
Check out Conditional Directive in the Delphi Help.  It is a very thing to know about. ;-).  In addition to the indicated use, it can also allow you to wrap modifications (as in, for the next version of the app) in conditional compiles so that you can test changes to the application and still be able to revert to the existing version to make bug-fixes.
0
 

Author Comment

by:LeTay
ID: 35514347
I know and use conditional directives
But I did not know how to "tell" my application that it is running in another locale than the real one ...
0
 
LVL 32

Expert Comment

by:Ephraim Wangoya
ID: 35522247

@8080_Diver

You can replace
  function StringCase (const Sought: string;  const CaseOptions  : array of string): Integer

with
  function AnsiIndexText(const AText: string; const AValues: array of string): Integer;

from StrUtils
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35690497
ewangoya,

Kind of depends on which version of Delphi you are working with. ;-)  Did you notice the date in the function?  That was when I ported it to a new location and added the documentation.  It was originally created in the early 2000's. ;-)
0
 
LVL 32

Expert Comment

by:Ephraim Wangoya
ID: 35690661

8080_Diver
Thats true, I did overlook that
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35691035
I still have that function around because I am still working with versions of Delphi from that era.

Somehow, I tend to wind up working with older versions of tools . . . something about clients not wanting to spend any more money than they have to. ;-)
0
 

Author Comment

by:LeTay
ID: 35696631
Hello
Can somebody summarise in a couple of lines what I have now to code ?
My Delphi s Delphi 2009
My locale are Belgium French
I plan to have the application also for English UK
What shall I code (the minimum) to be able
1. test the UK "version"
2. have the application starting with either french or english based on a parameter passed to it ?
Thanks
0
 
LVL 7

Expert Comment

by:huacat
ID: 35696746
0
 

Author Comment

by:LeTay
ID: 35696756
Hello huacat, my application is unicode, the article speaks about non-unicode ...
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35698146
The approach I would probably take would be to use the Conditional Compile Directive either to compile the code that accepts a commandline parameter to determine the desired language or to compile the code that uses the local system varaible to determine the proper language.  (The Conditional Compile Directive's parameter, e.g. UseUK, would be set in the Project/Options area.)  Once you have set the language indicator within your application, the rest of the application should work as though the local setting was for UK English.
0
 

Author Comment

by:LeTay
ID: 35698586
Using conditional compile etc... I understand, but shortly said, I do not understand how to "tell" to the application is it running with ENG locale ?
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35700085
If you have your app testing for commandline variables, you can simply put the indicator (e.g. ENG) on the commandline:
yourapplication.exe ENG

Open in new window


I would test for there being a parameter and then, if there is, have the app read that parameter and use it to set the appropriate language.

  {Note: The ParamCount includes teh application's executable name as ParamStr(0)}
  {          Also, I am assuming that the commandline would read [b]appname.exe ENGLISH[/b] for English}
  IF (ParamCount > 1)
  THEN BEGIN
    FOR i := 1 TO ParamCount DO
    BEGIN
      CASE AnsiIndexText(UpperCase(ParamStr(i)), ['DUTCH', 'ENGLISH', 'GERMAN', 'SPANISH', 'FRENCH', 'ITALIAN', 'NEDERLANDS']) OF
         1: result:='Deutsch';
         2: result:='English';
         3: result:='Español';
         4: result:='Français';
         5: result:='Italiano';
         6: result:='Nederlands';
        else result:='Other';
      END; {CASE}
    END; {FOR}
  END; {IF}

Open in new window



0
 
LVL 7

Expert Comment

by:huacat
ID: 35703833
Hi LeTay,

I'll like to use the control panel, international & regional settings, Regional settings, standard and format to set the locale settings(date format, currency format, and so on.).
This setting needn't restart the computer.

If you want to test language(like international & regional settings, advance page, NON-Unicode settings), I think we can use the AppLocale to do it.

Or

you can add a new user and set the user locale as your want, the use the switch user & logon as the new user to test your application.

Even you don't want to change the locale settings via control panel, I'm afraid we can do it via below method:
1. Please dump all language locale settings to a ini file, like this
    [UK]
    CurrencyString = '£'
    LongDateFormat = 'dd MMM yyyy'
    ShortDateFormat = 'dd/mm/yy'
    ...

    [US]
    CurrencyString = '$'
    ...
2. Pass a parameter or using INI to let the program know you wanna test which lang & locale settings. e.g. command line switch.
3. Add some code into the .dpr file, after "begin" line, e.g.
    if ParamStr(1) := 'UK' then
    begin
      SetThreadLocale(UK_LANG_ID);
      ShortDateFormat := IniRead('locale.ini', 'UK', 'ShortDateFormat');
      CurrencyString := IniRead('locale.ini', 'UK', 'CurrencyString');
      .........
    end;
    I think it better to do it with a function.

   All locale settings you can get it from the System.pas.

4. If you wanto change the lang UI dynamic, do it like other guys. and use below function to load the resource DLL.

function LoadNewResourceModule(Locale: LCID): Longint;
var
  FileName: array[0..260] of char;
  P: PChar;
  LocaleName: array[0..4] of Char;
  NewInst: Longint;
begin
  GetModuleFileName(HInstance, FileName, SizeOf(FileName));
  GetLocaleInfo(Locale, LOCALE_SABBREVLANGNAME, LocaleName, SizeOf(LocaleName));
  P := PChar(@FileName) + lstrlen(FileName);
  while (P^ <> '.') and (P <> @FileName) do Dec(P);
  NewInst := 0;
  Result := 0;
  if P <> @FileName then
  begin
    Inc(P);
    if LocaleName[0] <> #0 then
    begin
      // Then look for a potential language/country translation
      lstrcpy(P, LocaleName);
      NewInst := LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE);
      if NewInst = 0 then
      begin
        // Finally look for a language only translation
        LocaleName[2] := #0;
        lstrcpy(P, LocaleName);
        NewInst := LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE);
      end;
    end;
  end;
  if NewInst <> 0 then
    Result := SetResourceHInstance(NewInst)
end;

Full code can be download from http://en.pudn.com/downloads67/sourcecode/delphi_control/detail240891_en.html 

also you can check all function which support TFormatSettings
0
 

Author Comment

by:LeTay
ID: 35726897
Well finally I found another way
After creating the DLL for ENG locale, I renamed it from ENG to FRB (french belgium) and running the program, it uses it !
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35728474
Isn't that kind of cheating? ;-)

Did you even try the method I suggested (i.e. passing the parameter)?
0
 

Author Comment

by:LeTay
ID: 35729445
No : if I pass a parameter to the executable, it is fine, but I don't understand what the executable shell do with it for it to use the "right" localisation DLL !
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35729755
You have stated that you currently use the following to get the "right" language:
function GetSysLangName: string; // language id. from registry
begin
case SysLocale.PriLangID of
   7: result:='Deutsch';
   9: result:='English';
  10: result:='Español';
  12: result:='Français';
  16: result:='Italiano';
  19: result:='Nederlands';
  else result:='Other';
  end;
end;

Open in new window


If you replace it with the following code, then you should get the "right" language from same procedure:
function GetSysLangName: string; // language id. from registry
begin
{$IFDEF TEST}
CASE AnsiIndexText(UpperCase(ParamStr(i)), ['DUTCH', 'ENGLISH', 'GERMAN', 'SPANISH', 'FRENCH', 'ITALIAN', 'NEDERLANDS']) OF
   1: result:='Deutsch';
   2: result:='English';
   3: result:='Español';
   4: result:='Français';
   5: result:='Italiano';
   6: result:='Nederlands';
  else result:='Other';
  end;
{$ELSE}
case SysLocale.PriLangID of
   7: result:='Deutsch';
   9: result:='English';
  10: result:='Español';
  12: result:='Français';
  16: result:='Italiano';
  19: result:='Nederlands';
  else result:='Other';
  end;
{$ENDIF}
end;

Open in new window

0
 

Author Comment

by:LeTay
ID: 35729939
Ok ok, that's not the point
By which magic will my program use the right DLL ?
This is my main question
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35732182
How does it use it now?
0
 

Author Comment

by:LeTay
ID: 35733572
This is my question since the beginning
I have a Delphi application named myprogram.exe
I created a ENG localisation, so DLL myprogram.ENG
How does the "system" know to use the DLL ?
Via the system locale
My system locale is FRB so the DLL is NOT used
WITHOUT changing the system locale, how can my program use the ENG DLL ?
Is there a trick to do that ?
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35733621
How are you currently controlling the use of the DLL from the system locale?

I was assuming that your GetSysLangName function was driving that.  If that function is controlling the selection of the DLL, then the altered version of te function should do so based upon ParamStr(1).
0
 

Author Comment

by:LeTay
ID: 35736037
Hello 8080Diver, I do not control anything currently as I do not know how the do !
Of course I can the locale from Windows using such a function described by other experts about this question
But I don't know WHAT TO DO inside my application to use it !
Of course what I can do, it first to change my Windows locale then run the application, but I am searching for an alternative way to do it
That is my question
0
 
LVL 7

Accepted Solution

by:
huacat earned 2000 total points
ID: 35736352
I assume you wanna this: Switch language when program running.
 MultiLan.zip
0
 

Author Comment

by:LeTay
ID: 35736572
I just want the program ITSEF to be able to decide to run with one or another locale
Will have a look at your zip !
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35737953
huacat,

Can you provide a brief description of what your zipped demo does?  (It always helps to provide some information regarding the contents of a zipped file instead of just saying, "Here, do this." because some of us are restricted regarding opening things if we don't have any idea what is in it or what it does. ;-)
0
 
LVL 7

Expert Comment

by:huacat
ID: 35738108
The attached Demo is very simple, only demo two function:
1: Automatic load the Localisation DLL resource(which created by Delphi ITE) according the system default language when program load.
2: Let the user change the language to anyone if the wanted. (Attached only create two language resource DLL: Chinese & English, User can switch them dynamic)
 Screenshots of Multilan Demo
0
 
LVL 7

Expert Comment

by:huacat
ID: 35738134
Because ex-ex block some files, so I can't zip all files, but we can download the whole source from below URL:
http://en.pudn.com/downloads67/sourcecode/delphi_control/detail240891_en.html 
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 35739911
@huacat,

Thank you for the explanation.  It was not that I felt insecure about your doe but I have to have an answer for our security guy should he ask. ;-)

Looks like a handy demo to have.

@LeTay,

huacat's demo should provide you with the answer for how to change languages based upon the commandline parameter.
0
 

Author Comment

by:LeTay
ID: 35744509
@huacat
Thank you, I unzipped an ran it successfully
I will try to adapt it to my case
I keep you informed
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Loops Section Overview
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
Suggested Courses

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question