Hi,
I am using the TSILang and I am very satisfied with them. I have only on problem: I can't translate the Shortcut names of Menuitems. That means, that "Strg+N" is replaced with "Ctrl+N". Is there a solution for this?
Kai
Translation of Shortcuts in Menus
Unfortunately, Borland didn't make these strings (shortcut names) used as resource strings when translating shortcut values to string representation in menus unit.
So this is possible only by altering code in standard Menus.Pas unit and translating resource strings responsible for shortcut names using resource string wizard from expert. If this is acceptable for you we can provide step by step instructions. Let us know about your decision.
So this is possible only by altering code in standard Menus.Pas unit and translating resource strings responsible for shortcut names using resource string wizard from expert. If this is acceptable for you we can provide step by step instructions. Let us know about your decision.
Hi,
I have the same question as kai.
I've developed internationalization functions
for BCB 4 on my own which work perfectly,
even for Japanese. The language file are
simple text files which are loaded at
run-time.
The *only* thing left to translate are the
menu shortcuts.
If anybody as any ideas, let me know!
Thanx, Stefan
I have the same question as kai.
I've developed internationalization functions
for BCB 4 on my own which work perfectly,
even for Japanese. The language file are
simple text files which are loaded at
run-time.
The *only* thing left to translate are the
menu shortcuts.
If anybody as any ideas, let me know!
Thanx, Stefan
In SiComp.pas unit there is procedure called:
procedure OverwriteProcedure(OldProcedure, NewProcedure: Pointer);
Just copy it into your code and use the following example code which allows translation menu shortcuts:
Hope this helps.
procedure OverwriteProcedure(OldProcedure, NewProcedure: Pointer);
Just copy it into your code and use the following example code which allows translation menu shortcuts:
Code: Select all
function SiShortCutToText(ShortCut: TShortCut): string;
implementation
{$R *.dfm}
function GetSpecialName(ShortCut: TShortCut): string;
var
ScanCode: Integer;
KeyName: array[0..255] of Char;
begin
Result := '';
ScanCode := MapVirtualKey(WordRec(ShortCut).Lo, 0) shl 16;
if ScanCode <> 0 then
begin
GetKeyNameText(ScanCode, KeyName, SizeOf(KeyName));
GetSpecialName := KeyName;
end;
end;
function SiShortCutToText(ShortCut: TShortCut): string;
var
Name: string;
begin
case WordRec(ShortCut).Lo of
$08: Name := Form1.siLang1.GetTextOrDefault('IDS_0' (* 'BkSp' *) );
$09: Name := Form1.siLang1.GetTextOrDefault('IDS_1' (* 'Tab' *) );
$0D: Name := Form1.siLang1.GetTextOrDefault('IDS_2' (* 'Enter' *) );
$1B: Name := Form1.siLang1.GetTextOrDefault('IDS_3' (* 'Esc' *) );
$20: Name := Form1.siLang1.GetTextOrDefault('IDS_4' (* 'Space' *) );
$21: Name := Form1.siLang1.GetTextOrDefault('IDS_5' (* 'PgUp' *) );
$22: Name := Form1.siLang1.GetTextOrDefault('IDS_6' (* 'PgDn' *) );
$23: Name := Form1.siLang1.GetTextOrDefault('IDS_7' (* 'End' *) );
$24: Name := Form1.siLang1.GetTextOrDefault('IDS_8' (* 'Home' *) );
$25: Name := Form1.siLang1.GetTextOrDefault('IDS_9' (* 'Left' *) );
$26: Name := Form1.siLang1.GetTextOrDefault('IDS_10' (* 'Up' *) );
$27: Name := Form1.siLang1.GetTextOrDefault('IDS_11' (* 'Right' *) );
$28: Name := Form1.siLang1.GetTextOrDefault('IDS_12' (* 'Down' *) );
$2D: Name := Form1.siLang1.GetTextOrDefault('IDS_13' (* 'Ins' *) );
$2E: Name := Form1.siLang1.GetTextOrDefault('IDS_14' (* 'Del' *) );
$30..$39: Name := Chr(WordRec(ShortCut).Lo - $30 + Ord('0'));
$41..$5A: Name := Chr(WordRec(ShortCut).Lo - $41 + Ord('A'));
$60..$69: Name := Chr(WordRec(ShortCut).Lo - $60 + Ord('0'));
$70..$87: Name := 'F' + IntToStr(WordRec(ShortCut).Lo - $6F);
else
Name := GetSpecialName(ShortCut);
end;
if Name <> '' then
begin
Result := '';
if ShortCut and scShift <> 0 then Result := Result + Form1.siLang1.GetTextOrDefault('IDS_15' (* 'Shift+' *) );
if ShortCut and scCtrl <> 0 then Result := Result + Form1.siLang1.GetTextOrDefault('IDS_16' (* 'Ctrl+' *) );
if ShortCut and scAlt <> 0 then Result := Result + Form1.siLang1.GetTextOrDefault('IDS_17' (* 'Alt+' *) );
Result := Result + Name;
end
else Result := '';
end;
type
TAccessMenu = class(TMenu);
procedure TForm1.Language1Click(Sender: TObject);
begin
siLang1.ActiveLanguage := TComponent(Sender).Tag;
TAccessMenu(MainMenu1).UpdateItems;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TAccessMenu(MainMenu1).UpdateItems;
end;
initialization
OverwriteProcedure(@ShortCutToText, @SiShortCutToText);
end.
The answer was how to translate the shortcuts using TsiLang Components Suite.
In order to translate them without using TsiLang Components Suite I can suggest the following way:
1. Delphi/C++Builder show shortcuts in menu after converting the shortcut value (word) to text prezentation.
2. This is done using ShortCutToText() function from Menus.pas unit.
3. Unfortunately, Borland didn't make the strings that are used in this conversation used as resource strings. You can see this by investigating original source code of ShortCutToText() function from Menus.pas unit.
4. So in order to translate this you can make a "hack" by overwriting the ShortcutToText() function in your executable by yours implementation. And in your implementation just use strings corresponding to shortcut modifiers as Shift, CTRL... and using your translate algorithm translate them.
OverwriteProcedure is implemented like this:
In order to translate them without using TsiLang Components Suite I can suggest the following way:
1. Delphi/C++Builder show shortcuts in menu after converting the shortcut value (word) to text prezentation.
2. This is done using ShortCutToText() function from Menus.pas unit.
3. Unfortunately, Borland didn't make the strings that are used in this conversation used as resource strings. You can see this by investigating original source code of ShortCutToText() function from Menus.pas unit.
4. So in order to translate this you can make a "hack" by overwriting the ShortcutToText() function in your executable by yours implementation. And in your implementation just use strings corresponding to shortcut modifiers as Shift, CTRL... and using your translate algorithm translate them.
OverwriteProcedure is implemented like this:
Code: Select all
procedure OverwriteProcedure(OldProcedure, NewProcedure: pointer);
var
x: pchar;
y: integer;
ov2, ov: cardinal;
begin
x := PChar(OldProcedure);
if not VirtualProtect(Pointer(x), 5, PAGE_EXECUTE_READWRITE, @ov) then
RaiseLastOSError;
x[0] := char($E9);
y := integer(NewProcedure) - integer(OldProcedure) - 5;
x[1] := char(y and 255);
x[2] := char((y shr 8) and 255);
x[3] := char((y shr 16) and 255);
x[4] := char((y shr 24) and 255);
if not VirtualProtect(Pointer(x), 5, ov, @ov2) then
RaiseLastOSError;
end;
Hi!
Thanx for your answer!
I've converted your code into C++. Does anybody find any
errors? At least it compiles without errors or warnings ...
Unfortunately, Borland C++ Builder 4 doesn't have a file
called "Menus.pas". It only has some headers or already
compiled files.
Could anyone, please, post the ShortcutToText() function
here?
By the way: Where should I call the overwrite function?
Before any forms are created?
Thanx
Stefan
Thanx for your answer!
I've converted your code into C++. Does anybody find any
errors? At least it compiles without errors or warnings ...
Code: Select all
void OverwriteProcedure(Pointer OldProcedure, Pointer NewProcedure)
{
PChar x;
int y;
unsigned long ov2, ov;
x = PChar(OldProcedure);
if (!VirtualProtect(Pointer(x), 5, PAGE_EXECUTE_READWRITE, &ov))
RaiseLastWin32Error();
x[0] = char('E9');
y = int(NewProcedure) - int(OldProcedure) - 5;
x[1] = char(y & 255);
x[2] = char((y >> 8) & 255);
x[3] = char((y >> 16) & 255);
x[4] = char((y >> 24) & 255);
if (!VirtualProtect(Pointer(x), 5, ov, &ov2))
RaiseLastWin32Error();
}
called "Menus.pas". It only has some headers or already
compiled files.
Could anyone, please, post the ShortcutToText() function
here?
By the way: Where should I call the overwrite function?
Before any forms are created?
Thanx
Stefan
Below is example code from C++ Builder to perform discussed task:
Code: Select all
AnsiString __fastcall SiShortCutToText(TShortCut ShortCut)
{
AnsiString res = "AAA";
return (res);
}
void OverwriteProcedure(Pointer OldProcedure, Pointer NewProcedure)
{
PChar x;
int y;
unsigned long ov2, ov;
x = PChar(OldProcedure);
if (!VirtualProtect(Pointer(x), 5, PAGE_EXECUTE_READWRITE, &ov))
RaiseLastWin32Error();
x[0] = 0xE9;
y = int(NewProcedure) - int(OldProcedure) - 5;
x[1] = char(y & 255);
x[2] = char((y >> 8) & 255);
x[3] = char((y >> 16) & 255);
x[4] = char((y >> 24) & 255);
if (!VirtualProtect(Pointer(x), 5, ov, &ov2))
RaiseLastWin32Error();
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
OverwriteProcedure(&ShortCutToText, &SiShortCutToText);
// to update menu and recreate shortcuts
MainMenu1->Images = NULL;
}