Improve feeds translate

This commit is contained in:
the1812 2020-03-03 10:28:45 +08:00
parent 9c427793be
commit db9b6228f1
16 changed files with 108 additions and 80 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -79,9 +79,9 @@
"feeds-apis.min.js": "FB079652CED58A4442B95D407955E9E5207E9434DE2BA0019AD52F9C35B92FBD",
"feeds-filter.min.js": "10557E498B8BADA3C1C03E8C1DCD6FB24DBA2DA27A5A03BD861054F7E2989D46",
"feeds-filter-card.vue.min.js": "922E7201AD48573E00123C36A61246ECB3F957AC9C97712A7E0CD5B01C2BEBA8",
"feeds-translate.min.css": "B89D2672E937CA2A89B5265924B4CF28E8ECC067A22693E50BAEE6B3E5985B43",
"feeds-translate.min.js": "6EDDC72E562895EC263D6D1DF8055F99E8C1B1863DB950B23469B3C78F03FD84",
"feeds-translate-providers.min.js": "D938CB5F6437AE4A38C1A9933F530B89168FB4E88DCA2289C46465059CE6473C",
"feeds-translate.min.css": "AE522246431CEE8B45106D2318BE0A5B6DAC64FEC236013FF378D43FC9A411D4",
"feeds-translate.min.js": "3BFACEC337137ABA7EA27184A03F42523DE24F96596BA14AD16A012749D919B1",
"feeds-translate-providers.min.js": "DD3B48C051ED1CD89AB79B2563723B2639D8737EF2194136D63ABAA8D4B64F6C",
"ffmpeg-support.min.js": "B88C5BFDC1CC582CA25098D6BA47189FF628B7323EF9F90D4CFBC4E946648927",
"fill-with-comments.min.js": "A32B6D4ADFA29C164F9675E07715EAC0A5CFE0BBB346735DD691BDA2D9F338C3",
"filter-type-switch.vue.min.js": "E06B00EF48F3CCFACC82B858A266CE0DF48F8332C5900B3AD579330D4C6D3125",
@ -98,7 +98,7 @@
"full-tweets-title.min.css": "13A0CF1C96F374CED3FA59A532E28B4B620D7A4C374385A363F32AD1A7656764",
"full-tweets-title.min.js": "DD57BB732ABEF7739CA84AEFF97E86F8984FCC4A8A75B957213622350B2A7C37",
"gui-settings.min.css": "47A4FAA94402D7400F8C5B2A83D7D77BE88C7566AB6ED1C2C9B3A5F2BEC07068",
"gui-settings.min.html": "873D233EF13BE2DEE45EA24F649B917D288D23B843E71F6FB348EB090405260A",
"gui-settings.min.html": "07963A18AABC04E11528DE82E6BD1077582AA1F7E1A5830E0644EB9132CF1D5B",
"gui-settings.min.js": "029562CA0C0DEFCCBFF38C662C56C651C09847CDB78A99873E3ABA9936B428BA",
"haruna-scale.min.js": "D046864416831B101582DD87E602AE21309FDE2DB64A8F24D57B6ADBE67E6D7B",
"hide-bangumi-reviews.min.js": "7265C0CE994FDA926355A9A4F9B207E7E68E749D47332F3C537EF93E97927A23",
@ -174,7 +174,7 @@
"settings-tooltip.loader.min.js": "B3941A6B9A5AC693832EA49015397114DC95137E12E6D1ABC311EFF3A3D6F319",
"settings-tooltip.min.css": "0C138D5CF16B9068E73D173D229B2B458C15F50272DA73D6A580921C5A848845",
"settings-tooltip.min.js": "E9ABA72B3C29CA850342109E57B055B193F3356DD59876B202E8E908AE6247C9",
"settings-tooltip.zh-CN.min.js": "4111C9ADCD3BA65C7114F2B1AECAC55385434BD8E7F25D67369B8893529CFCD6",
"settings-tooltip.zh-CN.min.js": "F0717F3B20AFA78D4697129E7B566D2B8151251643D4EFFDAF6C1962B1796E34",
"show-dead-video-title.min.js": "8D591930421EBA43A1BDF50DC8B645C1BD1A17E109FB1CFBCD6B78E6C74E1D68",
"simple-home.vue.min.js": "BB936D1E635E21B72A81F448F86AE2E6773ADABC204BFE4BF78A02BB604E16C0",
"simple-home-bangumi-category.vue.min.js": "3CE2077EAA17E33FC3B0003E528658D34F0BBC34259FF5E47E8D2025A11D47AB",

Binary file not shown.

View File

@ -1 +1 @@
(()=>{return(t,e)=>{class n{}class s extends n{constructor(){super(...arguments);this.name="Bing";this.link="https://translate.bing.com/"}async translate(t,e){const n="zh-Hans";let s=_.get(e,"targetLanguage",n);if(s.includes("-")&&s!==n){s=s.substring(0,s.indexOf("-"))}const a=await Ajax.monkey({url:"https://cn.bing.com/ttranslatev3",method:"POST",data:Object.entries({fromLang:"auto-detect",to:s,text:t}).map(([t,e])=>`${t}=${e}`).join("&"),headers:{"User-Agent":UserAgent,"Content-Type":"application/x-www-form-urlencoded"},responseType:"json"});const[r]=a;if(r.translations){return r.translations.map(t=>t.text).join("\n")}else{throw new Error("调用Bing翻译失败.\n"+JSON.stringify(r))}}}class a extends n{constructor(){super(...arguments);this.name="Google";this.link="https://translate.google.com/";this.apiUrl="https://translate.google.com/translate_a/single"}async translate(t,e){const n="zh";let s=_.get(e,"targetLanguage",n);if(s.includes("-")&&s!==n){s=s.substring(0,s.indexOf("-"))}const a=await Ajax.monkey({url:`${this.apiUrl}?${Object.entries({client:"gtx",sl:"auto",tl:s,dt:"t",q:encodeURIComponent(t)}).map(([t,e])=>`${t}=${e}`).join("&")}`,method:"GET",headers:{"User-Agent":UserAgent},responseType:"json"});console.log(_.flattenDeep(a),a,a[0].map(t=>t[0]).join("\n"));const r=a[0].map(t=>t[0]).join("");return r}}class r extends a{constructor(){super(...arguments);this.link="https://translate.google.cn/";this.apiUrl="https://translate.google.cn/translate_a/single"}}const o=()=>{switch(t.feedsTranslateProvider){default:case"Bing":return new s;case"Google":return new a;case"GoogleCN":return new r}};return{export:{getTranslator:o}}}})();
(()=>{return(t,e)=>{class n{}class r extends n{constructor(){super(...arguments);this.name="Bing";this.link="https://translate.bing.com/"}async translate(t,e){const n="zh-Hans";let r=_.get(e,"targetLanguage",n);if(r.includes("-")&&r!==n){r=r.substring(0,r.indexOf("-"))}try{const e=await Ajax.monkey({url:"https://cn.bing.com/ttranslatev3",method:"POST",data:Object.entries({fromLang:"auto-detect",to:r,text:t}).map(([t,e])=>`${t}=${e}`).join("&"),headers:{"User-Agent":UserAgent,"Content-Type":"application/x-www-form-urlencoded"},responseType:"json"});const[n]=e;if(n.translations){return n.translations.map(t=>t.text).join("\n")}else{console.error("Translator: Bing",n);throw new Error("调用Bing翻译失败.")}}catch(t){console.error("Translator: Bing",t);throw new Error("调用Bing翻译失败.")}}}class s extends n{constructor(){super(...arguments);this.name="Google";this.link="https://translate.google.com/";this.apiUrl="https://translate.google.com/translate_a/single"}async translate(t,e){const n="zh";let r=_.get(e,"targetLanguage",n);if(r.includes("-")&&r!==n){r=r.substring(0,r.indexOf("-"))}try{const e=await Ajax.monkey({url:`${this.apiUrl}?${Object.entries({client:"gtx",sl:"auto",tl:r,dt:"t",q:encodeURIComponent(t)}).map(([t,e])=>`${t}=${e}`).join("&")}`,method:"GET",headers:{"User-Agent":UserAgent},responseType:"json"});const n=e[0].map(t=>t[0]).join("");return n}catch(t){console.error("Translator: Google",t);throw new Error("调用Google翻译失败.")}}}class o extends s{constructor(){super(...arguments);this.link="https://translate.google.cn/";this.apiUrl="https://translate.google.cn/translate_a/single"}}const a=()=>{switch(t.feedsTranslateProvider){default:case"Bing":return new r;case"Google":return new s;case"GoogleCN":return new o}};return{export:{getTranslator:a}}}})();

View File

@ -1 +1 @@
.card-content .translate-container{margin-top:10px}.card-content .translate-container .translated{font-size:12px;color:#aaa}.card-content .translate-container .translated a{color:var(--theme-color)}.card-content .translate-container .translate{display:flex;align-items:center;font-size:12px;color:#aaa;cursor:pointer}.card-content .translate-container .translate:hover{color:var(--theme-color)}.card-content .translate-container .translate .mdi{font-size:14px;margin-right:2px}.card-content .translate-container .translating{font-size:18px}.card-content .translate-container .translate-result{padding-top:10px;white-space:pre-wrap;line-height:22px;word-break:break-all;overflow-wrap:break-word}
.card-content .translate-container{margin-top:10px}.card-content .translate-container .translated{font-size:12px;color:#aaa}.card-content .translate-container .translated a{color:var(--theme-color)}.card-content .translate-container .translate{display:flex;align-items:center;font-size:12px;color:#aaa;cursor:pointer}.card-content .translate-container .translate:hover{color:var(--theme-color)}.card-content .translate-container .translate .mdi{font-size:14px;margin-right:2px}.card-content .translate-container .translating{font-size:18px}.card-content .translate-container .translate-result{padding-top:10px;white-space:pre-wrap;line-height:22px;word-break:break-all;overflow-wrap:break-word}body.dark .card-content .translate-container .translate-result{color:#eee}

View File

@ -1 +1 @@
(()=>{return(t,a)=>{(async()=>{if(!document.URL.startsWith("https://t.bilibili.com/")){return}a.applyStyle("feedsTranslateStyle");const{getTranslator:e}=await a.importAsync("feeds-translate-providers");const{feedsCardsManager:r}=await a.importAsync("feeds-apis");const n=await r.startWatching();if(!n){console.error("feedsCardsManager.startWatching() failed");return}const s=Vue.extend({template:`\n<div class="translate-container">\n<div class="translate" v-if="!working && !translated" @click="translate()">\n<i class="mdi mdi-earth"></i>翻译\n</div>\n<i v-if="working" class="translating mdi mdi-18px mdi-loading mdi-spin"></i>\n<div class="translated" v-if="translated">翻译自<a :href="activeTranslator.link" target="_blank">{{activeTranslator.name}}</a>:</div>\n<div v-if="translated" class="translate-result">{{result}}</div>\n</div>\n`,props:{card:{type:Object,required:true}},data(){return{result:"",working:false,activeTranslator:{}}},computed:{translated(){return this.result!==""}},methods:{async translate(){const a=this.card;try{this.working=true;const r=(await a.getText()).replace(/#(.+?)#/g,"");const n=this.activeTranslator=e();this.result=await n.translate(r,{targetLanguage:(()=>{if(t.i18n){return languageNameToCode[t.i18nLanguage]}if(t.feedsTranslateLanguage!==""){return t.feedsTranslateLanguage}return})()})}catch(t){logError(t)}finally{this.working=false}}}});const i=t=>{if(t.text.replace(/#(.+?)#/g,"")===""){return}const a=t.element.querySelector(".card-content");const e=new s({propsData:{card:_.clone(t)}}).$mount();a.insertAdjacentElement("beforeend",e.$el)};r.cards.forEach(i);r.addEventListener("addCard",t=>{i(t.detail)})})()}})();
(()=>{return(t,a)=>{(async()=>{if(!document.URL.startsWith("https://t.bilibili.com/")){return}a.applyStyle("feedsTranslateStyle");const{getTranslator:e}=await a.importAsync("feeds-translate-providers");const r=Vue.extend({template:`\n<div class="translate-container">\n<div class="translate" v-if="!working && !translated" @click="translate()">\n<i class="mdi mdi-earth"></i>翻译\n</div>\n<i v-if="working" class="translating mdi mdi-18px mdi-loading mdi-spin"></i>\n<div class="translated" v-if="translated">翻译自<a :href="activeTranslator.link" target="_blank">{{activeTranslator.name}}</a>:</div>\n<div v-if="translated" class="translate-result">{{result}}</div>\n</div>\n`,props:{card:{type:Object,required:true}},data(){return{result:"",working:false,activeTranslator:{}}},computed:{translated(){return this.result!==""}},methods:{async translate(){const a=this.card;try{this.working=true;const r=(await a.getText()).replace(/#(.+?)#/g,"");const n=this.activeTranslator=e();this.result=await n.translate(r,{targetLanguage:(()=>{if(t.i18n){return languageNameToCode[t.i18nLanguage]}if(t.feedsTranslateLanguage!==""){return t.feedsTranslateLanguage}return})()})}catch(t){logError(t)}finally{this.working=false}}}});const n=t=>{if(t.text.replace(/#(.+?)#/g,"")===""){return}const a=t.element.querySelector(".card-content");const e=new r({propsData:{card:_.clone(t)}}).$mount();a.insertAdjacentElement("beforeend",e.$el)};const s=document.URL.replace(location.search,"");const{feedsCardsManager:i}=await a.importAsync("feeds-apis");if(s==="https://t.bilibili.com/"){const t=await i.startWatching();if(!t){console.error("feedsCardsManager.startWatching() failed");return}i.cards.forEach(n);i.addEventListener("addCard",t=>{n(t.detail)})}else if(s.match(/t.bilibili.com\/(\d+)/)){const t=await SpinQuery.select(".detail-card .card");if(t!==null&&"__vue__"in t){const a=await i.parseCard(t);n(a)}}})()}})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,25 +15,31 @@ class BingTranslate extends FeedsTranslateProvider {
if (targetLanguage.includes('-') && targetLanguage !== defaultLanguage) {
targetLanguage = targetLanguage.substring(0, targetLanguage.indexOf('-'))
}
const response = await Ajax.monkey({
url: 'https://cn.bing.com/ttranslatev3',
method: 'POST',
data: Object.entries({
fromLang: 'auto-detect',
to: targetLanguage,
text,
}).map(([key, value]) => `${key}=${value}`).join('&'),
headers: {
'User-Agent': UserAgent,
'Content-Type': 'application/x-www-form-urlencoded',
},
responseType: 'json',
})
const [result] = response
if (result.translations) {
return (result.translations as any[]).map(t => t.text as string).join('\n')
} else {
throw new Error('调用Bing翻译失败.\n' + JSON.stringify(result))
try {
const response = await Ajax.monkey({
url: 'https://cn.bing.com/ttranslatev3',
method: 'POST',
data: Object.entries({
fromLang: 'auto-detect',
to: targetLanguage,
text,
}).map(([key, value]) => `${key}=${value}`).join('&'),
headers: {
'User-Agent': UserAgent,
'Content-Type': 'application/x-www-form-urlencoded',
},
responseType: 'json',
})
const [result] = response
if (result.translations) {
return (result.translations as any[]).map(t => t.text as string).join('\n')
} else {
console.error('Translator: Bing', result)
throw new Error('调用Bing翻译失败.')
}
} catch (error) {
console.error('Translator: Bing', error)
throw new Error('调用Bing翻译失败.')
}
}
}
@ -48,23 +54,28 @@ class GoogleTranslate extends FeedsTranslateProvider {
if (targetLanguage.includes('-') && targetLanguage !== defaultLanguage) {
targetLanguage = targetLanguage.substring(0, targetLanguage.indexOf('-'))
}
const response = await Ajax.monkey({
url: `${this.apiUrl}?${Object.entries({
client: 'gtx',
sl: 'auto',
tl: targetLanguage,
dt: 't',
q: encodeURIComponent(text),
}).map(([key, value]) => `${key}=${value}`).join('&')}`,
method: 'GET',
headers: {
'User-Agent': UserAgent,
},
responseType: 'json',
})
console.log(_.flattenDeep(response), response, response[0].map((it: any) => it[0]).join('\n'))
const result = response[0].map((it: any) => it[0]).join('')
return result
try {
const response = await Ajax.monkey({
url: `${this.apiUrl}?${Object.entries({
client: 'gtx',
sl: 'auto',
tl: targetLanguage,
dt: 't',
q: encodeURIComponent(text),
}).map(([key, value]) => `${key}=${value}`).join('&')}`,
method: 'GET',
headers: {
'User-Agent': UserAgent,
},
responseType: 'json',
})
// console.log(_.flattenDeep(response), response, response[0].map((it: any) => it[0]).join('\n'))
const result = response[0].map((it: any) => it[0]).join('')
return result
} catch (error) {
console.error('Translator: Google', error)
throw new Error('调用Google翻译失败.')
}
}
}
class GoogleCNTranslate extends GoogleTranslate {

View File

@ -30,5 +30,8 @@
line-height: 22px;
word-break: break-all;
overflow-wrap: break-word;
body.dark & {
color: #eee;
}
}
}

View File

@ -6,12 +6,6 @@ import { FeedsCard } from '../feeds-apis'
}
resources.applyStyle('feedsTranslateStyle')
const { getTranslator } = await import('./feeds-translate-providers')
const { feedsCardsManager } = await import('../feeds-apis')
const success = await feedsCardsManager.startWatching()
if (!success) {
console.error('feedsCardsManager.startWatching() failed')
return
}
const Translator = Vue.extend({
template: /*html*/`
<div class="translate-container">
@ -79,8 +73,26 @@ import { FeedsCard } from '../feeds-apis'
}).$mount()
cardContent.insertAdjacentElement('beforeend', translator.$el)
}
feedsCardsManager.cards.forEach(injectButton)
feedsCardsManager.addEventListener('addCard', e => {
injectButton(e.detail)
})
const urlWithoutQuery = document.URL.replace(location.search, '')
const { feedsCardsManager } = await import('../feeds-apis')
// 动态首页
if (urlWithoutQuery === 'https://t.bilibili.com/') {
const success = await feedsCardsManager.startWatching()
if (!success) {
console.error('feedsCardsManager.startWatching() failed')
return
}
feedsCardsManager.cards.forEach(injectButton)
feedsCardsManager.addEventListener('addCard', e => {
injectButton(e.detail)
})
} else if (urlWithoutQuery.match(/t.bilibili.com\/(\d+)/)) { // 动态详情页
const card = await SpinQuery.select('.detail-card .card')
if (card !== null && '__vue__' in card) {
const feedsCard = await feedsCardsManager.parseCard(card)
injectButton(feedsCard)
}
}
})()

View File

@ -117,8 +117,8 @@
<checkbox indent="0" key="fullActivityContent" dependencies=""></checkbox>
<!-- <checkbox indent="0" key="oldTweets" dependencies=""></checkbox> -->
<checkbox indent="0" key="feedsFilter" dependencies=""></checkbox>
<!-- <checkbox indent="0" key="feedsTranslate" dependencies=""></checkbox>
<dropdown indent="1" key="feedsTranslateProvider" dependencies="feedsTranslate"></dropdown> -->
<checkbox indent="0" key="feedsTranslate" dependencies=""></checkbox>
<dropdown indent="1" key="feedsTranslateProvider" dependencies="feedsTranslate"></dropdown>
<category icon="tool">工具</category>
<checkbox indent="0" key="removeAds" dependencies=""></checkbox>
<checkbox indent="1" key="showBlockedAdsTip" dependencies="removeAds"></checkbox>

View File

@ -180,6 +180,8 @@ export const toolTips = new Map<keyof BilibiliEvolvedSettings, string>([
- <span>n</span>: , n个视频.`],
[`removeGameMatchModule`, /*html*/`删除电竞赛事板块.`],
[`recordLiveDanmaku`, /*html*/`在附加功能中添加直播弹幕记录器, 可以记录直播弹幕并导出XML.`],
[`feedsTranslate`, /*html*/`在每条动态下方添加翻译按钮, 可将动态的文字机器翻译为中文. 若开启了界面翻译, 则会翻译成界面翻译里设定的语言.`],
[`feedsTranslateProvider`, /*html*/`机器翻译的提供者`],
]);
export default {
export: { toolTips },