Can package with localization feature?

27.6.05

I am trying to add multi-language support feature into my package but meet difficulties. In the package, some components are to send command to the host server and handle its responses code. Based on received code, the components return out the corresponding message. With localization feature, the components need able to return the translated messages based on workstation locale or application defined language. It seems to be not difficult task as many 3rd party localization toolkits are available like Localizer, TsiLang and etc.
But when I do it with the localization toolkit (my boss picks Localizer as it performs pretty well in the stress test), I find this is not as easy as I think. Let me explain it in details with the simple testing package and program:

I have prepared a class TStrLibrary in the package for holding all possible codes and messages:


type
TStrLibrary = Class(TObject)
private
FLib: TStringList;
procedure PrepareLibrary;
protected
constructor Create;
public
destructor Destroy; override;
function GetLibMessage(Const ACode: String): String;
end;

resourcestring
R_String = 'String 1'; // in Chinese is 'String 1 (CHI)'
R_String2 = 'String 2'; // in Chinese is 'String 2 (CHI)'
R_String3 = 'String 3'; // in Chinese is 'String 3 (CHI)'

procedure TStrLibrary.PrepareLibrary;
begin
With FLib do
begin
Values['CODE1'] := R_String;
Values['CODE2'] := R_String2;
Values['CODE3'] := R_String3;
end;
end;

function TStrLibrary.GetLibMessage(const ACode: String): String;
begin
if FLib.IndexOfName(ACode) > -1 then
Result := FLib.Values[ACode]
else
Result := '';
end;


In the program,
uses
LocOnFly, StrLibrary;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
LStrLibrary: TStrLibrary;
Public
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
LocalizerOnFly.PopulateMenu(memuItem, 0);
LTestingLibrary := TMessageLib.GetInstance;
end;

// after select language (e.g. Chinese),
// click Button1 to pretend receiving message code from server
procedure TForm1.Button1Click(Sender: TObject);
var
LStr: String;
begin
LStr := LStrLibrary.GetStr(Edit1.text);
Memo1.Lines.Add(Edit1.text +' is translated to '+LStr);
end;
Everything can be localized in the application but not in the components. When input "CODE1" in editbox Edit1, it always return "String 1" no matter which language I select. After consulting with Localizer support, it is normal as Localizer does not translate those not used in the application. And the resourcestrings in the TStrLibrary is loaded at the moment it being created and never after.

Does it mean there is no way to do localization in my package??

[updated on Jun 28 for blog display]


Comments:
add dummy string constants to cheat localizer...e.g.

implementation

const
_R_String = R_String;
...

sorry... posted too fast, wrong syntax, should be

_R_String: string = R_String;

Hi.
I'm Urano and I am living in Mexico City. I'm a reader for you blog.
Today I realized that the format in your blog has changed. I don't like the new format, What happened?

Best Regards...
Urano

Urano, I also find that the display format is changed today... Let me check check what happened :P

Found what wrong with the display.
It is due to too long code above within a line.

William,
I don't want to take this solution as the component users has to add a list of dummy strings into their programs.

Not quite get your meaning??? If it is your component (designtime + runtime package), you can put the dummy constants definition in the same units as of the resourcestring. BTW, it is Delphi itself who removed unused resourcestring, and I think localizer now supports so called external strings?

Hi Gloria,

Any unused strings are normally optimized out by the Delphi compiler. You can see this by telling the Delphi compiler to leave the .drc file (I think the command-line option is --gendrc) and opening it in a text editor. Any resource strings not used by your application will not show up in the .drc file.

As far as the loading of the resources, if you are using resourcestrings then this is automatically done when your program starts. BTW, you can try looking at the source for the LoadResourceModule function in System.pas to see how exactly the resource loading is done.

If you really want to be able to change resources on the fly, see the RichEdit demo (should be under \Demos\RichEdit), specifically the source file reinit.pas. That should give you some ideas on what would need to be done.

If you have any questions or clarifications, please do not hesitate to contact me. My email is lsaguisag (at) borland (dot) com.

Cheers.

-- Leo

This comment has been removed by a blog administrator.

Post a Comment

<< Home