SubtitleTranslate - tmt.as 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /*
  2. real time subtitle translate for PotPlayer using Tencent Machine Translation API
  3. https://github.com/BlackGlory/subtitle-translate-tmt
  4. https://cloud.tencent.com/product/tmt
  5. */
  6. // string GetTitle() -> get title for UI
  7. // string GetVersion -> get version for manage
  8. // string GetDesc() -> get detail information
  9. // string GetLoginTitle() -> get title for login dialog
  10. // string GetLoginDesc() -> get desc for login dialog
  11. // string GetUserText() -> get user text for login dialog
  12. // string GetPasswordText() -> get password text for login dialog
  13. // string ServerLogin(string User, string Pass) -> login
  14. // string ServerLogout() -> logout
  15. // array<string> GetSrcLangs() -> get source language
  16. // array<string> GetDstLangs() -> get target language
  17. // string Translate(string Text, string &in SrcLang, string &in DstLang) -> do translate !!
  18. bool debug = false;
  19. string secretId = '';
  20. string secretKey = '';
  21. uint secondsOfMinute = 60;
  22. uint secondsOfHour = 3600;
  23. uint secondsOfDay = 86400;
  24. // https://cloud.tencent.com/document/api/551/15619
  25. dictionary DstLangTable = {
  26. {'zh', 'zh'} // 中文
  27. , {'zh-CN', 'zh'} // 简体中文
  28. , {'zh-TW', 'zh'} // 繁体中文
  29. , {'en', 'en'} // 英文
  30. , {'ja', 'jp'} // 日语
  31. , {'ko', 'kr'} // 韩语
  32. , {'de', 'de'} // 德语
  33. , {'fr', 'fr'} // 法语
  34. , {'es', 'es'} // 西班牙文
  35. , {'it', 'it'} // 意大利文
  36. , {'tr', 'tr'} // 土耳其文
  37. , {'ru', 'ru'} // 俄文
  38. , {'pt', 'pt'} // 葡萄牙文
  39. , {'vi', 'vi'} // 越南文
  40. , {'id', 'id'} // 印度尼西亚文
  41. , {'ms', 'ms'} // 马来西亚文
  42. , {'th', 'th' } // 泰文
  43. };
  44. dictionary SrcLangTable = {
  45. {'', 'auto'} // 自动检测
  46. , {'zh', 'zh'} // 中文
  47. , {'zh-CN', 'zh'} // 简体中文
  48. , {'zh-TW', 'zh'} // 繁体中文
  49. , {'en', 'en'} // 英文
  50. , {'ja', 'jp'} // 日语
  51. , {'ko', 'kr'} // 韩语
  52. , {'de', 'de'} // 德语
  53. , {'fr', 'fr'} // 法语
  54. , {'es', 'es'} // 西班牙文
  55. , {'it', 'it'} // 意大利文
  56. , {'tr', 'tr'} // 土耳其文
  57. , {'ru', 'ru'} // 俄文
  58. , {'pt', 'pt'} // 葡萄牙文
  59. , {'vi', 'vi'} // 越南文
  60. , {'id', 'id'} // 印度尼西亚文
  61. , {'ms', 'ms'} // 马来西亚文
  62. , {'th', 'th' } // 泰文
  63. };
  64. uint getTimestamp() {
  65. datetime fakeUnix = datetime(1970, 1, 2, 0, 0, 0); // datetime(1970, 1, 1) may an invalid value.
  66. datetime now = datetime();
  67. uint timestamp = now - fakeUnix;
  68. timestamp += secondsOfDay; // patch for fakeUnix.
  69. return timestamp;
  70. }
  71. string createQuerystring(dictionary query) {
  72. array<string> keys = query.getKeys();
  73. keys.sortAsc();
  74. uint length = keys.length();
  75. array<string> pairs(length);
  76. for (uint i = 0; i < length; i++) {
  77. string key = keys[i];
  78. string value = string(query[key]);
  79. pairs[i] = key + '=' + value;
  80. }
  81. string querystring = join(pairs, '&');
  82. return querystring;
  83. }
  84. // for debug
  85. /*
  86. void printHex(string str) {
  87. string hexStr = '';
  88. for (uint i = 0; i < str.length(); i++) {
  89. hexStr += formatInt(str[i], 'H') + ' ';
  90. }
  91. HostPrintUTF8(hexStr);
  92. }
  93. */
  94. string createChar(uint bytechar) {
  95. string result = '';
  96. result.resize(1);
  97. result[0] = bytechar;
  98. return result;
  99. }
  100. string repeat(string str, uint times) {
  101. string result = '';
  102. for (uint i = 0; i < times; i++) {
  103. result += str;
  104. }
  105. return result;
  106. }
  107. string xorStr(string leftStr, string rightStr) {
  108. string result = '';
  109. result.resize(leftStr.length());
  110. for (uint i = 0, length = leftStr.length(); i < length; i++) {
  111. result[i] = leftStr[i] ^ rightStr[i];
  112. }
  113. return result;
  114. }
  115. string hex2bin(string hexStr) {
  116. uint resultLength = hexStr.length() / 2;
  117. string result = '';
  118. result.resize(resultLength);
  119. for (uint i = 0; i < resultLength; i++) {
  120. result[i] = parseInt(hexStr.substr(i * 2, 2), 16);
  121. }
  122. return result;
  123. }
  124. string hmacSHA1(string key, string message) {
  125. uint blockSize = 64;
  126. if (key.length() > blockSize) {
  127. key = HostHashSHA1(key);
  128. }
  129. if (key.length() < blockSize) {
  130. key += repeat(createChar(0x00), blockSize - key.length());
  131. }
  132. string ipadKey = xorStr(repeat(createChar(0x36), blockSize), key);
  133. string opadKey = xorStr(repeat(createChar(0x5c), blockSize), key);
  134. return HostHashSHA1(opadKey + hex2bin(HostHashSHA1(ipadKey + message)));
  135. }
  136. // https://cloud.tencent.com/document/api/213/15693
  137. string createSignature(string querystring, string host, string method = 'GET', string path = '/') {
  138. return HostBase64Enc(hex2bin(hmacSHA1(secretKey, method + host + path + '?' + querystring)));
  139. }
  140. JsonValue parseJSON(string json) {
  141. JsonReader reader;
  142. JsonValue data;
  143. reader.parse(json, data);
  144. return data;
  145. }
  146. string replace(string str, string substr, string newSubstr) {
  147. array<string> arr = str.split(substr);
  148. string result = join(arr, newSubstr);
  149. return result;
  150. }
  151. string GetTitle() {
  152. return
  153. '{$CP936=腾讯机器翻译$}'
  154. '{$CP0=Tencent Machine Translate$}';
  155. }
  156. string GetVersion() {
  157. return '1';
  158. }
  159. string GetDesc() {
  160. return
  161. '<a href="https://github.com/BlackGlory/subtitle-translate-tmt">'
  162. 'Extension Source Code'
  163. '</a>'
  164. ' '
  165. '<a href="https://cloud.tencent.com/product/tmt">'
  166. 'About TMT'
  167. '</a>';
  168. }
  169. string GetLoginTitle() {
  170. return
  171. '{$CP936=填写 API 密钥$}'
  172. '{$CP0=Input Tencent Cloud API key$}';
  173. }
  174. string GetLoginDesc() {
  175. return 'https://console.cloud.tencent.com/cam/capi';
  176. }
  177. string GetUserText() {
  178. return 'SecretId:';
  179. }
  180. string GetPasswordText() {
  181. return 'SecretKey:';
  182. }
  183. string ServerLogin(string user, string pass) {
  184. if (user.empty() || pass.empty()) {
  185. return 'fail';
  186. }
  187. secretId = user;
  188. secretKey = pass;
  189. return '200 ok';
  190. }
  191. void ServerLogout() {
  192. secretKey = '';
  193. secretId = '';
  194. }
  195. array<string> GetSrcLangs() {
  196. array<string> ret = SrcLangTable.getKeys();
  197. return ret;
  198. }
  199. array<string> GetDstLangs() {
  200. array<string> ret = DstLangTable.getKeys();
  201. return ret;
  202. }
  203. string Translate(string text, string &in srcLang, string &in dstLang) {
  204. if (debug) HostOpenConsole();
  205. dictionary query = {
  206. {'Action', 'TextTranslate'}
  207. , {'Version', '2018-03-21'}
  208. , {'Region', 'ap-shanghai'}
  209. , {'Timestamp', formatInt(getTimestamp())}
  210. , {'Nonce', formatInt(HostGetTickCount())}
  211. , {'SecretId', secretId}
  212. , {'SourceText', text}
  213. , {'Source', string(SrcLangTable[srcLang])}
  214. , {'Target', string(DstLangTable[dstLang])}
  215. , {'ProjectId', formatInt(0)}
  216. };
  217. string signature = createSignature(createQuerystring(query), 'tmt.tencentcloudapi.com');
  218. query['SourceText'] = HostUrlEncode(string(query['SourceText']));
  219. string querystring = createQuerystring(query);
  220. string url = 'https://tmt.tencentcloudapi.com/?' + querystring + '&Signature=' + HostUrlEncode(signature);
  221. string json = HostUrlGetString(url);
  222. JsonValue data = parseJSON(json);
  223. if (data.isObject()) {
  224. JsonValue response = data['Response'];
  225. if (response.isObject()) {
  226. JsonValue targetText = response['TargetText'];
  227. if (targetText.isString()) {
  228. string translatedText = replace(targetText.asString(), '*', '\n');
  229. if (debug) HostPrintUTF8(string(SrcLangTable[srcLang]) + '=>' + string(DstLangTable[dstLang]));
  230. if (debug) HostPrintUTF8(text + '\n=>\n' + translatedText);
  231. srcLang = 'UTF8';
  232. dstLang = 'UTF8';
  233. return translatedText;
  234. }
  235. if (debug) HostPrintUTF8(json);
  236. }
  237. }
  238. return '';
  239. }