|
@@ -0,0 +1,259 @@
|
|
|
+{
|
|
|
+ This file is part of the Pas2JS run time library.
|
|
|
+ Copyright (c) 2019 by Michael Van Canneyt
|
|
|
+
|
|
|
+ See the file COPYING.FPC, included in this distribution,
|
|
|
+ for details about the copyright.
|
|
|
+
|
|
|
+ This program is distributed in the hope that it will be useful,
|
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
+
|
|
|
+ **********************************************************************}
|
|
|
+unit rstranslate;
|
|
|
+
|
|
|
+{$mode objfpc}
|
|
|
+
|
|
|
+interface
|
|
|
+
|
|
|
+uses
|
|
|
+ SysUtils, JS, web;
|
|
|
+
|
|
|
+Type
|
|
|
+
|
|
|
+ { TResourceTranslator }
|
|
|
+ TLoadFailEvent = Reference to Procedure (Sender : TObject; aCode : Integer; aError : String);
|
|
|
+ TOnTranslatedEvent = Reference to Procedure (Sender : TObject; aURL : String);
|
|
|
+
|
|
|
+ TResourceTranslator = Class
|
|
|
+ Private
|
|
|
+ FOnLoadFail: TLoadFailEvent;
|
|
|
+ FOnURLTranslated: TOnTranslatedEvent;
|
|
|
+ class var FInstance : TResourceTranslator;
|
|
|
+ function GetUnitResources(const aUnit: string): TJSOBject;
|
|
|
+ Protected
|
|
|
+ procedure ResetTranslation(aUnitResources: TJSObject; AString: String); virtual;
|
|
|
+ procedure Translate(aUnitResources: TJSObject; AString, aTranslation: String); virtual;
|
|
|
+ Public
|
|
|
+ Class Function Instance : TResourceTranslator;
|
|
|
+ Procedure Translate(Const aUnit,aString,aTranslation : String); overload;
|
|
|
+ Procedure Translate(Const aTranslations : TJSOBject); overload;
|
|
|
+ Procedure ResetTranslation(Const aUnit : String; const aString : String = ''); overload;
|
|
|
+ procedure Translate(const aURL: string; aOnTranslated : TOnTranslatedEvent = Nil); overload;
|
|
|
+ Property OnLoadFail : TLoadFailEvent Read FOnLoadFail Write FOnLoadFail;
|
|
|
+ Property OnURLTranslated : TOnTranslatedEvent Read FOnURLTranslated Write FOnURLTranslated;
|
|
|
+ end;
|
|
|
+
|
|
|
+Function ResourceTranslator : TResourceTranslator;
|
|
|
+Procedure Translate(Const aURL : String; aOnTranslated : TOnTranslatedEvent = Nil);
|
|
|
+Procedure Translate(Const aUnit,aString,aTranslation : String);
|
|
|
+Procedure Translate(Const aTranslations : TJSOBject);
|
|
|
+Procedure ResetTranslation(Const aUnit : String; Const aString : String = '');
|
|
|
+
|
|
|
+implementation
|
|
|
+
|
|
|
+Const
|
|
|
+ SCurrent = 'current';
|
|
|
+
|
|
|
+var
|
|
|
+ Pas : TJSObject; external name 'pas';
|
|
|
+
|
|
|
+{ TResourceTranslator }
|
|
|
+
|
|
|
+
|
|
|
+procedure TResourceTranslator.Translate(aUnitResources: TJSObject; AString, aTranslation: String);
|
|
|
+
|
|
|
+Var
|
|
|
+ res: JSValue;
|
|
|
+
|
|
|
+begin
|
|
|
+ res:=aUnitResources[aString];
|
|
|
+ if Assigned(Res) then
|
|
|
+ TJSOBject(Res)[SCurrent]:=aTranslation;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TResourceTranslator.ResetTranslation(aUnitResources: TJSObject; AString: String);
|
|
|
+
|
|
|
+Var
|
|
|
+ res: JSValue;
|
|
|
+
|
|
|
+begin
|
|
|
+ res:=aUnitResources[aString];
|
|
|
+ if Assigned(Res) then
|
|
|
+ TJSOBject(Res)[SCurrent]:=undefined;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function TResourceTranslator.GetUnitResources(const aUnit: string): TJSOBject;
|
|
|
+
|
|
|
+var
|
|
|
+ jsMod,res : JSValue;
|
|
|
+
|
|
|
+begin
|
|
|
+ Result:=Nil;
|
|
|
+ jsMod:=Pas[aUnit];
|
|
|
+ if assigned(jsMod) then
|
|
|
+ begin
|
|
|
+ res:=(TJSObject(jsMod)['$resourcestrings']);
|
|
|
+ if Assigned(res) then
|
|
|
+ Result:=TJSObject(res);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TResourceTranslator.Translate(const aTranslations: TJSOBject);
|
|
|
+
|
|
|
+var
|
|
|
+ aUnitName,aStringName : String;
|
|
|
+ aUnit,Res : TJSObject;
|
|
|
+ V : JSValue;
|
|
|
+
|
|
|
+begin
|
|
|
+ for aUnitName in TJSObject.getOwnPropertyNames(aTranslations) do
|
|
|
+ if IsValidIdent(aUnitName,True) and isObject(aTranslations[aUnitName]) then
|
|
|
+ begin
|
|
|
+ aUnit:=TJSObject(aTranslations[aUnitName]);
|
|
|
+ Res:=GetUnitResources(aUnitName);
|
|
|
+ if Assigned(Res) then
|
|
|
+ For aStringName in TJSObject.getOwnPropertyNames(aUnit) do
|
|
|
+ begin
|
|
|
+ V:=aUnit[aStringName];
|
|
|
+ if IsString(V) then
|
|
|
+ Translate(Res,aStringName,String(V));
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TResourceTranslator.Translate(const aUnit, aString, aTranslation: String);
|
|
|
+
|
|
|
+Var
|
|
|
+ jsmod : TJSObject;
|
|
|
+
|
|
|
+begin
|
|
|
+ jsMod:=GetUnitResources(aUnit);
|
|
|
+ if Assigned(jsMod) then
|
|
|
+ Translate(jsMod, aString,aTranslation);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TResourceTranslator.ResetTranslation(const aUnit: String; const aString: String);
|
|
|
+
|
|
|
+Var
|
|
|
+ jsmod : TJSObject;
|
|
|
+ S : String;
|
|
|
+
|
|
|
+begin
|
|
|
+ jsMod:=GetUnitResources(aUnit);
|
|
|
+ if Assigned(jsMod) then
|
|
|
+ if (aString<>'') then
|
|
|
+ ResetTranslation(jsMod, aString)
|
|
|
+ else
|
|
|
+ for S in TJSOBject.getOwnPropertyNames(TJSObject(jsMod)) do
|
|
|
+ ResetTranslation(jsMod, S);
|
|
|
+end;
|
|
|
+
|
|
|
+Type
|
|
|
+
|
|
|
+ { TURLTranslator }
|
|
|
+
|
|
|
+ TURLTranslator = Class
|
|
|
+ Private
|
|
|
+ FTranslator : TResourceTranslator;
|
|
|
+ FURL : String;
|
|
|
+ FXHR : TJSXMLHttpRequest;
|
|
|
+ FOnTranslated : TOnTranslatedEvent;
|
|
|
+ procedure DoStateChange;
|
|
|
+ Public
|
|
|
+ Constructor Create(aUrl : String; ATranslator : TResourceTranslator;aOnTranslated : TOnTranslatedEvent);
|
|
|
+ Procedure Translate;
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TURLTranslator }
|
|
|
+
|
|
|
+procedure TURLTranslator.DoStateChange;
|
|
|
+
|
|
|
+Var
|
|
|
+ O : TJSObject;
|
|
|
+
|
|
|
+begin
|
|
|
+ if (FXHR.ReadyState=TJSXMLHttpRequest.DONE) then
|
|
|
+ if ((FXHR.Status div 100)=2) then
|
|
|
+ begin
|
|
|
+ try
|
|
|
+ O:=TJSJSON.parseObject(FXHR.responseText);
|
|
|
+ FTranslator.Translate(O);
|
|
|
+ if Assigned(FOnTranslated) then
|
|
|
+ FOnTranslated(FTranslator,FURL);
|
|
|
+ if Assigned(FTranslator.OnURLTranslated) then
|
|
|
+ FTranslator.OnURLTranslated(FTranslator,FURL);
|
|
|
+ except
|
|
|
+ if Assigned(FTranslator.OnLoadFail) then
|
|
|
+ FTranslator.OnLoadFail(FTranslator,0,'Invalid JSON')
|
|
|
+ end
|
|
|
+ end
|
|
|
+ else
|
|
|
+ if Assigned(FTranslator.OnLoadFail) then
|
|
|
+ FTranslator.OnLoadFail(FTranslator,FXHR.Status,FXHR.StatusText);
|
|
|
+end;
|
|
|
+
|
|
|
+constructor TURLTranslator.Create(aUrl: String; ATranslator: TResourceTranslator;aOnTranslated : TOnTranslatedEvent);
|
|
|
+begin
|
|
|
+ FURL:=aURL;
|
|
|
+ FTranslator:=ATranslator;
|
|
|
+ FOnTranslated:=aOnTranslated;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TURLTranslator.Translate;
|
|
|
+begin
|
|
|
+ FXHR:=TJSXMLHttpRequest.new;
|
|
|
+ FXHR.open('GET',fURL);
|
|
|
+ FXHR.onreadystatechange:=@DoStateChange;
|
|
|
+ FXHR.responseType:='text';
|
|
|
+ FXHR.send;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TResourceTranslator.Translate(const aURL : string;aOnTranslated : TOnTranslatedEvent = Nil);
|
|
|
+
|
|
|
+begin
|
|
|
+ With TURLTranslator.Create(aURL,Self,aOnTranslated) do
|
|
|
+ Translate;
|
|
|
+end;
|
|
|
+
|
|
|
+class function TResourceTranslator.Instance: TResourceTranslator;
|
|
|
+begin
|
|
|
+ if FInstance=Nil then
|
|
|
+ FInstance:=TResourceTranslator.Create;
|
|
|
+ Result:=FInstance;
|
|
|
+end;
|
|
|
+
|
|
|
+{ ---------------------------------------------------------------------
|
|
|
+ Procedural access
|
|
|
+ ---------------------------------------------------------------------}
|
|
|
+
|
|
|
+Procedure Translate(Const aURL : String; aOnTranslated : TOnTranslatedEvent = Nil);
|
|
|
+
|
|
|
+begin
|
|
|
+ TResourceTranslator.Instance.Translate(aURL,aOnTranslated);
|
|
|
+end;
|
|
|
+
|
|
|
+Procedure Translate(Const aTranslations : TJSOBject);
|
|
|
+
|
|
|
+begin
|
|
|
+ TResourceTranslator.Instance.Translate(aTranslations);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure Translate(const aUnit, aString, aTranslation: String);
|
|
|
+begin
|
|
|
+ TResourceTranslator.Instance.Translate(aUnit,aString,aTranslation);
|
|
|
+end;
|
|
|
+
|
|
|
+Procedure ResetTranslation(Const aUnit : String; Const aString : String = '');
|
|
|
+begin
|
|
|
+ TResourceTranslator.Instance.ResetTranslation(aUnit,Astring);
|
|
|
+end;
|
|
|
+
|
|
|
+Function ResourceTranslator : TResourceTranslator;
|
|
|
+begin
|
|
|
+ Result:=TResourceTranslator.Instance;
|
|
|
+end;
|
|
|
+
|
|
|
+end.
|
|
|
+
|