rstranslate.pp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. {
  2. This file is part of the Pas2JS run time library.
  3. Copyright (c) 2019 by Michael Van Canneyt
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit rstranslate;
  11. {$mode objfpc}
  12. interface
  13. uses
  14. SysUtils, JS, web;
  15. Type
  16. { TResourceTranslator }
  17. TLoadFailEvent = Reference to Procedure (Sender : TObject; aCode : Integer; aError : String);
  18. TOnTranslatedEvent = Reference to Procedure (Sender : TObject; aURL : String);
  19. TResourceTranslator = Class
  20. Private
  21. FOnLoadFail: TLoadFailEvent;
  22. FOnURLTranslated: TOnTranslatedEvent;
  23. class var FInstance : TResourceTranslator;
  24. function GetUnitResources(const aUnit: string): TJSOBject;
  25. Protected
  26. procedure ResetTranslation(aUnitResources: TJSObject; AString: String); virtual;
  27. procedure Translate(aUnitResources: TJSObject; AString, aTranslation: String); virtual;
  28. Public
  29. Class Function Instance : TResourceTranslator;
  30. Procedure Translate(Const aUnit,aString,aTranslation : String); overload;
  31. Procedure Translate(Const aTranslations : TJSOBject); overload;
  32. Procedure ResetTranslation(Const aUnit : String; const aString : String = ''); overload;
  33. procedure Translate(const aURL: string; aOnTranslated : TOnTranslatedEvent = Nil); overload;
  34. Property OnLoadFail : TLoadFailEvent Read FOnLoadFail Write FOnLoadFail;
  35. Property OnURLTranslated : TOnTranslatedEvent Read FOnURLTranslated Write FOnURLTranslated;
  36. end;
  37. Function ResourceTranslator : TResourceTranslator;
  38. Procedure Translate(Const aURL : String; aOnTranslated : TOnTranslatedEvent = Nil);
  39. Procedure Translate(Const aUnit,aString,aTranslation : String);
  40. Procedure Translate(Const aTranslations : TJSOBject);
  41. Procedure ResetTranslation(Const aUnit : String; Const aString : String = '');
  42. implementation
  43. Const
  44. SCurrent = 'current';
  45. var
  46. Pas : TJSObject; external name 'pas';
  47. { TResourceTranslator }
  48. procedure TResourceTranslator.Translate(aUnitResources: TJSObject; AString, aTranslation: String);
  49. Var
  50. res: JSValue;
  51. begin
  52. res:=aUnitResources[aString];
  53. if Assigned(Res) then
  54. TJSOBject(Res)[SCurrent]:=aTranslation;
  55. end;
  56. procedure TResourceTranslator.ResetTranslation(aUnitResources: TJSObject; AString: String);
  57. Var
  58. res: JSValue;
  59. begin
  60. res:=aUnitResources[aString];
  61. if Assigned(Res) then
  62. TJSOBject(Res)[SCurrent]:=undefined;
  63. end;
  64. function TResourceTranslator.GetUnitResources(const aUnit: string): TJSOBject;
  65. var
  66. jsMod,res : JSValue;
  67. begin
  68. Result:=Nil;
  69. jsMod:=Pas[aUnit];
  70. if assigned(jsMod) then
  71. begin
  72. res:=(TJSObject(jsMod)['$resourcestrings']);
  73. if Assigned(res) then
  74. Result:=TJSObject(res);
  75. end;
  76. end;
  77. procedure TResourceTranslator.Translate(const aTranslations: TJSOBject);
  78. var
  79. aUnitName,aStringName : String;
  80. aUnit,Res : TJSObject;
  81. V : JSValue;
  82. begin
  83. for aUnitName in TJSObject.getOwnPropertyNames(aTranslations) do
  84. if IsValidIdent(aUnitName,True) and isObject(aTranslations[aUnitName]) then
  85. begin
  86. aUnit:=TJSObject(aTranslations[aUnitName]);
  87. Res:=GetUnitResources(aUnitName);
  88. if Assigned(Res) then
  89. For aStringName in TJSObject.getOwnPropertyNames(aUnit) do
  90. begin
  91. V:=aUnit[aStringName];
  92. if IsString(V) then
  93. Translate(Res,aStringName,String(V));
  94. end;
  95. end;
  96. end;
  97. procedure TResourceTranslator.Translate(const aUnit, aString, aTranslation: String);
  98. Var
  99. jsmod : TJSObject;
  100. begin
  101. jsMod:=GetUnitResources(aUnit);
  102. if Assigned(jsMod) then
  103. Translate(jsMod, aString,aTranslation);
  104. end;
  105. procedure TResourceTranslator.ResetTranslation(const aUnit: String; const aString: String);
  106. Var
  107. jsmod : TJSObject;
  108. S : String;
  109. begin
  110. jsMod:=GetUnitResources(aUnit);
  111. if Assigned(jsMod) then
  112. if (aString<>'') then
  113. ResetTranslation(jsMod, aString)
  114. else
  115. for S in TJSOBject.getOwnPropertyNames(TJSObject(jsMod)) do
  116. ResetTranslation(jsMod, S);
  117. end;
  118. Type
  119. { TURLTranslator }
  120. TURLTranslator = Class
  121. Private
  122. FTranslator : TResourceTranslator;
  123. FURL : String;
  124. FXHR : TJSXMLHttpRequest;
  125. FOnTranslated : TOnTranslatedEvent;
  126. procedure DoStateChange;
  127. Public
  128. Constructor Create(aUrl : String; ATranslator : TResourceTranslator;aOnTranslated : TOnTranslatedEvent);
  129. Procedure Translate;
  130. end;
  131. { TURLTranslator }
  132. procedure TURLTranslator.DoStateChange;
  133. Var
  134. O : TJSObject;
  135. begin
  136. if (FXHR.ReadyState=TJSXMLHttpRequest.DONE) then
  137. if ((FXHR.Status div 100)=2) then
  138. begin
  139. try
  140. O:=TJSJSON.parseObject(FXHR.responseText);
  141. FTranslator.Translate(O);
  142. if Assigned(FOnTranslated) then
  143. FOnTranslated(FTranslator,FURL);
  144. if Assigned(FTranslator.OnURLTranslated) then
  145. FTranslator.OnURLTranslated(FTranslator,FURL);
  146. except
  147. if Assigned(FTranslator.OnLoadFail) then
  148. FTranslator.OnLoadFail(FTranslator,0,'Invalid JSON')
  149. end
  150. end
  151. else
  152. if Assigned(FTranslator.OnLoadFail) then
  153. FTranslator.OnLoadFail(FTranslator,FXHR.Status,FXHR.StatusText);
  154. end;
  155. constructor TURLTranslator.Create(aUrl: String; ATranslator: TResourceTranslator;aOnTranslated : TOnTranslatedEvent);
  156. begin
  157. FURL:=aURL;
  158. FTranslator:=ATranslator;
  159. FOnTranslated:=aOnTranslated;
  160. end;
  161. procedure TURLTranslator.Translate;
  162. begin
  163. FXHR:=TJSXMLHttpRequest.new;
  164. FXHR.open('GET',fURL);
  165. FXHR.onreadystatechange:=@DoStateChange;
  166. FXHR.responseType:='text';
  167. FXHR.send;
  168. end;
  169. procedure TResourceTranslator.Translate(const aURL : string;aOnTranslated : TOnTranslatedEvent = Nil);
  170. begin
  171. With TURLTranslator.Create(aURL,Self,aOnTranslated) do
  172. Translate;
  173. end;
  174. class function TResourceTranslator.Instance: TResourceTranslator;
  175. begin
  176. if FInstance=Nil then
  177. FInstance:=TResourceTranslator.Create;
  178. Result:=FInstance;
  179. end;
  180. { ---------------------------------------------------------------------
  181. Procedural access
  182. ---------------------------------------------------------------------}
  183. Procedure Translate(Const aURL : String; aOnTranslated : TOnTranslatedEvent = Nil);
  184. begin
  185. TResourceTranslator.Instance.Translate(aURL,aOnTranslated);
  186. end;
  187. Procedure Translate(Const aTranslations : TJSOBject);
  188. begin
  189. TResourceTranslator.Instance.Translate(aTranslations);
  190. end;
  191. procedure Translate(const aUnit, aString, aTranslation: String);
  192. begin
  193. TResourceTranslator.Instance.Translate(aUnit,aString,aTranslation);
  194. end;
  195. Procedure ResetTranslation(Const aUnit : String; Const aString : String = '');
  196. begin
  197. TResourceTranslator.Instance.ResetTranslation(aUnit,Astring);
  198. end;
  199. Function ResourceTranslator : TResourceTranslator;
  200. begin
  201. Result:=TResourceTranslator.Instance;
  202. end;
  203. end.