Support regex translation

This commit is contained in:
the1812 2019-04-08 23:06:34 +08:00
parent fd171b921d
commit 545c8e5dba
14 changed files with 322 additions and 270 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
(()=>{return(r,e)=>{const n=new Map([[`*`,[]]]);return{export:{map:n}}}})(); (()=>{return(e,n)=>{const r=new Map([[`*`,[]]]);const t=new Map([]);return{export:{map:r,regex:t}}}})();

View File

@ -1 +1 @@
(()=>{return(e,t)=>{const o=new Map([[`主站`,`Home`],[`画友`,`Painting`],[`音频`,`Music`],[`游戏中心`,`Game`],[`直播`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Live`}],[`会员购`,`Shop`],[`漫画`,`Comic`],[`下载APP`,`APP`],[`大会员`,`VIP`],[`年度大会员`,`Annual VIP`],[`消息`,`Message`],[`动态`,`Activity`],[`稍后再看`,`Watchlater`],[`已加稍后再看`,`Added`],[`移除`,`Remove`],[`收藏`,`Favorite`],[`历史`,`History`],[`投稿`,`Upload`],[`关注`,[`Follow`,{selector:`.user-panel .text, .n .n-data .n-data-k`,text:`Following`}]],[`关注数`,`Following`],[`粉丝`,`Followers`],[`粉丝数`,`Followers`],[`已关注`,`Following`],[`回复我的`,`Reply`],[`@我的`,`@Mentioned`],[`收到的赞`,`Likes`],[`系统通知`,`System`],[`我的消息`,`Whisper`],[`主页`,`Home`],[`频道`,`Channel`],[`订阅`,`Subscriptions`],[`设置`,`Settings`],[`搜索`,`Search`],[`搜索视频`,`Search videos`],[`搜索设置项`,`Search settings`],[`查看全部`,`View more`],[`查看更多`,`View more`],[`视频`,`Video`],[`专栏`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Column`}],[`转发`,`Forward`],[`评论`,`Reviews`],[``,`Like`],[`视角:`,`View: `],[`我自己`,`Myself`],[`新访客`,`New visitors`],[`我的粉丝`,`Followers`],[`暂时没有新动态了哦!`,`Nothing new at this moment...`],[`历史动态`,`History`],[`投稿了`,`posted`],[`更新了`,`updated`],[`番剧`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Bangumi`}],[`样式`,`Style`],[`工具`,`Tools`],[`触摸`,`Touch`],[`其他`,`Other`],[`附加功能`,`Add-on features`],[`空空如也哦...`,`Nothing...`],[`正在直播`,`Live broadcasting`],[`投稿视频`,`Posted video`],[`展开全文`,`Expand`],[`动画`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Anime`}],[`科技`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Tech`}],[`游戏`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Game`}],[`生活`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Life`}],[`国创`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Native`}],[`音乐`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Music`}],[`舞蹈`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Dance`}],[`数码`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Digital`}],[`鬼畜`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Kichiku`}],[`时尚`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Fashion`}],[`广告`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Ads`}],[`娱乐`,[{selector:`.elevator-module .nav-list .item`,not:true,text:`Entertainment`},{selector:`.primary-menu .nav-menu li .nav-name`,text:`Entmt`}]],[`电影`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Movie`}],[`TV剧`,{selector:`.elevator-module .nav-list .item`,not:true,text:`TV drama`}],[`影视`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Film`}],[`纪录片`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Documentary`}],[`放映厅`,`Cinema`],[`广场`,`Plaza`],[`小黑屋`,`Blackroom`],[`*`,[]]]);return{export:{map:o}}}})(); (()=>{return(e,t)=>{const o=new Map([[`主站`,`Home`],[`画友`,`Painting`],[`音频`,`Music`],[`游戏中心`,`Game`],[`直播`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Live`}],[`会员购`,`Shop`],[`漫画`,`Comic`],[`下载APP`,`APP`],[`大会员`,`VIP`],[`年度大会员`,`Annual VIP`],[`消息`,`Message`],[`动态`,`Activity`],[`稍后再看`,`Watchlater`],[`已加稍后再看`,`Added`],[`移除`,`Remove`],[`收藏`,`Favorite`],[`历史`,`History`],[`投稿`,`Upload`],[`关注`,[`Follow`,{selector:`.user-panel .text, .n .n-data .n-data-k`,text:`Following`}]],[`关注数`,`Following`],[`粉丝`,`Followers`],[`粉丝数`,`Followers`],[`已关注`,`Following`],[`回复我的`,`Reply`],[`@我的`,`@Mentioned`],[`收到的赞`,`Likes`],[`系统通知`,`System`],[`我的消息`,`Whisper`],[`主页`,`Home`],[`频道`,`Channel`],[`订阅`,`Subscriptions`],[`设置`,`Settings`],[`搜索`,`Search`],[`搜索视频`,`Search videos`],[`搜索设置项`,`Search settings`],[`查看全部`,`View more`],[`查看更多`,`View more`],[`视频`,`Video`],[`专栏`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Column`}],[`转发`,`Forward`],[`评论`,`Reviews`],[``,`Like`],[`视角:`,`View: `],[`我自己`,`Myself`],[`新访客`,`New visitors`],[`我的粉丝`,`Followers`],[`暂时没有新动态了哦!`,`Nothing new at this moment...`],[`历史动态`,`History`],[`投稿了`,`posted`],[`更新了`,`updated`],[`番剧`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Bangumi`}],[`样式`,`Style`],[`工具`,`Tools`],[`触摸`,`Touch`],[`其他`,`Other`],[`附加功能`,`Add-on features`],[`空空如也哦...`,`Nothing...`],[`正在直播`,`Live broadcasting`],[`投稿视频`,`Posted video`],[`展开全文`,`Expand`],[`动画`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Anime`}],[`科技`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Tech`}],[`游戏`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Game`}],[`生活`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Life`}],[`国创`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Native`}],[`音乐`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Music`}],[`舞蹈`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Dance`}],[`数码`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Digital`}],[`鬼畜`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Kichiku`}],[`时尚`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Fashion`}],[`广告`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Ads`}],[`娱乐`,[{selector:`.elevator-module .nav-list .item`,not:true,text:`Entertainment`},{selector:`.primary-menu .nav-menu li .nav-name`,text:`Entmt`}]],[`电影`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Movie`}],[`TV剧`,{selector:`.elevator-module .nav-list .item`,not:true,text:`TV drama`}],[`影视`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Film`}],[`纪录片`,{selector:`.elevator-module .nav-list .item`,not:true,text:`Documentary`}],[`放映厅`,`Cinema`],[`广场`,`Plaza`],[`小黑屋`,`Blackroom`],[`*`,[]]]);const l=new Map([]);return{export:{map:o,regex:l}}}})();

File diff suppressed because one or more lines are too long

2
min/i18n.min.css vendored
View File

@ -1 +1 @@
#page-follows .follow-sidenav .text,.admin-list-cntr .rank-cntr .item .admin-icon,.attention-btn-ctnr .left-part,.author-info .communicate-btn,.author-info .favourite-btn,.bili-search .nav-wrap .wrap>.sub,.dashboard li.like,.h .h-f-btn,.live-sidebar-ctnr .sidebar-btn,.n .n-data,.textarea-container .comm-tool .comm-emoji,.textarea-container .comm-tool .comm-submit,.up-info .up-focus-btn{width:auto!important}.bb-comment .comment-send .comment-emoji{width:max-content!important}.live-panel .more-button,.tag-panel .more-button{width:44px!important}.link-navbar .main-ctnr .nav-logo{width:70px!important}.bili-header-m .profile-m .grade .bar{width:160px!important}.bili-search .contain,.link-navbar .main-ctnr{width:90%!important}.bili-search .video.list{width:calc(100% - 172px)!important}.bili-search .video.list .des{width:100%!important}#page-follows .follow-sidenav .text{min-width:78px!important}.h .h-f-btn{min-width:76px!important}.primary-menu .nav-menu .nav-name,.primary-menu .nav-menu .side-nav .side-link span{white-space:pre!important}.admin-list-cntr .rank-cntr .item .admin-icon,.attention-btn-ctnr .left-part,.bb-comment .comment-send .comment-emoji,.h .h-f-btn,.textarea-container .comm-tool .comm-emoji,.textarea-container .comm-tool .comm-submit,.up-info .up-focus-btn{padding:0 8px!important}.n .n-data{padding:10px 8px!important}.user-panel-ctnr .user-panel .content-ctnr .ctrl-btn:nth-child(2n){padding-left:8px!important}.dashboard li.share .text{padding-top:15px!important}.dashboard li.collection{margin:0 24px 0 8px!important}.bili-search .rocket-con{margin-left:40%!important}.bili-search .video.matrix:nth-child(5n){margin-right:32px!important}.dynamic-m .dyn_menu .line,.nav-wrap .hover-bar,.tab-bar .line{display:none!important}.tab-bar .tab .tab-text.selected{color:var(--theme-color)!important;border-bottom:2px solid!important;box-sizing:border-box!important}.live-panel .more-button{transform:translateX(-9px)!important}.bilibili-player-ending-panel-box-functions .bilibili-player-upinfo-spans>div{align-items:center!important}.dashboard li.collection>div:first-child,.user-panel-ctnr .user-panel .content-ctnr .section-block{display:flex!important;align-items:center!important;flex-direction:column!important}.dashboard li.share{display:inline-flex!important;align-items:center!important;flex-direction:column!important}.user-panel-ctnr .user-panel .content-ctnr .ctrl-btn{float:none!important}#area-list ul li dd{font-size:18px!important}.author-info .communicate-btn,.author-info .communicate-btn:active,.author-info .favourite-btn,.author-info .favourite-btn:active{font-size:12px!important} #page-follows .follow-sidenav .text,.admin-list-cntr .rank-cntr .item .admin-icon,.attention-btn-ctnr .left-part,.author-info .communicate-btn,.author-info .favourite-btn,.bili-search .nav-wrap .wrap>.sub,.dashboard li.like,.h .h-f-btn,.live-sidebar-ctnr .sidebar-btn,.n .n-data,.textarea-container .comm-tool .comm-emoji,.textarea-container .comm-tool .comm-submit,.up-info .up-focus-btn{width:auto!important}.bb-comment .comment-send .comment-emoji{width:max-content!important}.live-panel .more-button,.tag-panel .more-button{width:44px!important}.link-navbar .main-ctnr .nav-logo{width:70px!important}.bili-header-m .profile-m .grade .bar{width:160px!important}.bili-search .contain,.link-navbar .main-ctnr{width:90%!important}.bili-search .video.list{width:calc(100% - 172px)!important}.bili-search .video.list .des{width:100%!important}.gui-settings-box{width:450px!important}#page-follows .follow-sidenav .text{min-width:78px!important}.h .h-f-btn{min-width:76px!important}.primary-menu .nav-menu .nav-name,.primary-menu .nav-menu .side-nav .side-link span{white-space:pre!important}.admin-list-cntr .rank-cntr .item .admin-icon,.attention-btn-ctnr .left-part,.bb-comment .comment-send .comment-emoji,.h .h-f-btn,.textarea-container .comm-tool .comm-emoji,.textarea-container .comm-tool .comm-submit,.up-info .up-focus-btn{padding:0 8px!important}.n .n-data{padding:10px 8px!important}.user-panel-ctnr .user-panel .content-ctnr .ctrl-btn:nth-child(2n){padding-left:8px!important}.dashboard li.share .text{padding-top:15px!important}.dashboard li.collection{margin:0 10px 0 0!important}.bili-search .rocket-con{margin-left:40%!important}.bili-search .video.matrix:nth-child(5n){margin-right:32px!important}.dynamic-m .dyn_menu .line,.nav-wrap .hover-bar,.tab-bar .line{display:none!important}.tab-bar .tab .tab-text.selected{color:var(--theme-color)!important;border-bottom:2px solid!important;box-sizing:border-box!important}.live-panel .more-button{transform:translateX(-9px)!important}.bilibili-player-ending-panel-box-functions .bilibili-player-upinfo-spans>div{align-items:center!important}.dashboard li.collection>div:first-child,.user-panel-ctnr .user-panel .content-ctnr .section-block{display:flex!important;align-items:center!important;flex-direction:column!important}.dashboard li.share{display:inline-flex!important;align-items:center!important;flex-direction:column!important}.user-panel-ctnr .user-panel .content-ctnr .ctrl-btn{float:none!important}#area-list ul li dd{font-size:18px!important}.author-info .communicate-btn,.author-info .communicate-btn:active,.author-info .favourite-btn,.author-info .favourite-btn:active{font-size:12px!important}.dashboard li.like{border-color:transparent!important}

2
min/i18n.min.js vendored
View File

@ -1 +1 @@
(()=>{return(e,t)=>{const a={"日本語":"ja-JP",English:"en-US",Deutsch:"de-DE"};class r{accepts(e){return e.nodeType===Node.ELEMENT_NODE}getValue(e){return e.nodeValue}setValue(e,t){e.nodeValue=t}getElement(e){return e}translate(e){const t=this.getValue(e);if(!t||typeof t!=="string"||t==="*"){return}const a=r.map.get(t.trim());if(a===undefined){return}if(typeof a==="string"){this.setValue(e,a)}else if(Array.isArray(a)){let t=null;for(const r of a){if(typeof r==="string"){t=r}else{const{text:a,selector:s,not:l}=r;if(this.getElement(e).matches(s)!==Boolean(l)){t=a}}}if(t!==null){this.setValue(e,t)}}else{const{text:t,selector:r,not:s}=a;if(this.getElement(e).matches(r)!==Boolean(s)){this.setValue(e,t)}}}static walk(e,t){const a=document.createTreeWalker(e,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null,false);let r=a.nextNode();while(r){t(r);r=a.nextNode()}}static translate(e){if(e.nodeType===Node.TEXT_NODE){r.textNode.translate(e);return}r.walk(e,e=>{for(const t of r.allTranslators){if(t.accepts(e)){t.translate(e)}}})}static translateCssMatches(){const e=r.map.get("*");if(!e){return}for(const{selector:t,text:a}of e){const e=document.querySelector(t);if(e){[...e.childNodes].filter(e=>e.nodeType===Node.TEXT_NODE).forEach(e=>e.nodeValue=a)}}}}class s extends r{accepts(e){return e.nodeType===Node.TEXT_NODE}getElement(e){return e.parentElement}}class l extends r{getValue(e){return e.getAttribute("title")}setValue(e,t){e.setAttribute("title",t)}}class n extends r{getValue(e){return e.getAttribute("placeholder")}setValue(e,t){e.setAttribute("placeholder",t)}}r.textNode=new s;r.title=new l;r.placeholder=new n;r.allTranslators=[r.textNode,r.title,r.placeholder];(async()=>{const{map:s}=await t.importAsync(`i18n.${a[e.i18nLanguage]}`);r.map=s;r.translate(document.body);r.translateCssMatches();Observer.observe("body",e=>{e.forEach(e=>{if(e.type==="childList"){if(e.addedNodes.length>0){r.translateCssMatches()}e.addedNodes.forEach(e=>{r.translate(e)})}else if(e.type==="characterData"){r.textNode.translate(e.target)}})},{characterData:true,childList:true,subtree:true})})();return{export:{Translator:r,TextNodeTranslator:s,TitleTranslator:l,PlaceholderTranslator:n}}}})(); (()=>{return(e,t)=>{const a={"日本語":"ja-JP",English:"en-US",Deutsch:"de-DE"};class s{accepts(e){return e.nodeType===Node.ELEMENT_NODE}getValue(e){return e.nodeValue}setValue(e,t){e.nodeValue=t}getElement(e){return e}translate(e){const t=this.getValue(e);if(!t||typeof t!=="string"||t==="*"){return}const a=s.map.get(t.trim());if(a===undefined){const a=s.regex.find(([e])=>e.test(t));if(a){const[s,r]=a;this.setValue(e,t.replace(s,r))}}else if(typeof a==="string"){this.setValue(e,a)}else if(Array.isArray(a)){let t=null;for(const s of a){if(typeof s==="string"){t=s}else{const{text:a,selector:r,not:l}=s;if(this.getElement(e).matches(r)!==Boolean(l)){t=a}}}if(t!==null){this.setValue(e,t)}}else{const{text:t,selector:s,not:r}=a;if(this.getElement(e).matches(s)!==Boolean(r)){this.setValue(e,t)}}}static walk(e,t){const a=document.createTreeWalker(e,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null,false);let s=a.nextNode();while(s){t(s);s=a.nextNode()}}static translate(e){if(e.nodeType===Node.TEXT_NODE){s.textNode.translate(e);return}s.walk(e,e=>{for(const t of s.allTranslators){if(t.accepts(e)){t.translate(e)}}})}static translateCssMatches(){const e=s.map.get("*");if(!e){return}for(const{selector:t,text:a}of e){const e=document.querySelector(t);if(e){[...e.childNodes].filter(e=>e.nodeType===Node.TEXT_NODE).forEach(e=>e.nodeValue=a)}}}}class r extends s{accepts(e){return e.nodeType===Node.TEXT_NODE}getElement(e){return e.parentElement}}class l extends s{getValue(e){return e.getAttribute("title")}setValue(e,t){e.setAttribute("title",t)}}class n extends s{getValue(e){return e.getAttribute("placeholder")}setValue(e,t){e.setAttribute("placeholder",t)}}s.textNode=new r;s.title=new l;s.placeholder=new n;s.allTranslators=[s.textNode,s.title,s.placeholder];(async()=>{const{map:r,regex:l}=await t.importAsync(`i18n.${a[e.i18nLanguage]}`);s.map=r;s.regex=[...l.entries()];s.translate(document.body);s.translateCssMatches();Observer.observe("body",e=>{e.forEach(e=>{if(e.type==="childList"){if(e.addedNodes.length>0){s.translateCssMatches()}e.addedNodes.forEach(e=>{s.translate(e)})}else if(e.type==="characterData"){s.textNode.translate(e.target)}})},{characterData:true,childList:true,subtree:true})})();return{export:{Translator:s,TextNodeTranslator:r,TitleTranslator:l,PlaceholderTranslator:n}}}})();

View File

@ -44,6 +44,10 @@
{ {
width: 100% !important; width: 100% !important;
} }
.gui-settings-box
{
width: 450px !important;
}
#page-follows .follow-sidenav .text #page-follows .follow-sidenav .text
{ {
min-width: 78px !important; min-width: 78px !important;
@ -82,7 +86,7 @@
} }
.dashboard li.collection .dashboard li.collection
{ {
margin: 0px 24px 0 8px !important; margin: 0 10px 0 0px !important;
} }
.bili-search .rocket-con .bili-search .rocket-con
{ {
@ -142,3 +146,7 @@
{ {
font-size: 12px !important; font-size: 12px !important;
} }
.dashboard li.like
{
border-color: transparent !important;
}

View File

@ -4,6 +4,9 @@ export const map = new Map([
/* CSS translation here */ /* CSS translation here */
]], ]],
]); ]);
export const regex = new Map([
/* Regex translation here */
]);
export default { export default {
export: { map }, export: { map, regex },
}; };

View File

@ -172,6 +172,9 @@ export const map = new Map([
]], ]],
]); ]);
export const regex = new Map([
/* Regex translation here */
]);
export default { export default {
export: { map }, export: { map, regex },
}; };

View File

@ -11,158 +11,158 @@ export const map = new Map([
[`稍后再看`, `後で見る`], [`稍后再看`, `後で見る`],
[`收藏`, `お気に入り`], [`收藏`, `お気に入り`],
[`历史`, `視聴履歴`], [`历史`, `視聴履歴`],
[`关注`,`フォロー`], [`关注`, `フォロー`],
[`粉丝`,`ファン`], [`粉丝`, `ファン`],
[`更多`,`もっと`], [`更多`, `もっと`],
[`排行`,`ランキング`], [`排行`, `ランキング`],
[`图片`,`ピクチャ`], [`图片`, `ピクチャ`],
[`视频`,`ビデオ`], [`视频`, `ビデオ`],
[`番剧`,`番組`], [`番剧`, `番組`],
[`音乐`,`音楽`], [`音乐`, `音楽`],
[`时尚`,`潮流`], [`时尚`, `潮流`],
[`电影`,`劇場`], [`电影`, `劇場`],
[`影视`,`映画`], [`影视`, `映画`],
[`放映厅`,`映画館`], [`放映厅`, `映画館`],
[`广告`,`広告`], [`广告`, `広告`],
[`广场`,`広場`], [`广场`, `広場`],
[`发布`,`発表`], [`发布`, `発表`],
[`举报`,`通報`], [`举报`, `通報`],
[`首页`,`ホーム`], [`首页`, `ホーム`],
[`热门`,`人気`], [`热门`, `人気`],
[`周一`,``], [`周一`, ``],
[`周二`,``], [`周二`, ``],
[`周三`,``], [`周三`, ``],
[`周四`,``], [`周四`, ``],
[`周五`,``], [`周五`, ``],
[`周六`,``], [`周六`, ``],
[`周日`,``], [`周日`, ``],
[`发送`,`送信`], [`发送`, `送信`],
[`取消`,`取り消し`], [`取消`, `取り消し`],
[`关闭`,`閉じる`], [`关闭`, `閉じる`],
[`表情`,`ステッカー`], [`表情`, `ステッカー`],
[`小视频`,`短いビデオ`], [`小视频`, `短いビデオ`],
[`查看更多`,`もっと見る`], [`查看更多`, `もっと見る`],
[`查看全部`,`すべて表示`], [`查看全部`, `すべて表示`],
[`播放历史`, `視聴履歴`], [`播放历史`, `視聴履歴`],
[`删除`,`削除`], [`删除`, `削除`],
[`确认`,`確認`], [`确认`, `確認`],
[`取消关注`,`フォロー解除`], [`取消关注`, `フォロー解除`],
[`全部`,`全て`], [`全部`, `全て`],
[`投稿视频`,`ビデオ`], [`投稿视频`, `ビデオ`],
[`公告栏`,`掲示板`], [`公告栏`, `掲示板`],
[`正在直播`,`生放送中`], [`正在直播`, `生放送中`],
[`虚拟主播`,`Vtuber`], [`虚拟主播`, `Vtuber`],
[`房间标题`,`タイトル`], [`房间标题`, `タイトル`],
[`设置`,`設定`], [`设置`, `設定`],
[`频道`,`チャンネル`], [`频道`, `チャンネル`],
[`标签`,`タグ`], [`标签`, `タグ`],
[`关注数`,`フォロー数`], [`关注数`, `フォロー数`],
[`粉丝数`,`ファン数`], [`粉丝数`, `ファン数`],
[`相簿`,`アルバム`], [`相簿`, `アルバム`],
[`我的频道`,`私のチャンネル`], [`我的频道`, `私のチャンネル`],
[`我的视频`,`私のビデオ`], [`我的视频`, `私のビデオ`],
[`我的音频`,`私の音楽`], [`我的音频`, `私の音楽`],
[`我的音乐`,`私の音楽`], [`我的音乐`, `私の音楽`],
[`我的专栏`,`私のコラム`], [`我的专栏`, `私のコラム`],
[`我的相簿`,`私のアルバム`], [`我的相簿`, `私のアルバム`],
[`我的关注`,`私のフォロー`], [`我的关注`, `私のフォロー`],
[`我的粉丝`,`私のファン`], [`我的粉丝`, `私のファン`],
[`我的消息`,`DM`], [`我的消息`, `DM`],
[`系统通知`,`システム`], [`系统通知`, `システム`],
[`网游`,`オンライン`], [`网游`, `オンライン`],
[`手游`,`モバイル`], [`手游`, `モバイル`],
[`单机`,`単機ゲーム`], [`单机`, `単機ゲーム`],
[`电台`,`ラジオ`], [`电台`, `ラジオ`],
[`绘画`,`絵画`], [`绘画`, `絵画`],
[`热门话题`,`人気話題`], [`热门话题`, `人気話題`],
[`热门排行`,`人気ランキング`], [`热门排行`, `人気ランキング`],
[`我关注的话题`,`私の話題`], [`我关注的话题`, `私の話題`],
[`有什么想和大家分享的?`,`何をみんなと共有したいのですか`], [`有什么想和大家分享的?`, `何をみんなと共有したいのですか`],
[`有新动态,点击查看`,`新しい情報がある、クリックして見る`], [`有新动态,点击查看`, `新しい情報がある、クリックして見る`],
[`刚刚`,`さっき`], [`刚刚`, `さっき`],
[`转发动态`,`転送した`], [`转发动态`, `転送した`],
[`转发`,`転送`], [`转发`, `転送`],
[`投稿了`,`投稿した`], [`投稿了`, `投稿した`],
[`历史动态`,`歴史情報`], [`历史动态`, `歴史情報`],
[`在线人数`,`オンライン`], [`在线人数`, `オンライン`],
[`追番`,`番組`], [`追番`, `番組`],
[`评论`,`コメント`], [`评论`, `コメント`],
[`新番时间表`,`番組時間表`], [`新番时间表`, `番組時間表`],
[`小黑屋`,`公開処刑`], [`小黑屋`, `公開処刑`],
[`摄影`,`撮影`], [`摄影`, `撮影`],
[`其他`,`他の`], [`其他`, `他の`],
[`下载`,`ダウンロード`], [`下载`, `ダウンロード`],
[`更新了`,`更新した`], [`更新了`, `更新した`],
[`排行榜`,`ランキング`], [`排行榜`, `ランキング`],
[`推荐`,`推薦`], [`推荐`, `推薦`],
[`播放`,`再生`], [`播放`, `再生`],
[`弹幕`,`弾幕`], [`弹幕`, `弾幕`],
[`已结束`,`終わり`], [`已结束`, `終わり`],
[`电视剧`,`ドラマ`], [`电视剧`, `ドラマ`],
[`上一页`,`前へ`], [`上一页`, `前へ`],
[`下一页`,`次へ`], [`下一页`, `次へ`],
[`搜索`,`検索`], [`搜索`, `検索`],
[`直播中`,`生放送中`], [`直播中`, `生放送中`],
[`个人中心`,`個人センター`], [`个人中心`, `個人センター`],
[`等级`,`レベル`], [`等级`, `レベル`],
[`直播中心`,`生放送センター`], [`直播中心`, `生放送センター`],
[`主页`,`ホーム`], [`主页`, `ホーム`],
[`排序`,`序列`], [`排序`, `序列`],
[`移除`,`削除`], [`移除`, `削除`],
[`复制`,`コピー`], [`复制`, `コピー`],
[`换一换`,`更新`], [`换一换`, `更新`],
[`特别推荐`,`特別推薦`], [`特别推荐`, `特別推薦`],
[`热门榜单`,`人気ランキング`], [`热门榜单`, `人気ランキング`],
[`播放全部`,`すべて放送`], [`播放全部`, `すべて放送`],
[`观看历史`,`視聴履歴`], [`观看历史`, `視聴履歴`],
[`个人收益`,`個人収益`], [`个人收益`, `個人収益`],
[`同时转发到我的动态`,`同時に転送もする`], [`同时转发到我的动态`, `同時に転送もする`],
[`人气值`,`人気値`], [`人气值`, `人気値`],
[`话题`,`話題`], [`话题`, `話題`],
[`活动`,`活動`], [`活动`, `活動`],
[`活动中心`,`活動中心`], [`活动中心`, `活動中心`],
[`消息中心`,`ニュースセンター`], [`消息中心`, `ニュースセンター`],
[`专栏投稿`,`コラム`], [`专栏投稿`, `コラム`],
[`音频投稿`,`音楽`], [`音频投稿`, `音楽`],
[`视频投稿`,`ビデオ`], [`视频投稿`, `ビデオ`],
[`相簿投稿`,`アルバム`], [`相簿投稿`, `アルバム`],
[`上传视频`,`アップロード`], [`上传视频`, `アップロード`],
[`退出登录`,`ログアウト`], [`退出登录`, `ログアウト`],
[`回复我的`,`返信`], [`回复我的`, `返信`],
[`领取`,`受け取り`], [`领取`, `受け取り`],
[`样式`,`スタイル`], [`样式`, `スタイル`],
[`工具`,`道具`], [`工具`, `道具`],
[`触摸`,`タッチスクリーン`], [`触摸`, `タッチスクリーン`],
[`指定播放器布局`,'プレーヤーレイアウト'], [`指定播放器布局`, 'プレーヤーレイアウト'],
[`视频区布局`,`ビデオ`], [`视频区布局`, `ビデオ`],
[`番剧区布局`,`番組`], [`番剧区布局`, `番組`],
[`使用默认播放器模式`,`プレーヤーモード`], [`使用默认播放器模式`, `プレーヤーモード`],
[`默认播放器模式`,`デフォルト・モード`], [`默认播放器模式`, `デフォルト・モード`],
[`播放时应用模式`,`再生時に使う`], [`播放时应用模式`, `再生時に使う`],
[`播放时自动关灯`,`再生時はライトを消す`], [`播放时自动关灯`, `再生時はライトを消す`],
[`使用默认视频画质`,`映像画質`], [`使用默认视频画质`, `映像画質`],
[`画质设定`,`画質設定`], [`画质设定`, `画質設定`],
[`使用默认弹幕设置`,`弾幕設定`], [`使用默认弹幕设置`, `弾幕設定`],
[`开启弹幕`,`弾幕を開ける`], [`开启弹幕`, `弾幕を開ける`],
[`记住弹幕设置`,'シールド設定を覚える'], [`记住弹幕设置`, 'シールド設定を覚える'],
[`自动展开弹幕列表`,`弾幕のリストを展開する`], [`自动展开弹幕列表`, `弾幕のリストを展開する`],
[`自动展开视频简介`,`ビデオ紹介を展開する`], [`自动展开视频简介`, `ビデオ紹介を展開する`],
[`自动从历史记录点播放`,`歴史記録から再生します`], [`自动从历史记录点播放`, `歴史記録から再生します`],
[`自动播放视频`,`ビデオを自動再生する`], [`自动播放视频`, `ビデオを自動再生する`],
[`跳过充电鸣谢`,`エンディングをスキップ`], [`跳过充电鸣谢`, `エンディングをスキップ`],
[`启用逐帧调整`,`フレーム毎に調整する`], [`启用逐帧调整`, `フレーム毎に調整する`],
[`主题颜色`,`テーマカラー`], [`主题颜色`, `テーマカラー`],
[`样式调整`,`スタイルの調整`], [`样式调整`, `スタイルの調整`],
[`顶栏(对横幅)透明度`,`(横断幕に)トップバーの透明度`], [`顶栏(对横幅)透明度`, `(横断幕に)トップバーの透明度`],
[`夜间模式`,`ナイトモード`], [`夜间模式`, `ナイトモード`],
[`夜间模式计划时段`,`ナイトモード计画タイム`], [`夜间模式计划时段`, `ナイトモード计画タイム`],
[`首页使用紧凑布局`,`トップページにコンパクトなレイアウトを使う`], [`首页使用紧凑布局`, `トップページにコンパクトなレイアウトを使う`],
[`简化评论区`,`コメントエリアの簡潔化`], [`简化评论区`, `コメントエリアの簡潔化`],
[`简化直播间`,`生放送ページの簡潔化`], [`简化直播间`, `生放送ページの簡潔化`],
[`搜索栏置顶`,`検索欄がトップになる`], [`搜索栏置顶`, `検索欄がトップになる`],
[`显示顶部横幅`,`トップの横断幕を表示する`], [`显示顶部横幅`, `トップの横断幕を表示する`],
[`显示排行榜图标`,`ランキングのアイコンを表示する`], [`显示排行榜图标`, `ランキングのアイコンを表示する`],
[`模糊视频控制栏背景`,`ビデオ制御欄の背景がぼやける`], [`模糊视频控制栏背景`, `ビデオ制御欄の背景がぼやける`],
[`动画`, { [`动画`, {
selector: `.elevator-module .nav-list .item`, selector: `.elevator-module .nav-list .item`,
not: true, not: true,
@ -223,99 +223,102 @@ export const map = new Map([
not: true, not: true,
text: `全画面`, text: `全画面`,
}], }],
[`登录`,`ログイン`], [`登录`, `ログイン`],
[`注册`,`登録`], [`注册`, `登録`],
[`我的直播间`,`私のスタジオ`], [`我的直播间`, `私のスタジオ`],
[`直播间`,`スタジオ`], [`直播间`, `スタジオ`],
[`订阅`,`登録チャンネル`], [`订阅`, `登録チャンネル`],
[`主站空间`,`個人センター`], [`主站空间`, `個人センター`],
[`播放数`,`再生数`], [`播放数`, `再生数`],
[`综合`,`すべて`], [`综合`, `すべて`],
[`用户`,`ユーザー`], [`用户`, `ユーザー`],
[`投稿管理`,`ダッシュボード`], [`投稿管理`, `ダッシュボード`],
[`个人信息`,`個人情報`], [`个人信息`, `個人情報`],
[`开播设置`,`放送設定`], [`开播设置`, `放送設定`],
[`直播分类`,`カテゴリ`], [`直播分类`, `カテゴリ`],
[`修改分区`,`カテゴリを変更`], [`修改分区`, `カテゴリを変更`],
[`房间标题`,`タイトル`], [`房间标题`, `タイトル`],
[`开始直播`,`放送開始`], [`开始直播`, `放送開始`],
[`停止直播`,`放送中止`], [`停止直播`, `放送中止`],
[`主播公告`,`チャンネル公告`], [`主播公告`, `チャンネル公告`],
[`简介`,`概要`], [`简介`, `概要`],
[`直播封面`,`サムネイル`], [`直播封面`, `サムネイル`],
[`我的个人标签`,`私のタグ`], [`我的个人标签`, `私のタグ`],
[`个人简介`,`概要`], [`个人简介`, `概要`],
[`直播间信息`,`スタジオ情報`], [`直播间信息`, `スタジオ情報`],
[`我的船员`,`私のクルー`], [`我的船员`, `私のクルー`],
[`直播数据`,`アナリティクス`], [`直播数据`, `アナリティクス`],
[`数据总览`,`データ概要`], [`数据总览`, `データ概要`],
[`直播时长`,`総再生時間`], [`直播时长`, `総再生時間`],
[`最高人气值`,`最大人気値`], [`最高人气值`, `最大人気値`],
[`金仓鼠`,`金ハムスター`], [`金仓鼠`, `金ハムスター`],
[`贝壳`,`貝殻`], [`贝壳`, `貝殻`],
[`直播收益(金仓鼠)`,`投げ銭(金ハムスター)`], [`直播收益(金仓鼠)`, `投げ銭(金ハムスター)`],
[`直播收益`,`投げ銭`], [`直播收益`, `投げ銭`],
[`新增关注数`,`新しい登録者`], [`新增关注数`, `新しい登録者`],
[`人均观看时长`,`平均視聴時間`], [`人均观看时长`, `平均視聴時間`],
[`礼物流水`,`ギフト記録`], [`礼物流水`, `ギフト記録`],
[`礼物统计`,`ギフト一覧`], [`礼物统计`, `ギフト一覧`],
[`消费排行`,`ランキング`], [`消费排行`, `ランキング`],
[`更多>>`,`もっと>>`], [`更多>>`, `もっと>>`],
[`主播`,`配信者`], [`主播`, `配信者`],
[`未开播`,`待機中`], [`未开播`, `待機中`],
[`金瓜子`,`金ヒマワリの種`], [`金瓜子`, `金ヒマワリの種`],
[`银瓜子`,`銀ヒマワリの種`], [`银瓜子`, `銀ヒマワリの種`],
[`残忍取关`,`フォロー解除`], [`残忍取关`, `フォロー解除`],
[`再考虑一下`,`考え直す`], [`再考虑一下`, `考え直す`],
[`已关注`,`フォロー中`], [`已关注`, `フォロー中`],
[`七日榜`,`週間rank`], [`七日榜`, `週間rank`],
[`舰队`,`艦隊`], [`舰队`, `艦隊`],
[`房管`,`管理者`], [`房管`, `管理者`],
[`分享`,`シェア`], [`分享`, `シェア`],
[`轮播`,`再放送`], [`轮播`, `再放送`],
[`闲置`,`待機中`], [`闲置`, `待機中`],
[`回复`,`リプレイ`], [`回复`, `リプレイ`],
[`查看更多评论`,`もっと見る`], [`查看更多评论`, `もっと見る`],
[`英雄联盟`,`LOL`], [`英雄联盟`, `LOL`],
[`APEX英雄`,`Apex Legends`], [`APEX英雄`, `Apex Legends`],
[`守望先锋`,`Overwatch`], [`守望先锋`, `Overwatch`],
[`绝地求生`,`PUBG`], [`绝地求生`, `PUBG`],
[`王者荣耀`,`伝説対決`], [`王者荣耀`, `伝説対決`],
[`第五人格`,`Identity V`], [`第五人格`, `Identity V`],
[`绝地求生:刺激战场`,`PUBG Mobile`], [`绝地求生:刺激战场`, `PUBG Mobile`],
[`崩坏3`,`崩壊3rd`], [`崩坏3`, `崩壊3rd`],
[`主机游戏`,`テレビゲーム`], [`主机游戏`, `テレビゲーム`],
[`我的世界`,`マイクラ`], [`我的世界`, `マイクラ`],
[`怪物猎人:世界`,`モンハンワールド`], [`怪物猎人:世界`, `モンハンワールド`],
[`只狼:影逝二度`,`SEKIRO/隻狼`], [`只狼:影逝二度`, `SEKIRO/隻狼`],
[`鬼泣5`,`デビルメイクライ5`], [`鬼泣5`, `デビルメイクライ5`],
[`视频唱见`,`顔出し歌枠`], [`视频唱见`, `顔出し歌枠`],
[`舞见`,`踊り枠`], [`舞见`, `踊り枠`],
[`视频聊天`,`顔出し雑談枠`], [`视频聊天`, `顔出し雑談枠`],
[`才艺`,`タレントショー`], [`才艺`, `タレントショー`],
[`唱见电台`,`歌枠`], [`唱见电台`, `歌枠`],
[`声优`,`声優`], [`声优`, `声優`],
[`聊天电台`,`雑談枠`], [`聊天电台`, `雑談枠`],
[`同人绘画`,`同人`], [`同人绘画`, `同人`],
[`原创绘画`,`オリジナル`], [`原创绘画`, `オリジナル`],
[`临摹绘画`,`模写`], [`临摹绘画`, `模写`],
[`其他绘画`,`他の絵`], [`其他绘画`, `他の絵`],
[`扭蛋机`,`ガチャ`], [`扭蛋机`, `ガチャ`],
[`我关注的直播`,`フォローした配信`], [`我关注的直播`, `フォローした配信`],
[`我关注的动态`,`フォローした情報`], [`我关注的动态`, `フォローした情報`],
[`按热度排序`,`人気多い順位`], [`按热度排序`, `人気多い順位`],
[`全部评论`,`すべて`], [`全部评论`, `すべて`],
[`发消息`,`DMを送る`], [`发消息`, `DMを送る`],
[`点赞`,`いいね!`], [`点赞`, `いいね!`],
[`浏览`,`閲覧数`], [`浏览`, `閲覧数`],
[`收藏`,`ブックマーク`], [`收藏`, `ブックマーク`],
[`支持`,`いいね!`], [`支持`, `いいね!`],
[`发表评论`,`コメント`], [`发表评论`, `コメント`],
[`*`, [ [`*`, [
/* CSS translation here */ /* CSS translation here */
]], ]],
]); ]);
export const regex = new Map([
[/浏览:([0-9\.a-z])/, `閲覧数:$1`],
]);
export default { export default {
export: { map }, export: { map, regex },
}; };

View File

@ -15,9 +15,13 @@ export class Translator {
} }
const translation = Translator.map.get(value.trim()); const translation = Translator.map.get(value.trim());
if (translation === undefined) { if (translation === undefined) {
return; const result = Translator.regex.find(([r]) => r.test(value));
if (result) {
const [regex, replacement] = result;
this.setValue(node, value.replace(regex, replacement));
} }
if (typeof translation === "string") { }
else if (typeof translation === "string") {
this.setValue(node, translation); this.setValue(node, translation);
} }
else if (Array.isArray(translation)) { else if (Array.isArray(translation)) {
@ -103,8 +107,9 @@ Translator.title = new TitleTranslator;
Translator.placeholder = new PlaceholderTranslator; Translator.placeholder = new PlaceholderTranslator;
Translator.allTranslators = [Translator.textNode, Translator.title, Translator.placeholder]; Translator.allTranslators = [Translator.textNode, Translator.title, Translator.placeholder];
(async () => { (async () => {
const { map } = await import(`./i18n.${languageCodeMap[settings.i18nLanguage]}`); const { map, regex } = await import(`./i18n.${languageCodeMap[settings.i18nLanguage]}`);
Translator.map = map; Translator.map = map;
Translator.regex = [...regex.entries()];
Translator.translate(document.body); Translator.translate(document.body);
Translator.translateCssMatches(); Translator.translateCssMatches();
Observer.observe("body", records => { Observer.observe("body", records => {

View File

@ -22,11 +22,14 @@ export const map = new Map([
/* CSS translation here */ /* CSS translation here */
]], ]],
]); ]);
export const regex = new Map([
/* Regex translation here */
]);
export default { export default {
export: { map }, export: { map, regex },
}; };
``` ```
3. 在`/* Your translation here */`上方添加翻译, 或在`/* CSS translation here */`上方添加选择器翻译, 详细语法见下一节. 3. 在`/* Your translation here */`上方添加翻译, 或在`/* CSS translation here */`上方添加选择器翻译, 在`/* Regex translation here */`上方添加正则翻译, 详细语法见下一节.
## 翻译语法 ## 翻译语法
有多种翻译方式可供选择. 有多种翻译方式可供选择.
@ -170,6 +173,21 @@ export default {
<a class="xxx yyy">Home3</a> <a class="xxx yyy">Home3</a>
``` ```
### 使用正则翻译
当原文本包含一段不确定内容时, 可以使用正则翻译来匹配, 需要翻译者对正则表达式有一定了解. 这种翻译放在这一区域: (`export const regex`)
```js
export const regex = new Map([
/* Regex translation here */
]);
```
例如, 要将`浏览23.3w`翻译为`Read: 23.3w`, 则添加:
```js
[/浏览:([0-9\.a-z])/, `Read: $1`],
```
第一个元素是正则表达式, 用一对斜杠(`/`)包围, 语法可在[MDN文档](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions)中学习. 第二个元素是替换文本. 在这个例子中, `$1`指代原文本中的浏览量数字, 利用了正则表达式的分组功能, 详见文档中的["使用括号的子字符串匹配"](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions#%E4%BD%BF%E7%94%A8%E6%8B%AC%E5%8F%B7%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D_2)一节.
## 调整界面元素 ## 调整界面元素
一些界面元素的尺寸是固定大小, 如果添加翻译后, 无法适应翻译后的文本长度, 可以在`i18n.css`中添加CSS样式来调整. 一些界面元素的尺寸是固定大小, 如果添加翻译后, 无法适应翻译后的文本长度, 可以在`i18n.css`中添加CSS样式来调整.
@ -202,8 +220,12 @@ export const map = new Map([
/* CSS translation here */ /* CSS translation here */
]], ]],
]); ]);
export const regex = new Map([
[/(\d+)次播放/, `Played $1 times`],
/* Regex translation here */
]);
export default { export default {
export: { map }, export: { map, regex },
}; };
``` ```
该文件能够将类似以下的网页内容 该文件能够将类似以下的网页内容
@ -217,6 +239,7 @@ export default {
<a class="xxx">其他</a> <a class="xxx">其他</a>
<a class="yyy">其他</a> <a class="yyy">其他</a>
<a class="zzz">其他</a> <a class="zzz">其他</a>
<a>233次播放</a>
``` ```
翻译为 翻译为
```html ```html
@ -228,5 +251,5 @@ export default {
<a class="ccc">Follow</a> <a class="ccc">Follow</a>
<a class="xxx">XXX</a> <a class="xxx">XXX</a>
<a class="yyy">YYY</a> <a class="yyy">YYY</a>
<a class="zzz">其他</a> <a>Played 233 times</a>
``` ```

View File

@ -10,6 +10,7 @@ export class Translator
static placeholder: PlaceholderTranslator; static placeholder: PlaceholderTranslator;
static allTranslators: Translator[]; static allTranslators: Translator[];
static map: Map<string, any>; static map: Map<string, any>;
static regex: [RegExp, string][];
accepts(node: Node) { return node.nodeType === Node.ELEMENT_NODE; } accepts(node: Node) { return node.nodeType === Node.ELEMENT_NODE; }
getValue(node: Node) { return node.nodeValue; } getValue(node: Node) { return node.nodeValue; }
@ -25,9 +26,14 @@ export class Translator
const translation = Translator.map.get(value.trim()); const translation = Translator.map.get(value.trim());
if (translation === undefined) if (translation === undefined)
{ {
return; const result = Translator.regex.find(([r]) => r.test(value));
if (result)
{
const [regex, replacement] = result;
this.setValue(node, value.replace(regex, replacement));
} }
if (typeof translation === "string") }
else if (typeof translation === "string")
{ {
this.setValue(node, translation); this.setValue(node, translation);
} }
@ -142,8 +148,9 @@ Translator.allTranslators = [Translator.textNode, Translator.title, Translator.p
(async () => (async () =>
{ {
const { map } = await import(`./i18n.${languageCodeMap[settings.i18nLanguage]}`); const { map, regex } = await import(`./i18n.${languageCodeMap[settings.i18nLanguage]}`);
Translator.map = map; Translator.map = map;
Translator.regex = [...regex.entries()];
Translator.translate(document.body); Translator.translate(document.body);
Translator.translateCssMatches(); Translator.translateCssMatches();