Jump to content

Recommended Posts

Hi,

 

I'm revisiting the application I wrote to help me manage my applications localization, but after seeing all the nice work done in better translation manager... I'm puzzled.. Should I continue with my interface, or move to BTM?
So here I am....I need to know how I can duplicate some features my implementation has.

 

Basically my application generates a global class (glbLocalization) that I include in my projects.
I can access all the localization properties I require. For example: glbLocalization.FormLogin.btnLogin.caption( aLanguageID : Cardinal = 0 )

When LanguageID is 0, the user default kicks in, which means, can be windows language, or any other language the user wants to be its default.

 

There is a feature that my customers are very used too: Multi language UI.
Basically this features allows the user to do whatever localization combination he likes:

  * The application remains in the main language, reports can be generated in any other languages.
  * Any form can be opened in different languages.


Ex: All the user interface is in portuguese. The reports can be viewed in portuguese and mailed to a Brazilian manager, switch to any  other supported language and email the report directlly
     The user might need to share some information available on his form with another user in LA, He opens another form in Spanish and share the contents.

 

The implementation became trivial since I just have pass the LanguageID as the parameter ( to a form, report, etc) and everything is retrieved from the corresponding resource.
To achieve this I generate a single resource file (.RC) with all the supported languages and translation. Given the LanguageID, it's a matter to go the corresponding section and get the string.
Delphi's RTL resources (aka ResourceString) are not translated, it's a feature I would like to add in this new version.

 

Back in Borland era, when I studied delphi translation features, I haven't found a way to implement the above features.
Is there a way to use BTM (or delphi native localization) to mimic the above feature?


 

Share this post


Link to post

It seems to me that what you're describing is beyond the scope of localization and therefore BTM.

BTM is a localization manager/editor. It provides translations to the standard localization mechanism built into the Delphi RTL. If you're not using that, and it doesn't sound like it, then I can't see how BTM can meet your needs.

 

That said, the translated resource modules generated by BTM are just DLLs containing the translated resources (i.e. resourcestrings and DFMs). This means that you can use regular Windows APIs to load and extract the resources from these resource modules. It's also possible to hook into the resource loading mechanism and redirect the loading of selected forms to other resource modules. This could provide the multi-language capability. You could also just read the translation project file (it's XML) and extract the translations from there.

But, to be honest, none of the above sounds like a good path to go down.

Share this post


Link to post

I liked BTM but I was afraid you would say that.
I will have to keep my interface then.

 

Anyway, thanks for that great tool!

 

Share this post


Link to post

I use dxGetText (https://sourceforge.net/projects/dxgettext/) in all my application which must support several languages. To do the translation it self, I used PoEdit (https://poedit.net/).

 

I have never been confronted to some parts being translated in one language and others translated in a different languages but I think it is possible to do it since translation process pass by functions you have control on it.

 

Share this post


Link to post
1 hour ago, FPiette said:

I have never been confronted to some parts being translated in one language and others translated in a different languages but I think it is possible to do it since translation process pass by functions you have control on it.

I have done that with dxgettext, so, yes, it can be done. But beware that dxgettext does not support translating FMX forms out of the box, only VCL.

 

As for the translation tool, I prefer Gorm over PoEdit, mostly because it's written in Delphi and I have got the source code and write access to the repository, so I can adapt and extend it (and have done that).

Share this post


Link to post

There's also the Virtaal translation editor, which hasn't been updated for a while, but works fine.

There are many platforms that can handle gettext .po files and provide nice web editors, if you are in need of collaborative translation. Most of them are free for OSS projects.

Share this post


Link to post

Hi,

I finally reached a Beta version of the utility I'm rewriting to help me manage my application localization.

Since I talked about it here, I thought I could share some screens to give you an idea of this tool. 

I'm using mustache templates to generate the output, in theory the utility can generate code for any language. The generation process creates a JSON containing the translations that is merged with the templates.
For the .RC and Delphi I using the following templates:

 

.RC:

{{#constants}}
#define {{name}} {{value}}
{{/constants}}
{{#resources}}
STRINGTABLE 
LANGUAGE {{language}}, {{subLanguage}}
BEGIN
{{#stringTable}}
     {{{name}}}  "{{{value}}}"
{{/stringTable}}
END   
{{/resources}}

.PAS (part of it):

unit app.localization;

interface

uses WinAPI.Windows;

const
{{#languages}}
   {{constantName}} = {{languageID}};
{{/languages}}
// ---------------
{{#constants}}
    {{name}} = {{value}};
{{/constants}}



function _( const StringID : DWORD; aLanguageID : DWORD = 0 ) : String;
procedure SetDefaultLanguage( aLanguageID : DWord );

implementation

{$R {{outputRES}}}

var  
   gDefaultLanguage : DWord;
   
procedure SetDefaultLanguage( aLanguageID : DWord );
begin
  gDefaultLanguage := aLanguageID;
end;   
   

function StringTableRes(hInstLib: Cardinal; idString: DWORD; wLang: Word): String;


This is the generate .PAS:

unit app.localization;

interface

uses WinAPI.Windows;

const
   _EN_US = 1033;
   _PT_BR = 1046;
   _EL_GR = 1032;

// ---------------
    GLOBAL_CPTN_BTN_OK = 1;
    GLOBAL_CPTN_BTN_APPLY = 2;
    GLOBAL_CPTN_BTN_CANCEL = 3;
    GLOBAL_CPTN_BTN_PRINT = 4;
    GLOBAL_CPTN_BTN_EXPORT = 5;
    GLOBAL_CPTN_BTN_FILTER = 6;
    GLOBAL_CPTN_GB_SAMPLEDATA = 7;
    GLOBAL_TXT_SAMPLE_DESCRIPTION = 8;
    FORMLOGIN_CPTN_WELCOME = 9;




function _( const StringID : DWORD; aLanguageID : DWORD = 0 ) : String;
procedure SetDefaultLanguage( aLanguageID : DWord );

implementation

{$R teste.res}

var  
   gDefaultLanguage : DWord;
   
procedure SetDefaultLanguage( aLanguageID : DWord );
begin
  gDefaultLanguage := aLanguageID;
end;   
   



Let me show you the result:
 

image.thumb.png.15f472c1dfb1cd46113f0cd60a6be03d.png

 

The code:

implementation

uses app.localization;

{$R *.dfm}

procedure TForm1.DoLocalize;
begin
    GroupBox1.Caption := _( GLOBAL_CPTN_GB_SAMPLEDATA, _EN_US );
    GroupBox2.Caption := _( GLOBAL_CPTN_GB_SAMPLEDATA, _PT_BR );
    GroupBox3.Caption := _( GLOBAL_CPTN_GB_SAMPLEDATA, _EL_GR );


    btnOK.Caption  := _( GLOBAL_CPTN_BTN_APPLY, _EN_US );
    btnOk1.Caption := _( GLOBAL_CPTN_BTN_APPLY, _PT_BR );
    btnOk2.Caption := _( GLOBAL_CPTN_BTN_APPLY, _EL_GR );

    btnCancel.Caption  := _( GLOBAL_CPTN_BTN_CANCEL, _EN_US );
    btnCancel1.Caption := _( GLOBAL_CPTN_BTN_CANCEL, _PT_BR );
    btnCancel2.Caption := _( GLOBAL_CPTN_BTN_CANCEL, _EL_GR );

    label1.caption := _( GLOBAL_TXT_SAMPLE_DESCRIPTION, _EN_US );
    label2.caption := _( GLOBAL_TXT_SAMPLE_DESCRIPTION, _PT_BR );
    label3.caption := _( GLOBAL_TXT_SAMPLE_DESCRIPTION, _EL_GR );



end;

procedure TForm1.DoShow;
begin
  DoLocalize;
  inherited;

end;

And the generator

 

image.thumb.png.4e8b026708ed9f77f763dc0c5035d1ab.pngimage.thumb.png.b4c0d6841b6d36d0eb3700c73af43c27.pngimage.thumb.png.58573db0e07dfa4261f40d7960e7a6d4.pngimage.thumb.png.f10d94cd6da5e5087afe5b80c6c92652.png

 

Edited by Clément

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×