123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- {
- 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.
|