Skip to content

Commit

Permalink
fix popup
Browse files Browse the repository at this point in the history
  • Loading branch information
bujnlc8 committed Aug 6, 2024
1 parent ff5d361 commit b8d205f
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 83 deletions.
43 changes: 22 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,61 @@
# 一个有用的翻译VIM插件, 提供有道和百度两种选择
# 一个有用的翻译 VIM 插件, 提供有道和百度两种选择

先上图:

![](https://s3.bmp.ovh/imgs/2021/10/9e32b13bc6936ca8.jpg)

## 安装

* 将代码clone到`~/.vim/plugin`下面即可。
- 将代码 clone 到`~/.vim/plugin`下面即可。

OR

* 如果你有安装插件管理工具,比如, `vim-plug`, 可以加入以下行到你的`.vimrc`进行安装
- 如果你有安装插件管理工具,比如, `vim-plug`, 可以加入以下行到你的`.vimrc`进行安装

<!---->

Plug 'bujnlc8/vim-translator'

**只在 macOS 中测试过,理论上 Linux 也适用,Windows 应该会报错**

## 命令

* `:Ti`, 支持在底部输入框输入翻译,可以在`.vimrc`加入`noremap <leader>ti :<C-u>Ti<CR>`支持快捷键输入。
- `:Ti`, 支持在底部输入框输入翻译,可以在`.vimrc`加入`noremap <leader>ti :<C-u>Ti<CR>`支持快捷键输入。

* `:Ty`, 从粘贴板中获取文字进行翻译(匿名寄存器中""), 可以在`.vimrc`加入`noremap <leader>ty :<C-u>Ty<CR>`支持快捷键输入。
- `:Ty`, 从粘贴板中获取文字进行翻译(匿名寄存器中""), 可以在`.vimrc`加入`noremap <leader>ty :<C-u>Ty<CR>`支持快捷键输入。

* `:Tc`, 支持翻译光标处单词,可以在`.vimrc`加入`noremap <leader>tc :<C-u>Tc<CR>`支持快捷键。
- `:Tc`, 支持翻译光标处单词,可以在`.vimrc`加入`noremap <leader>tc :<C-u>Tc<CR>`支持快捷键。

* `:Tv`, 支持在visual模式下选中翻译,可以在`.vimrc`加入`vnoremap <leader>tv :<C-u>Tv<CR>`支持快捷键。
- `:Tv`, 支持在 visual 模式下选中翻译,可以在`.vimrc`加入`vnoremap <leader>tv :<C-u>Tv<CR>`支持快捷键。

* `:Tr`, 支持在visual模式下将文字替换成翻译,可以在`.vimrc`加入`vnoremap <leader>tr :<C-u>Tr<CR>`支持快捷键。
- `:Tr`, 支持在 visual 模式下将文字替换成翻译,可以在`.vimrc`加入`vnoremap <leader>tr :<C-u>Tr<CR>`支持快捷键。

* `:Te`, 收藏单词或语句,如果提供了一个参数,那么会收藏该参数,否则收藏光标处的单词。
- `:Te`, 收藏单词或语句,如果提供了一个参数,那么会收藏该参数,否则收藏光标处的单词。

* `:Tev`, 收藏visual 模式下选中的词汇,需要在visual模式下启用
- `:Tev`, 收藏 visual 模式下选中的词汇,需要在 visual 模式下启用

* `:Tee`, 编辑收藏的单词或语句,可以像编辑一个文本来进行编辑。
- `:Tee`, 编辑收藏的单词或语句,可以像编辑一个文本来进行编辑。

* `:Tz`, 查询中文拼音及释义等。
- `:Tz`, 查询中文拼音及释义等。

## 选项

* `let g:translator_cache=1`, 是否启用缓存,默认1。

* `let g:translator_cache_path='~/.cache'`,缓存路径,默认`expand('<sfile>:p:h').'/.cache'`
- `let g:translator_cache=1`, 是否启用缓存,默认 1。

* `let g:translator_channel='youdao'`查询通道,默认`youdao`, 也可切到`baidu`
- `let g:translator_cache_path='~/.cache'`缓存路径,默认`expand('<sfile>:p:h').'/.cache'`

* `let g:translator_outputype='popup'`, 结果输出方式,如果支持弹窗(vim-8.2及以上)默认弹窗展示,否则输出到底部,也可以设置成`echo`显式开启输出到底部,弹窗模式下按`z`关闭弹窗。`echo` 模式下,如果结果长度大于200,会输出到`fixquick`窗口中
- `let g:translator_channel='youdao'`,查询通道,默认`youdao`, 也可切到`baidu`

- `let g:translator_outputype='popup'`, 结果输出方式,如果支持弹窗(vim-8.2 及以上)默认弹窗展示,否则输出到底部,也可以设置成`echo`显式开启输出到底部,弹窗模式下按`z`关闭弹窗。`echo` 模式下,如果结果长度大于 200,会输出到`fixquick`窗口中。

## 后记

在写插件的过程中借鉴了[vim-youdao-translater](https://github.com/ianva/vim-youdao-translater) 这个项目,特此表示感谢♥️。
在写插件的过程中借鉴了[vim-youdao-translater](https://github.com/ianva/vim-youdao-translater) 这个项目,特此表示感谢 ♥️。

但在使用上述插件的过程中经常出现查询出错的情况,而且使用的接口也已经比较老了,遂萌生了重写插件的念头, 本插件根据有道翻译[官网](https://fanyi.youdao.com/)最新接口封装,大大减小了出错的几率, 相当智能。写完之后觉得百度翻译好像也还可以,于是又加上了百度翻译。可以通过`let g:translator_channel='baidu'`来切换到百度翻译。

在使用过程中如果出现问题,欢迎在Issues提出
在使用过程中如果出现问题,欢迎在 Issues 提出

另外,为了推广python3, 本插件只支持python3
另外,为了推广 python3, 本插件只支持 python3

如果百度翻译提示token失效或者类似的错误,请尝试用chrome访问[百度翻译](https://fanyi.baidu.com/),打开开发者工具,随意输入一个单词查询,在`https://fanyi.baidu.com/v2transapi?xxx`的form表单提交中应该有一个`token`字段,在Cookies中应该有一个名字为`BAIDUID_BFESS`的cookie, 将它们的值分别替换掉`plugin/baidu.py`文件顶部的`TOKEN``BAIDUID_BFESS`变量。 替换之后再次尝试。
如果百度翻译提示 token 失效或者类似的错误,请尝试用 chrome 访问[百度翻译](https://fanyi.baidu.com/),打开开发者工具,随意输入一个单词查询,在`https://fanyi.baidu.com/v2transapi?xxx`的 form 表单提交中应该有一个`token`字段,在 Cookies 中应该有一个名字为`BAIDUID_BFESS`的 cookie, 将它们的值分别替换掉`plugin/baidu.py`文件顶部的`TOKEN``BAIDUID_BFESS`变量。 替换之后再次尝试。
82 changes: 75 additions & 7 deletions plugin/translator.vim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
let s:current_path = expand('<sfile>:p:h')

let s:has_popup = has('textprop') && has('patch-8.2.0286')
let s:has_popup = (has('textprop') && has('patch-8.2.0286')) || has("nvim")

if !exists('g:translator_outputype')
if s:has_popup
Expand All @@ -11,7 +11,7 @@ if !exists('g:translator_outputype')
endif

if g:translator_outputype == 'popup' && !s:has_popup
echoerr '[Translator] not support popup, `g:translator_outputype` will be changed to `echo`'
echoerr '[Translator] not support popup, `g:translator_outputype` will be switch to `echo`'
let g:translator_outputype = 'echo'
endif

Expand All @@ -20,7 +20,7 @@ if !exists('g:translator_channel')
endif

if g:translator_channel != 'youdao' && g:translator_channel != 'baidu'
echoerr '[Translator] g:translator_channel 配置错误'
echoerr '[Translator] g:translator_channel config error'
endif

let s:translator_file= s:current_path . '/'.g:translator_channel.'.py'
Expand All @@ -35,7 +35,10 @@ endif

if g:translator_cache
if !isdirectory(g:translator_cache_path)
call mkdir(g:translator_cache_path)
try
call mkdir(g:translator_cache_path)
catch
endtry
endif
endif

Expand All @@ -50,6 +53,9 @@ elseif executable('gzip')
endif

function! s:do_cache(md5, s)
if !isdirectory(g:translator_cache_path)
return
endif
let l:ppdir = g:translator_cache_path.'/'.a:md5[:1]
if !isdirectory(l:ppdir)
call mkdir(l:ppdir)
Expand All @@ -62,12 +68,74 @@ function! s:do_cache(md5, s)
endfunction

function! s:popup_filter(winid, key)
if a:key == 'z'
if a:key == 'z' || a:key == 'q'
call popup_close(a:winid)
endif
endfunction

function! s:create_popup_nvim(words, result)
call s:popup_clear_nvim()

if len(a:result) > 2000
let l:max_width = 132
else
let l:max_width = 66
endif

let l:height = min([len(split(a:result, "\n")) + 2, 20])
let l:width = l:max_width
let l:editor_width = &columns
let l:editor_height = &lines
let l:row = (l:editor_height - l:height) / 2
let l:col = (l:editor_width - l:width) / 2

let l:options = {
\ 'relative': 'editor',
\ 'width': l:max_width,
\ 'height': l:height,
\ 'col': l:col,
\ 'row': l:row,
\ 'anchor': 'NW',
\ 'style': 'minimal',
\ 'border': 'rounded',
\ 'zindex': 100,
\}

let l:result = []
for x in split(a:result, "\n")
call add(l:result, substitute(x, '\s', '', 'g'))
endfor

if len(a:words) < 132
let l:lines = [a:words, '------------------------------------------------------------------'] + l:result
else
let l:lines = l:result
endif

let l:buf = nvim_create_buf(v:false, v:true)
call nvim_buf_set_lines(l:buf, 0, -1, v:true, l:lines)
let l:winid = nvim_open_win(l:buf, v:true, l:options)
call nvim_win_set_option(l:winid, 'winhighlight', 'Normal:TranslatorHi,FloatBorder:TranslatorBorder')
call nvim_buf_set_option(l:buf, 'filetype', 'translator')
call nvim_buf_set_keymap(l:buf, 'n', 'z', ':call nvim_win_close(' . l:winid . ', v:true)<CR>', {'nowait': v:true, 'noremap': v:true, 'silent': v:true})
call nvim_buf_set_keymap(l:buf, 'n', 'q', ':call nvim_win_close(' . l:winid . ', v:true)<CR>', {'nowait': v:true, 'noremap': v:true, 'silent': v:true})
call nvim_buf_set_keymap(l:buf, 'n', '<Esc>', ':call nvim_win_close(' . l:winid . ', v:true)<CR>', {'nowait': v:true, 'noremap': v:true, 'silent': v:true})
endfunction

function! s:popup_clear_nvim()
let l:windows = nvim_list_wins()
for win in l:windows
if nvim_win_get_config(win).relative != ''
call nvim_win_close(win, v:true)
endif
endfor
endfunction

function! s:create_popup(words, result)
if has('nvim')
call s:create_popup_nvim(a:words, a:result)
return
endif
call popup_clear()
if len(a:result) > 2000
let l:max_wdith = 132
Expand Down Expand Up @@ -334,5 +402,5 @@ command! Tee call <SID>enshrine_edit()
command! Tev call <SID>enshrine_wordsv()
autocmd! BufWritePost *.tdata :call <SID>after_write_enshrine_file()
autocmd! BufWritePre *.tdata set fileencoding=utf-8
highlight TranslatorBorder ctermfg=37 guifg=#459d90 guibg=#202a31
highlight TranslatorHi term=bold guifg=#898f9e guibg=#202a31
highlight TranslatorBorder ctermfg=37 guifg=#459d90
highlight TranslatorHi term=bold guifg=#898f9e
112 changes: 57 additions & 55 deletions plugin/youdao.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,91 +10,93 @@
from urllib import error, parse, request

headers = {
'Content-Length': 417,
'Connection': 'keep-alive',
'sec-ch-ua': '"Google Chrome";v="93", " Not;A Brand";v="99", "Chromium";v="93"',
'DNT': '1',
'sec-ch-ua-mobile': '?0',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'X-Requested-With': 'XMLHttpRequest',
'sec-ch-ua-platform': '"macOS"',
'Origin': 'https://fanyi.youdao.com',
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Dest': 'empty',
'Referer': 'https://fanyi.youdao.com/',
'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
'Cookie': '',
"Content-Length": 417,
"Connection": "keep-alive",
"sec-ch-ua": '"Google Chrome";v="93", " Not;A Brand";v="99", "Chromium";v="93"',
"DNT": "1",
"sec-ch-ua-mobile": "?0",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Accept": "application/json, text/javascript, */*; q=0.01",
"X-Requested-With": "XMLHttpRequest",
"sec-ch-ua-platform": '"macOS"',
"Origin": "https://fanyi.youdao.com",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Dest": "empty",
"Referer": "https://fanyi.youdao.com/",
"Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
"Cookie": "",
}

Cookie = 'OUTFOX_SEARCH_USER_ID=1025647716@10.105.137.204; JSESSIONID=abcANZkLeT9rY7RGG8lmy; OUTFOX_SEARCH_USER_ID_NCOO=1716500965.6211884;'
Cookie = "OUTFOX_SEARCH_USER_ID=1025647716@10.105.137.204; JSESSIONID=abcANZkLeT9rY7RGG8lmy; OUTFOX_SEARCH_USER_ID_NCOO=1716500965.6211884;"

Url = 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
Url = "https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"


def get_result(query):
query = base64.b64decode(query).decode('utf-8')
query = base64.b64decode(query).decode("utf-8")
return _get_result(query)


def _get_result(query):
t = int(time.time() * 1000)
salt = str(t) + str(random.randint(1, 10))
sign = hashlib.md5(str('fanyideskweb{}{}Ygy_4c=r#e#4EX^NUGUc5'.format(query, salt)).encode('utf-8')).hexdigest()
sign = hashlib.md5(
str("fanyideskweb{}{}Ygy_4c=r#e#4EX^NUGUc5".format(query, salt)).encode("utf-8")
).hexdigest()
data = {
'i': query,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': '{}'.format(salt),
'sign': '{}'.format(sign),
'lts': '{}'.format(t),
'bv': 'd2d111fb0f6e20e76ece0d3d4ebbb36a',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME'
"i": query,
"from": "AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"salt": "{}".format(salt),
"sign": "{}".format(sign),
"lts": "{}".format(t),
"bv": "d2d111fb0f6e20e76ece0d3d4ebbb36a",
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_REALTlME",
}
headers['Cookie'] = Cookie + '___rl__test__cookies=' + str(t)
headers["Cookie"] = Cookie + "___rl__test__cookies=" + str(t)
try:
data = parse.urlencode(data).encode('utf-8')
headers['Content-Length'] = len(data)
data = parse.urlencode(data).encode("utf-8")
headers["Content-Length"] = len(data)
req = request.Request(Url, data=data, headers=headers)
res = request.urlopen(req)
if res.getcode() != 200:
return 'Err:返回异常[{}]'.format(res.getcode())
return "Err:返回异常[{}]".format(res.getcode())
res = json.loads(res.read())
if res['errorCode'] != 0:
if res['errorCode'] == 40:
return 'Err:无结果'
if res['errorCode'] == 50:
return 'Err:签名错误'
return 'Err:返回异常[{}]'.format(res['errorCode'])
if res["errorCode"] != 0:
if res["errorCode"] == 40:
return "Err:无结果"
if res["errorCode"] == 50:
return "Err:签名错误"
return "Err:返回异常[{}]".format(res["errorCode"])
result = []
if 'smartResult' in res:
entries = res['smartResult']['entries']
if "smartResult" in res:
entries = res["smartResult"]["entries"]
for x in entries:
if not x:
continue
result.append(x)
elif 'translateResult' in res:
if len(res['translateResult']) > 0:
for x in res['translateResult']:
elif "translateResult" in res:
if len(res["translateResult"]) > 0:
for x in res["translateResult"]:
for y in x:
result.append(y['tgt'])
result.append(y["tgt"])
if result:
return '\n'.join(result)
return 'Err:无结果'
return "\n".join(result)
return "Err:无结果"
except error.HTTPError:
return 'Err:请求异常'
return "Err:请求异常"
except Exception as e:
return 'Err:产生异常: %s' % e
return "Err:产生异常: %s" % e


if __name__ == '__main__':
if __name__ == "__main__":
if len(argv) >= 2:
stdout.write(str(get_result(argv[1])))
stdout.flush()

0 comments on commit b8d205f

Please sign in to comment.