Hi
I'm looking for your experience regarding the best approach to produce TMS Web app in 2 (or more) languages mainly based upon Delphi level than javascript
In VCL world I like solutions similar to TsiLang, but how do you process in TMS Web devs?
thanks
You might want to have a look at the TMSWeb_MultiLanguage demo. Basically, each Form has multiple associated HTML files. One for each language. You switch languages at runtime like this:
Application.Language := lGerman;
Hth, Walter
Thanks for
But in this case, it will be a mess for designer manage N templates per form for complex applications without taking profit of IDE level and components.
But it's a first approach... thanks
In another project, we read the language strings from a DB based on the Delphi controls name sitting on the form. It goes like this:
Type
TSupportedLanguage = (slNone,slGerman,slEnglish,slFrench);
TLanguageStringObject = Class
LanguageString : String;
End;
Const
LanguageID : Array [TSupportedLanguage] of String = ('','DE','EN','FR');
ControlTagNoLanguageCheck = 999;
ControlTagShowByLanguage = 998;
{---------------------------------------}
Function LanguageIDtoTSupportedLanguage(Const ID : String) : TSupportedLanguage;
Begin
For Result := TSupportedLanguage(1) to High(TSupportedLanguage) do
If ID=LanguageID[Result] then exit;
Result := slNone;
End;
{---------------------------------------}
Procedure TDM.SetLanguagePack(LanguagePack: TJSArray);
// LanguagePack is a JS Key-Value array received from a REST call
Var
LangItem : TJSObject;
LangKey,
LangStr : String;
LSO : TLanguageStringObject;
I : Integer;
Begin
Console.log(TrIn('TDM.SetLanguagePack'));
Try
If not assigned(CurrentLanguagePack) then
Begin
CurrentLanguagePack := TStringList.Create;
CurrentLanguagePack.Duplicates := dupError;
CurrentLanguagePack.Sorted := True;
CurrentLanguagePack.CaseSensitive := False;
End
Else
CurrentLanguagePack.Clear;
For I := 0 to LanguagePack.Length-1 do
Begin
LangItem := TJSObject(LanguagePack[I]);
LSO := TLanguageStringObject.Create;
LangKey := String(LangItem['Key']);
LangStr := String(LangItem['String']);
LSO.LanguageString := LangStr;
CurrentLanguagePack.AddObject(LangKey,LSO);
End;
MainForm.OnLanguageChange;
Finally
Console.log(TrOut('TDM.SetLanguagePack'));
End;
End;
{---------------------------------------}
Procedure TBaseForm.OnLanguageChange;
Var
I,Ind,
ItemInd : Integer;
Ctrl : TWebControl;
LangStr,
ItemName,
LangID : String;
e : Exception;
Begin
If CurrentLanguage=FFormLanguage then exit;
Console.log(TrIn('TBaseForm.OnLanguageChange',[Self.ClassName]));
Try
Try
// For every control on the form...
For I := 0 to ControlCount-1 do
Begin
Ctrl := Controls[I];
// Skip language checking if the control is not of an allowed class
// or has the Tag set to ControlTagNoLanguageCheck (i.e. 999)
If not (
((Ctrl is TWebLabel) or (Ctrl is TWebButton) or (Ctrl is TWebHTMLDiv) or (Ctrl is TWebComboBox))
and (Ctrl.Tag<>ControlTagNoLanguageCheck)
) then continue;
// If the controls Tag is set to ControlTagShowByLanguage (i.e. 998), then
// the forms HTML file holds an element (tpically a DIV) for each language.
// The IDs of those elements have to be named like this: <normalidname_DE>
// or <normalidname_FR>, i.e. the language-id (e.g. DE, EN, FR) has to be
// attached to the normal ID name, separated by an underscore. If an IDs
// language-id matches the current language, than this element will be set
// visible. All other elements will be set invisible.
If Ctrl.Tag=ControlTagShowByLanguage then
Begin
LangID := RightStr(Ctrl.Name,2);
Ctrl.Visible := (LanguageIDtoTSupportedLanguage(LangID)=CurrentLanguage);
Continue;
End;
// Multiple items for a TWebComboBox have keys in DB like: <control.name>_nnn
If Ctrl is TWebComboBox then
Begin
ItemInd := 1;
ItemName := Ctrl.Name + Format('_%.3d',[ItemInd]);
While CurrentLanguagePack.Find(ItemName,Ind) do
Begin
If ItemInd=1 then TWebComboBox(Ctrl).Clear;
LangStr := TLanguageStringObject(CurrentLanguagePack.Objects[Ind]).LanguageString;
TWebComboBox(Ctrl).AddItem(LangStr,Nil);
ItemInd := ItemInd + 1;
ItemName := Ctrl.Name + Format('_%.3d',[ItemInd]);
End;
If TWebComboBox(Ctrl).Items.Count>0 then
TWebComboBox(Ctrl).ItemIndex := 0;
Continue;
End;
// Search the controls name in the language pack string list
If CurrentLanguagePack.Find(Ctrl.Name,Ind) then
Begin
// If found, set the string in the control
LangStr := TLanguageStringObject(CurrentLanguagePack.Objects[Ind]).LanguageString;
If Ctrl is TWebLabel then with Ctrl as TWebLabel do Caption := LangStr
Else if Ctrl is TWebButton then with Ctrl as TWebButton do Caption := LangStr
Else if Ctrl is TWebHTMLDiv then with Ctrl as TWebHTMLDiv do HTML.Text := LangStr
End
Else
// If not found, leave a warning about a missing language string in the console
Console.warn(Lg('TBaseForm.OnLanguageChange',['Missing: ',Self.ClassName,'.',Ctrl.Name]));
End;
FFormLanguage := CurrentLanguage;
Except
{$IFNDEF WIN32} ASM e = $e; END; {$ENDIF}
Console.error(Err(e,'TBaseForm.OnLanguageChange'));
End;
Finally
Console.log(TrOut('TBaseForm.OnLanguageChange',[Self.ClassName]));
End;
End;
Hope it's useful, Walter
1 Like
Many thanks Walter
Excellent approach of problem, looks like first VCL solutions, decades ago.
Yes, that's me, a decades ago Turbo Pascal 3.0 guy...