├── .gitignore ├── LICENSE ├── README.md ├── rime ├── lua │ ├── c2e.lua │ ├── c2etrigger.lua │ ├── e2c.lua │ ├── e2ctrigger.lua │ ├── google.lua │ ├── google_trigger.lua │ └── json.lua └── rime.lua ├── squirrel └── simplehttp.so └── weasel └── simplehttp.dll /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Lua sources 2 | luac.out 3 | 4 | # luarocks build files 5 | *.src.rock 6 | *.zip 7 | *.tar.gz 8 | 9 | # Object files 10 | *.o 11 | *.os 12 | *.ko 13 | *.obj 14 | *.elf 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Libraries 21 | *.lib 22 | *.a 23 | *.la 24 | *.lo 25 | *.def 26 | *.exp 27 | 28 | # Shared objects (inc. Windows DLLs) 29 | *.dll 30 | *.so 31 | *.so.* 32 | *.dylib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | *.i*86 39 | *.x86_64 40 | *.hex 41 | 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 JACKCHAN000 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rime-Lua-GoogleTranslate 2 | GoogleTranslate in Rime輸入法 3 | 4 | Based On https://github.com/hchunhui/librime-cloud 5 | 6 | 中譯英: 7 | 8 | ![final_606b23cc785d7e003d750948_420746](https://user-images.githubusercontent.com/61930699/113588017-3419ce80-9662-11eb-8ce6-51e6443a32e8.gif) 9 | 10 | 11 | 英譯中: 12 | 13 | ![final_606b23148efa0600b740d680_363311](https://user-images.githubusercontent.com/61930699/113589246-b8b91c80-9663-11eb-8458-2312e69cfd92.gif) 14 | 15 | 16 | Google搜尋建議: 17 | 18 | ![final_626416ddcb2ed0006f470b0b_867555](https://user-images.githubusercontent.com/61930699/164912081-84caa354-d4a3-4d39-85ef-a84a1a33731e.gif) 19 | 20 | 21 | How to install 22 | 1. Windows: Copy all files in ```weasel``` to the program folder of rime 23 | 24 | Mac: Copy all files in ```squirrel``` to the program folder of rime```/Library/Input Methods/Squirrel.app/Contents/SharedSupport/``` 25 | 2. Edit the path of c2e.lua and c2etrigger.lua to your path 26 | 3. Copy all files in ```rime``` to your user folder of rime 27 | 4. Add ```lua_processor@xxx_processor, lua_translator@xxx_translator``` to your schema file 28 | 5. Enjoy 29 | 30 | 31 | How to use 32 | 33 | Trigger:``` 34 | 中譯英:Control+t 35 | 英譯中:Control+e 36 | Google搜尋建議:Control+g``` 37 | 1. Type the input 38 | 2. Activate the trigger 39 | 3. Return a translate on the candidate bar 40 | -------------------------------------------------------------------------------- /rime/lua/c2e.lua: -------------------------------------------------------------------------------- 1 | local json = require("json") 2 | local http = require("simplehttp") 3 | 4 | local function escape(s) 5 | return (string.gsub(s, "([^A-Za-z0-9_])", function(c) 6 | return string.format("%%%02x", string.byte(c)) 7 | end)) 8 | end 9 | 10 | local function make_url(input) 11 | local sl = "zh_TW" 12 | local tl = "en" 13 | return 'http://translate.googleapis.com/translate_a/single?client=gtx&sl='.. sl ..'&tl='.. tl ..'&dt=t&q='.. escape(input) 14 | end 15 | 16 | 17 | 18 | local function translator(input, seg, env) 19 | local string = env.focus_text 20 | local reply = http.request(make_url(string)) 21 | local data = json.decode(reply) 22 | 23 | for i, v in ipairs(data) do 24 | -- get the output string 25 | local output = v[1][1] 26 | local c = Candidate("translate", seg.start, seg._end, output, "翻譯") 27 | -- add to Candidate 28 | yield(c) 29 | end 30 | end 31 | 32 | return translator 33 | -------------------------------------------------------------------------------- /rime/lua/c2etrigger.lua: -------------------------------------------------------------------------------- 1 | local function make(trig_key, trig_translator) 2 | local flag = false 3 | local focus_text = nil 4 | 5 | 6 | local function processor(key, env) 7 | local kAccepted = 1 8 | local kNoop = 2 9 | local engine = env.engine 10 | local context = engine.context 11 | 12 | if key:repr() == trig_key then 13 | if context:is_composing() then 14 | focus_text = context:get_commit_text() 15 | flag = true 16 | context:refresh_non_confirmed_composition() 17 | return kAccepted 18 | end 19 | end 20 | 21 | return kNoop 22 | end 23 | 24 | local function translator(input, seg, env) 25 | if flag then 26 | flag = false 27 | env.focus_text = focus_text 28 | trig_translator(input, seg, env) 29 | end 30 | end 31 | 32 | return { 33 | processor = processor, 34 | translator = translator 35 | } 36 | end 37 | 38 | return make -------------------------------------------------------------------------------- /rime/lua/e2c.lua: -------------------------------------------------------------------------------- 1 | local json = require("json") 2 | local http = require("simplehttp") 3 | 4 | local function escape(s) 5 | return (string.gsub(s, "([^A-Za-z0-9_])", function(c) 6 | return string.format("%%%02x", string.byte(c)) 7 | end)) 8 | end 9 | 10 | local function make_url(input) 11 | local sl = "en" 12 | local tl = "zh_TW" 13 | return 'http://translate.googleapis.com/translate_a/single?client=gtx&sl='.. sl ..'&tl='.. tl ..'&dt=t&q='.. escape(input) 14 | end 15 | 16 | local function translator(input, seg) 17 | local context = input 18 | -- 'as space key 19 | local string = context:gsub("%'", " ") 20 | 21 | local reply = http.request(make_url(string)) 22 | local data = json.decode(reply) 23 | 24 | for i, v in ipairs(data) do 25 | -- get the output string 26 | local output = v[1][1] 27 | local c = Candidate("translate", seg.start, seg._end, output, "翻譯") 28 | -- add to Candidate 29 | yield(c) 30 | yield(Candidate("translate", seg.start, seg._end, string, "原文")) 31 | end 32 | end 33 | 34 | return translator 35 | -------------------------------------------------------------------------------- /rime/lua/e2ctrigger.lua: -------------------------------------------------------------------------------- 1 | local function make(trig_key, trig_translator) 2 | local flag = false 3 | 4 | local function processor(key, env) 5 | local kAccepted = 1 6 | local kNoop = 2 7 | local engine = env.engine 8 | local context = engine.context 9 | 10 | if key:repr() == trig_key then 11 | if context:is_composing() then 12 | flag = true 13 | context:refresh_non_confirmed_composition() 14 | return kAccepted 15 | end 16 | end 17 | 18 | return kNoop 19 | end 20 | 21 | local function translator(input, seg, env) 22 | if flag then 23 | flag = false 24 | trig_translator(input, seg, env) 25 | end 26 | end 27 | 28 | return { processor = processor, translator = translator } 29 | end 30 | 31 | return make 32 | -------------------------------------------------------------------------------- /rime/lua/google.lua: -------------------------------------------------------------------------------- 1 | local json = require("json") 2 | local http = require("simplehttp") 3 | 4 | local function escape(s) 5 | return (string.gsub(s, "([^A-Za-z0-9_])", function(c) 6 | return string.format("%%%02x", string.byte(c)) 7 | end)) 8 | end 9 | 10 | local function translator(input, seg, env) 11 | local string = env.focus_text 12 | local reply, code = http.request('http://suggestqueries.google.com/complete/search?output=firefox&q=' .. escape(string)) 13 | local data = json.decode(reply) 14 | output_list = data[2] 15 | output_length = #output_list 16 | for i = 1, output_length do 17 | -- add to Candidate 18 | local c = Candidate("translate", seg.start, seg._end, output_list[i], "建議") 19 | yield(c) 20 | end 21 | end 22 | 23 | return translator -------------------------------------------------------------------------------- /rime/lua/google_trigger.lua: -------------------------------------------------------------------------------- 1 | local function make(trig_key, trig_translator) 2 | local flag = false 3 | local focus_text = nil 4 | 5 | 6 | local function processor(key, env) 7 | local kAccepted = 1 8 | local kNoop = 2 9 | local engine = env.engine 10 | local context = engine.context 11 | 12 | if key:repr() == trig_key then 13 | if context:is_composing() then 14 | focus_text = context:get_commit_text() 15 | flag = true 16 | context:refresh_non_confirmed_composition() 17 | return kAccepted 18 | end 19 | end 20 | 21 | return kNoop 22 | end 23 | 24 | local function translator(input, seg, env) 25 | if flag then 26 | flag = false 27 | env.focus_text = focus_text 28 | trig_translator(input, seg, env) 29 | end 30 | end 31 | 32 | return { 33 | processor = processor, 34 | translator = translator 35 | } 36 | end 37 | 38 | return make -------------------------------------------------------------------------------- /rime/lua/json.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- json.lua 3 | -- 4 | -- Copyright (c) 2018 rxi 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | -- this software and associated documentation files (the "Software"), to deal in 8 | -- the Software without restriction, including without limitation the rights to 9 | -- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 10 | -- of the Software, and to permit persons to whom the Software is furnished to do 11 | -- so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in all 14 | -- copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | -- SOFTWARE. 23 | -- 24 | 25 | local json = { _version = "0.1.1" } 26 | 27 | ------------------------------------------------------------------------------- 28 | -- Encode 29 | ------------------------------------------------------------------------------- 30 | 31 | local encode 32 | 33 | local escape_char_map = { 34 | [ "\\" ] = "\\\\", 35 | [ "\"" ] = "\\\"", 36 | [ "\b" ] = "\\b", 37 | [ "\f" ] = "\\f", 38 | [ "\n" ] = "\\n", 39 | [ "\r" ] = "\\r", 40 | [ "\t" ] = "\\t", 41 | } 42 | 43 | local escape_char_map_inv = { [ "\\/" ] = "/" } 44 | for k, v in pairs(escape_char_map) do 45 | escape_char_map_inv[v] = k 46 | end 47 | 48 | 49 | local function escape_char(c) 50 | return escape_char_map[c] or string.format("\\u%04x", c:byte()) 51 | end 52 | 53 | 54 | local function encode_nil(val) 55 | return "null" 56 | end 57 | 58 | 59 | local function encode_table(val, stack) 60 | local res = {} 61 | stack = stack or {} 62 | 63 | -- Circular reference? 64 | if stack[val] then error("circular reference") end 65 | 66 | stack[val] = true 67 | 68 | if val[1] ~= nil or next(val) == nil then 69 | -- Treat as array -- check keys are valid and it is not sparse 70 | local n = 0 71 | for k in pairs(val) do 72 | if type(k) ~= "number" then 73 | error("invalid table: mixed or invalid key types") 74 | end 75 | n = n + 1 76 | end 77 | if n ~= #val then 78 | error("invalid table: sparse array") 79 | end 80 | -- Encode 81 | for i, v in ipairs(val) do 82 | table.insert(res, encode(v, stack)) 83 | end 84 | stack[val] = nil 85 | return "[" .. table.concat(res, ",") .. "]" 86 | 87 | else 88 | -- Treat as an object 89 | for k, v in pairs(val) do 90 | if type(k) ~= "string" then 91 | error("invalid table: mixed or invalid key types") 92 | end 93 | table.insert(res, encode(k, stack) .. ":" .. encode(v, stack)) 94 | end 95 | stack[val] = nil 96 | return "{" .. table.concat(res, ",") .. "}" 97 | end 98 | end 99 | 100 | 101 | local function encode_string(val) 102 | return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"' 103 | end 104 | 105 | 106 | local function encode_number(val) 107 | -- Check for NaN, -inf and inf 108 | if val ~= val or val <= -math.huge or val >= math.huge then 109 | error("unexpected number value '" .. tostring(val) .. "'") 110 | end 111 | return string.format("%.14g", val) 112 | end 113 | 114 | 115 | local type_func_map = { 116 | [ "nil" ] = encode_nil, 117 | [ "table" ] = encode_table, 118 | [ "string" ] = encode_string, 119 | [ "number" ] = encode_number, 120 | [ "boolean" ] = tostring, 121 | } 122 | 123 | 124 | encode = function(val, stack) 125 | local t = type(val) 126 | local f = type_func_map[t] 127 | if f then 128 | return f(val, stack) 129 | end 130 | error("unexpected type '" .. t .. "'") 131 | end 132 | 133 | 134 | function json.encode(val) 135 | return ( encode(val) ) 136 | end 137 | 138 | 139 | ------------------------------------------------------------------------------- 140 | -- Decode 141 | ------------------------------------------------------------------------------- 142 | 143 | local parse 144 | 145 | local function create_set(...) 146 | local res = {} 147 | for i = 1, select("#", ...) do 148 | res[ select(i, ...) ] = true 149 | end 150 | return res 151 | end 152 | 153 | local space_chars = create_set(" ", "\t", "\r", "\n") 154 | local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") 155 | local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") 156 | local literals = create_set("true", "false", "null") 157 | 158 | local literal_map = { 159 | [ "true" ] = true, 160 | [ "false" ] = false, 161 | [ "null" ] = nil, 162 | } 163 | 164 | 165 | local function next_char(str, idx, set, negate) 166 | for i = idx, #str do 167 | if set[str:sub(i, i)] ~= negate then 168 | return i 169 | end 170 | end 171 | return #str + 1 172 | end 173 | 174 | 175 | local function decode_error(str, idx, msg) 176 | local line_count = 1 177 | local col_count = 1 178 | for i = 1, idx - 1 do 179 | col_count = col_count + 1 180 | if str:sub(i, i) == "\n" then 181 | line_count = line_count + 1 182 | col_count = 1 183 | end 184 | end 185 | error( string.format("%s at line %d col %d", msg, line_count, col_count) ) 186 | end 187 | 188 | 189 | local function codepoint_to_utf8(n) 190 | -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa 191 | local f = math.floor 192 | if n <= 0x7f then 193 | return string.char(n) 194 | elseif n <= 0x7ff then 195 | return string.char(f(n / 64) + 192, n % 64 + 128) 196 | elseif n <= 0xffff then 197 | return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128) 198 | elseif n <= 0x10ffff then 199 | return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, 200 | f(n % 4096 / 64) + 128, n % 64 + 128) 201 | end 202 | error( string.format("invalid unicode codepoint '%x'", n) ) 203 | end 204 | 205 | 206 | local function parse_unicode_escape(s) 207 | local n1 = tonumber( s:sub(3, 6), 16 ) 208 | local n2 = tonumber( s:sub(9, 12), 16 ) 209 | -- Surrogate pair? 210 | if n2 then 211 | return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) 212 | else 213 | return codepoint_to_utf8(n1) 214 | end 215 | end 216 | 217 | 218 | local function parse_string(str, i) 219 | local has_unicode_escape = false 220 | local has_surrogate_escape = false 221 | local has_escape = false 222 | local last 223 | for j = i + 1, #str do 224 | local x = str:byte(j) 225 | 226 | if x < 32 then 227 | decode_error(str, j, "control character in string") 228 | end 229 | 230 | if last == 92 then -- "\\" (escape char) 231 | if x == 117 then -- "u" (unicode escape sequence) 232 | local hex = str:sub(j + 1, j + 5) 233 | if not hex:find("%x%x%x%x") then 234 | decode_error(str, j, "invalid unicode escape in string") 235 | end 236 | if hex:find("^[dD][89aAbB]") then 237 | has_surrogate_escape = true 238 | else 239 | has_unicode_escape = true 240 | end 241 | else 242 | local c = string.char(x) 243 | if not escape_chars[c] then 244 | decode_error(str, j, "invalid escape char '" .. c .. "' in string") 245 | end 246 | has_escape = true 247 | end 248 | last = nil 249 | 250 | elseif x == 34 then -- '"' (end of string) 251 | local s = str:sub(i + 1, j - 1) 252 | if has_surrogate_escape then 253 | s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape) 254 | end 255 | if has_unicode_escape then 256 | s = s:gsub("\\u....", parse_unicode_escape) 257 | end 258 | if has_escape then 259 | s = s:gsub("\\.", escape_char_map_inv) 260 | end 261 | return s, j + 1 262 | 263 | else 264 | last = x 265 | end 266 | end 267 | decode_error(str, i, "expected closing quote for string") 268 | end 269 | 270 | 271 | local function parse_number(str, i) 272 | local x = next_char(str, i, delim_chars) 273 | local s = str:sub(i, x - 1) 274 | local n = tonumber(s) 275 | if not n then 276 | decode_error(str, i, "invalid number '" .. s .. "'") 277 | end 278 | return n, x 279 | end 280 | 281 | 282 | local function parse_literal(str, i) 283 | local x = next_char(str, i, delim_chars) 284 | local word = str:sub(i, x - 1) 285 | if not literals[word] then 286 | decode_error(str, i, "invalid literal '" .. word .. "'") 287 | end 288 | return literal_map[word], x 289 | end 290 | 291 | 292 | local function parse_array(str, i) 293 | local res = {} 294 | local n = 1 295 | i = i + 1 296 | while 1 do 297 | local x 298 | i = next_char(str, i, space_chars, true) 299 | -- Empty / end of array? 300 | if str:sub(i, i) == "]" then 301 | i = i + 1 302 | break 303 | end 304 | -- Read token 305 | x, i = parse(str, i) 306 | res[n] = x 307 | n = n + 1 308 | -- Next token 309 | i = next_char(str, i, space_chars, true) 310 | local chr = str:sub(i, i) 311 | i = i + 1 312 | if chr == "]" then break end 313 | if chr ~= "," then decode_error(str, i, "expected ']' or ','") end 314 | end 315 | return res, i 316 | end 317 | 318 | 319 | local function parse_object(str, i) 320 | local res = {} 321 | i = i + 1 322 | while 1 do 323 | local key, val 324 | i = next_char(str, i, space_chars, true) 325 | -- Empty / end of object? 326 | if str:sub(i, i) == "}" then 327 | i = i + 1 328 | break 329 | end 330 | -- Read key 331 | if str:sub(i, i) ~= '"' then 332 | decode_error(str, i, "expected string for key") 333 | end 334 | key, i = parse(str, i) 335 | -- Read ':' delimiter 336 | i = next_char(str, i, space_chars, true) 337 | if str:sub(i, i) ~= ":" then 338 | decode_error(str, i, "expected ':' after key") 339 | end 340 | i = next_char(str, i + 1, space_chars, true) 341 | -- Read value 342 | val, i = parse(str, i) 343 | -- Set 344 | res[key] = val 345 | -- Next token 346 | i = next_char(str, i, space_chars, true) 347 | local chr = str:sub(i, i) 348 | i = i + 1 349 | if chr == "}" then break end 350 | if chr ~= "," then decode_error(str, i, "expected '}' or ','") end 351 | end 352 | return res, i 353 | end 354 | 355 | 356 | local char_func_map = { 357 | [ '"' ] = parse_string, 358 | [ "0" ] = parse_number, 359 | [ "1" ] = parse_number, 360 | [ "2" ] = parse_number, 361 | [ "3" ] = parse_number, 362 | [ "4" ] = parse_number, 363 | [ "5" ] = parse_number, 364 | [ "6" ] = parse_number, 365 | [ "7" ] = parse_number, 366 | [ "8" ] = parse_number, 367 | [ "9" ] = parse_number, 368 | [ "-" ] = parse_number, 369 | [ "t" ] = parse_literal, 370 | [ "f" ] = parse_literal, 371 | [ "n" ] = parse_literal, 372 | [ "[" ] = parse_array, 373 | [ "{" ] = parse_object, 374 | } 375 | 376 | 377 | parse = function(str, idx) 378 | local chr = str:sub(idx, idx) 379 | local f = char_func_map[chr] 380 | if f then 381 | return f(str, idx) 382 | end 383 | decode_error(str, idx, "unexpected character '" .. chr .. "'") 384 | end 385 | 386 | 387 | function json.decode(str) 388 | if type(str) ~= "string" then 389 | error("expected argument of type string, got " .. type(str)) 390 | end 391 | local res, idx = parse(str, next_char(str, 1, space_chars, true)) 392 | idx = next_char(str, idx, space_chars, true) 393 | if idx <= #str then 394 | decode_error(str, idx, "trailing garbage") 395 | end 396 | return res 397 | end 398 | 399 | 400 | return json 401 | -------------------------------------------------------------------------------- /rime/rime.lua: -------------------------------------------------------------------------------- 1 | local c2e = require("c2etrigger")("Control+t", require("c2e")) 2 | c2e_translator = c2e.translator 3 | c2e_processor = c2e.processor 4 | 5 | local e2c = require("e2ctrigger")("Control+e", require("e2c")) 6 | e2c_translator = e2c.translator 7 | e2c_processor = e2c.processor 8 | -------------------------------------------------------------------------------- /squirrel/simplehttp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKCHAN000/Rime-Lua-GoogleTranslate/3759db8f4df7881d220883302fa9fa659f17e72f/squirrel/simplehttp.so -------------------------------------------------------------------------------- /weasel/simplehttp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKCHAN000/Rime-Lua-GoogleTranslate/3759db8f4df7881d220883302fa9fa659f17e72f/weasel/simplehttp.dll --------------------------------------------------------------------------------