Recent

Author Topic: Example project for translation  (Read 28629 times)

Avishai

  • Hero Member
  • *****
  • Posts: 1021
Re: Example project for translation
« Reply #15 on: December 09, 2013, 01:32:37 am »
Here is some more R2L code you might find interesting.

Code: [Select]
function IsMirrored(ACtrl: TObject): Boolean;
begin
  Result:= False;
  if ACtrl is TWinControl then
    Result:= (GetWindowLong(TWinControl(ACtrl).Handle, GWL_EXSTYLE)
      and WS_EX_LAYOUTRTL)<>0;
end;

procedure RTLCtrl(ACtrl: TObject);
{ Make TWinControl RightToLeft - MSWindows ONLY! }
begin
  if ACtrl is TWinControl then
    with TWinControl(ACtrl) do
      SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
end;

procedure LTRCtrl(ACtrl: TObject);
{ Make TWinControl LeftToRight - MSWindows ONLY! }
begin
  if ACtrl is TWinControl then
    with TWinControl(ACtrl) do
      SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_LAYOUTRTL);
end;
« Last Edit: December 09, 2013, 06:02:53 am by Avishai »
Lazarus Trunk / fpc 2.6.2 / Win32

CM630

  • Hero Member
  • *****
  • Posts: 1522
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Example project for translation
« Reply #16 on: December 19, 2013, 08:39:07 am »
Thanks for the good explanation.
There are two major point that is not mentioned.
1. All interface items must be autosized, since strings have different length in each language. In my opinion, if the main interface is in English, at least 50% more space shall be considered.
2. Anchoring must be used, to prevent overlaps.
I added a GUI Design section in the wiki.
3. ShowMessage is not proper for localization, because the OK, Cancel, Yes, No, etc. strings will be retrieved from the language of the OS (or LCL?? which might not be translated). QuestionDlg is a much better solution. The thing I hate about is that I cannot find out how to remove the delphi-like icons from the buttons.
Because QuestionDialog takes too much parameters, things mighty be made easier:
Code: [Select]
procedure MsgBox (aString: string);
begin
    QuestionDlg (SMessage,aString,mtCustom,[mrOK,SOK],'');
end;
« Last Edit: December 19, 2013, 09:33:38 am by paskal »
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13210
Re: Example project for translation
« Reply #17 on: December 19, 2013, 09:17:43 am »
Thank you. I added another sentence on positioning of label above the controls instead of to the left.

Avishai

  • Hero Member
  • *****
  • Posts: 1021
Re: Example project for translation
« Reply #18 on: December 19, 2013, 09:25:27 am »
This is a good point.  I normally anchor the Label to both the Left and Right side of the Control and set Label.WordWrap:= true so that it can become multi-line when needed.  But you have to plan the layout to allow for that vertical growth.  I guess everyone has their own methods.
Lazarus Trunk / fpc 2.6.2 / Win32

parcel

  • Full Member
  • ***
  • Posts: 144
Re: Example project for translation
« Reply #19 on: December 19, 2013, 09:35:23 am »
3. ShowMessage is not proper for localization, because the OK, Cancel, Yes, No, etc. strings will be retrieved from the language of the OS. QuestionDlg is a much better solution. The thing I hate about is that I cannot find out how to remove the delphi-like icons from the buttons.
Dialog localization can translated with LCLStrConsts.(lang).po Files.

like this
Code: [Select]
  Translations.TranslateUnitResourceStrings('LCLStrConsts', 'lclstrconsts.%s.po', lng, lngf);

CM630

  • Hero Member
  • *****
  • Posts: 1522
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Example project for translation
« Reply #20 on: December 19, 2013, 09:56:11 am »
Yes, but can separate LCL translations for your application?
One of the cases is when LCL is not translated. Then you expect the translator of your app to translate it and to send it to someone from the Lazarus project. Well, the translator might have no idea what Lazarus is. Also, that might mean that he/she will be have to translate out of the context, which is not a nice idea.
The second case is when LCL is translated. Then practically you have one translator translating LCL, and another one, translating you application. This could cause inconsistency.
I would do anything possible not to use a string, which is translatable out of my application.
Edit: I just came to  http://wiki.lazarus.freepascal.org/Step-by-step_instructions_for_creating_multi-language_applications#Strings_defined_by_the_LCL. I will take some time to comprehend it.
Edit: If I understand the sentence  This works because resourcestrings are pulled in from all language files for the active language found in the languages folder right, one might have the same strings from LCL in his project and the strings from his project will have a higher priority?

« Last Edit: December 19, 2013, 10:28:44 am by paskal »
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13210
Re: Example project for translation
« Reply #21 on: December 19, 2013, 10:40:47 am »
To make it clear: to have LCL strings translated you copy lclstrconsts.*.po to your languages folder, and then you can modify them in any way you want - LCL translations are completely coupled off of Lazarus.

@parcel: There is no need to call TranslateUnitResourceStrings, this is done by Defaulttranslator automatically.

Unfortunately, there's a lot of common dialogs where strings are defined by the OS and cannot be changed that easily...

CM630

  • Hero Member
  • *****
  • Posts: 1522
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Example project for translation
« Reply #22 on: December 19, 2013, 11:13:30 am »
There is one more issue.
For example I have:
Code: [Select]
resourcestring
  SFileDoesNotExist = 'File does not exist.';
begin
  ShowMessage(SFileDoesNotExist);
end;
But I want to put the name of the file inside.
I can use nor  ShowMessage(SFileDoesNotExist + filename); neither  ShowMessage(SFile + filename + SDoesNotExist); because word order might vary.
There was some trick with %something. It shall be written in the wiki.



Unfortunately, there's a lot of common dialogs where strings are defined by the OS and cannot be changed that easily...
So if ShowMessage is one of these, it shall not be used.
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Example project for translation
« Reply #23 on: December 19, 2013, 11:42:04 am »
use format eg

Code: [Select]
resourcestring
  SFileDoesNotExist = 'File <%S> not found';
...

begin
...
ShowMessage(format(SFileDoesNotExist ,[ filename]);
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Avishai

  • Hero Member
  • *****
  • Posts: 1021
Re: Example project for translation
« Reply #24 on: December 19, 2013, 11:55:33 am »
You have a lot of flexibility with MessageDlg.  This code shows how to add some things but it's just garbage to show how to do it.

Edit: I just added code to get rid of the "delphi-like icons".

Code: [Select]
procedure TForm1.btnMeassageClick(Sender: TObject);
var
  RtlMessageDlg: TForm;
  I: Integer;
  ALabel: TLabel;
  Radio: TRadioButton;
begin
  RtlMessageDlg:= CreateMessageDialog('This is the Message Text.', mtConfirmation,[mbOK, mbCancel]);
  RtlMessageDlg.Caption:= 'A Caption';

  RtlMessageDlg.Controls[0].Caption:= 'Ok button Text';
  TBitBtn(RtlMessageDlg.Controls[0]).Glyph:= Nil;  // Get rid of delphi-like icons

  RtlMessageDlg.Controls[1].Caption:= 'Cancel button Text';

  for I:= 0 to RtlMessageDlg.ControlCount-1 do
    RtlMessageDlg.Controls[I].BiDiMode:= bdRightToLeft;

  RtlMessageDlg.Width:= RtlMessageDlg.Width*2;
  RtlMessageDlg.Height:= RtlMessageDlg.Height*2;

  ALabel:= TLabel.Create(Self);
  ALabel.Caption:= 'Some Text to Show!';
  ALabel.Parent:= RtlMessageDlg;
  ALabel.Align:= alBottom;
  ALabel.Alignment:= taCenter;

  Radio:= TRadioButton.Create(Self);
  Radio.Caption:= 'Some Text to Show!';
  Radio.Parent:= RtlMessageDlg;
  Radio.Align:= alBottom;

  RtlMessageDlg.ShowModal;
  FreeAndNil(RtlMessageDlg);
end;
« Last Edit: December 19, 2013, 12:40:34 pm by Avishai »
Lazarus Trunk / fpc 2.6.2 / Win32

CM630

  • Hero Member
  • *****
  • Posts: 1522
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Example project for translation
« Reply #25 on: December 19, 2013, 12:40:20 pm »
So it goes:
Code: [Select]
resourcestring
 SFilesProcessed = '%d out of %d files processed in folder „%s.“'
...
 ShowMessage(format(SFilesProcessed ,[27,49,'c:\'])); 
I suppose the answer is No, but there is probably no inbuilt function to replace the %d and %s with numbers?
To translate this line I have to do
Обработени са % change_keyboard_layoutdchange_keyboard_layout файла от общо   %change_keyboard_layoutdchange_keyboard_layout в папка %change_keyboard_layoutschange_keyboard_layout
If these chars were number I would simply do:
Обработени са %1 файла от общо %2 в папка „%3“.   
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Example project for translation
« Reply #26 on: December 19, 2013, 01:03:28 pm »
erm have you test it and it didn't work? Because what you have posted is the correct way to replace %D with numbers, integer numbers, of course there are more defines you can use for various data types as well, take a closer look on the Format description.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

wp

  • Hero Member
  • *****
  • Posts: 13210
Re: Example project for translation
« Reply #27 on: December 19, 2013, 01:12:49 pm »
Quote
resourcestring
 SFilesProcessed = '%d out of %d files processed in folder „%s.“'
And I'd use indices in the format specifier because the order of parameters may change from language to language. This is better:
Code: [Select]
resourcestring
 SFilesProcessed = '%0:d out of %1:d files processed in folder „%2:s.“'
begin
...
  ShowMessage(Format(SFilesProcessed, [27, 49, 'c:\']));
Therefore, the given format statement would still be valid if the translated version would be (back-translated to english) 'In folder "%2:s", %0:d out of %1 files were processed.'

CM630

  • Hero Member
  • *****
  • Posts: 1522
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Example project for translation
« Reply #28 on: December 19, 2013, 01:49:29 pm »
erm have you test it and it didn't work?
No, it works. The problem is that it uses Latin characters (s, d, etc) which requires the tranlators to change the keyboard layouts too often.
I just wrote a function to show the idea:
Code: [Select]
Uses ...strutils...
...
function LocalizeRowMultiple(const aString:string; const Args: array of String):string;

var
   RetVal:string;
   i: integer;
begin
   RetVal:=aString;
   for i:= 0 to Length(Args)-1 do
   begin
      RetVal:= StringsReplace  (RetVal,'%'+IntToStr(i+1), Args[i],[]);
   end;
   Result:=RetVal ;
end;
Usage is  SFilesProcessed = '%1 out of %2 files processed in folder „%3.“'


@WP, IMHO adding your example in the wiki will be useful.
« Last Edit: February 20, 2014, 10:22:58 am by paskal »
Лазар 4,2 32 bit (sometimes 64 bit); FPC3,2,2

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Example project for translation
« Reply #29 on: December 19, 2013, 02:43:54 pm »
No, it works. The problem is that it uses Latin characters (s, d, etc) which requires the tranlators to change the keyboard layouts too often.

1) you do not know the translators work flow
2) you can leave all the defines to be inserted after the translation, that will make things easier.
3) the format function is open sourced you can take it and change it as needed, eg use only index defines instead of data and use the TVarRec to guess what the user wants to show.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

 

TinyPortal © 2005-2018