From f8eff2afebe9c675ba7fb1ec4511e30cf0edb573 Mon Sep 17 00:00:00 2001 From: the1812 Date: Wed, 27 Mar 2019 17:25:19 +0800 Subject: [PATCH] Add german and traditional chinese --- bilibili-evolved.offline.user.js | 14 +- bilibili-evolved.preview-offline.user.js | 14 +- bilibili-evolved.preview.user.js | 8 + bilibili-evolved.user.js | 8 + client/resource-loader.js | 1 + client/resource-manager.js | 1 + client/resource-manifest.js | 6 + min/i18n.de-DE.min.js | 1 + min/i18n.min.js | 2 +- min/i18n.zh-TW.min.js | 1 + utils/i18n/i18n.de-DE.js | 9 + utils/i18n/i18n.js | 285 ++++++++++++----------- utils/i18n/i18n.zh-TW.js | 9 + 13 files changed, 220 insertions(+), 139 deletions(-) create mode 100644 min/i18n.de-DE.min.js create mode 100644 min/i18n.zh-TW.min.js create mode 100644 utils/i18n/i18n.de-DE.js create mode 100644 utils/i18n/i18n.zh-TW.js diff --git a/bilibili-evolved.offline.user.js b/bilibili-evolved.offline.user.js index 9f6e8862e..1760c53c3 100644 --- a/bilibili-evolved.offline.user.js +++ b/bilibili-evolved.offline.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name Bilibili Evolved (Offline) -// @version 253.91 +// @version 254.07 // @description Bilibili Evolved 的离线版, 所有功能都已内置于脚本中. // @author Grant Howard, Coulomb-G // @copyright 2019, Grant Howard (https://github.com/the1812) & Coulomb-G (https://github.com/Coulomb-G) @@ -360,6 +360,7 @@ function loadResources() { const resource = new Resource(data.path, data.styles); resource.key = key; + resource.dropdown = data.dropdown; if (data.displayNames) { resource.displayName = data.displayNames[key]; @@ -868,10 +869,12 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/gui-settings.min.js"] = (()=>{return(e,t)=>{const{ThemeColors:n}=t.import("theme-colors");const{SettingsSearch:i}=t.import("settings-search");const{Validator:c}=t.import("text-validate");function o(e){let t=e.nextElementSibling;const n=[];while(t!==null&&!t.classList.contains("category")){n.push(t);t=t.nextElementSibling}return n}function r(e,t){const n=document.querySelector(`input[type='checkbox'][key='${e}']`);if(n){n.checked=t;return}const i=document.querySelector(`input[type='text'][key='${e}']`);if(i){i.value=t;return}}function s(){for(const[t,n]of Object.entries(e)){r(t,n)}}function u(){document.querySelector(".gui-settings-mask").addEventListener("click",()=>{document.querySelectorAll(".gui-settings-widgets-box,.gui-settings-box,.gui-settings-mask").forEach(e=>e.classList.remove("opened"))});document.querySelectorAll("input[type='text'][key]").forEach(t=>{t.setAttribute("placeholder",e[t.getAttribute("key")])});document.querySelectorAll(".gui-settings-content ul li.category").forEach(e=>{e.addEventListener("click",e=>{const t=document.querySelector(".gui-settings-search");if(t.value!==""){t.value="";raiseEvent(t,"input")}e.currentTarget.classList.toggle("folded");o(e.currentTarget).forEach(e=>e.classList.toggle("folded"))})});document.querySelectorAll(".gui-settings-dropdown>input").forEach(e=>{e.addEventListener("click",e=>{e.currentTarget.parentElement.classList.toggle("opened")})});onSettingsChange((t,n,i)=>{if(e[t]!==i){e[t]=i;const n=document.querySelector(`input[type='checkbox'][key='${t}']`);if(n){n.checked=i;raiseEvent(n,"change");return}const c=document.querySelector(`input[type='text'][key='${t}']`);if(c){c.value=i;raiseEvent(c,"change");return}}})}function l(){const t=e=>{};document.querySelectorAll("input[type='checkbox'][key]").forEach(n=>{n.addEventListener("change",()=>{const i=n.getAttribute("key");const c=n.checked;e[i]=c;t(i);saveSettings(e)})});document.querySelectorAll("input[type='text'][key]").forEach(n=>{n.addEventListener("change",()=>{const i=n.getAttribute("key");const o=c.getValidator(i).validate(n.value);e[i]=o;n.value=o;t(i);saveSettings(e)})})}function a(){const e={};document.querySelectorAll(`input[dependencies]`).forEach(t=>{const n=t.getAttribute("dependencies");if(n){e[t.getAttribute("key")]=n}});const t=t=>{const n=t.checked;for(const i in e){const c=e[i].split(" ");if(c.indexOf(t.getAttribute("key"))!==-1){let e=true;if(n&&c.every(e=>document.querySelector(`input[key='${e}']`).checked)){e=false}let t=document.querySelector(`input[key='${i}']`);while(t.nodeName.toLowerCase()!=="li"){t=t.parentElement}const o=e?"add":"remove";t.classList[o]("disabled");const r=document.querySelector(`input[key='${i}'][type='text']`);r&&r.parentElement.classList[o]("disabled")}}};document.querySelectorAll(`input[type='checkbox'][key]`).forEach(e=>{e.addEventListener("change",e=>t(e.target));t(e)})}function d(){if(typeof offlineData!=="undefined"){document.querySelector(".gui-settings-checkbox-container>input[key=useCache]").parentElement.parentElement.classList.add("disabled");document.querySelector("input[key=useCache]").disabled=true}}function y(){document.querySelectorAll(".gui-settings-content ul li.category").forEach(e=>{e.click()})}function g(){if(!CSS.supports("backdrop-filter","blur(24px)")&&!CSS.supports("-webkit-backdrop-filter","blur(24px)")){document.querySelector("input[key=blurVideoControl]").disabled=true;e.blurVideoControl=false;saveSettings(e)}if(window.devicePixelRatio===1){document.querySelector("input[key=harunaScale]").disabled=true;e.harunaScale=false;saveSettings(e)}if(e.defaultPlayerLayout==="旧版"){const t=document.querySelector("input[key=overrideNavBar]");t.disabled=true;raiseEvent(t,"change");if(e.overrideNavBar){t.checked=false;raiseEvent(t,"change");e.overrideNavBar=false;saveSettings(e)}}}function p(){for(const[e,t]of Object.entries(Resource.displayNames)){const n=document.querySelector(`input[key=${e}]`);if(!n){continue}switch(n.type){case"checkbox":n.nextElementSibling.nextElementSibling.innerHTML=t;break;case"text":const e=n.parentElement;if(e.classList.contains("gui-settings-textbox-container")){n.previousElementSibling.innerHTML=t}else if(e.classList.contains("gui-settings-dropdown")){e.previousElementSibling.innerHTML=t}break;default:break}}}(async()=>{t.applyStyle("guiSettingsStyle");const e=(t.data.guiSettingsDom||t.data.guiSettingsHtml).text;document.body.insertAdjacentHTML("beforeend",e);new SpinQuery(()=>document.body,e=>e&&!(unsafeWindow.parent.window===unsafeWindow),e=>document.querySelector(".gui-settings-icon-panel").style.display="none").start();u();d();s();a();l();y();g();p();(new n).setupDom();new i})()}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/haruna-scale.min.js"] = (()=>{return(n,t)=>{const a="bilibili-haruna-scale";if($(a).length===0){t.applyStyleFromText(`\n \n `)}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/hide-top-search.min.js"] = (()=>{return(e,r)=>{const t=[".nav-search-keyword",".search-keyword"];for(const e of t){new SpinQuery(()=>$(e),e=>e!==undefined&&e.length>0&&e.attr("placeholder").length>0,e=>e.attr("placeholder","搜索")).start()}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.de-DE.min.js"] = (()=>{return(r,e)=>{const n=new Map([[`*`,[]]]);return{export:{map:n}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.en-US.min.js"] = (()=>{return(e,o)=>{const t=new Map([[`主站`,`Home`],[`画友`,`Painting`],[`音频`,`Music`],[`游戏中心`,`Game`],[`直播`,`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`],[`专栏`,`Blog`],[`转发`,`Forward`],[`评论`,`Reviews`],[`赞`,`Like`],[`视角:`,`View: `],[`我自己`,`Myself`],[`新访客`,`New visitors`],[`我的粉丝`,`Followers`],[`暂时没有新动态了哦!`,`Nothing new at this moment...`],[`历史动态`,`History`],[`投稿了`,`posted`],[`更新了`,`updated`],[`番剧`,`Bangumi`],[`样式`,`Style`],[`工具`,`Tools`],[`触摸`,`Touch`],[`其他`,`Other`],[`正在直播`,`Live broadcasting`],[`投稿视频`,`Posted video`],[`展开全文`,`Expand`],[`*`,[]]]);return{export:{map:t}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.ja-JP.min.js"] = (()=>{return(r,e)=>{const n=new Map([[`主站`,`ホーム`],[`画友`,`絵画`],[`音频`,`音楽`],[`游戏中心`,`ゲーム`],[`直播`,`生放送`],[`会员购`,`ショップ`],[`漫画`,`漫画`],[`下载APP`,`アプリ`],[`大会员`,`会員`],[`消息`,`通知`],[`动态`,`マイフィード`],[`稍后再看`,`後で鑑賞`],[`收藏`,`お気に入り`],[`历史`,`視聴履歴`],[`投稿`,`投稿`],[`*`,[]]]);return{export:{map:n}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.min.css"] = `.up-info .up-focus-btn{width:auto!important;padding:0 4px!important}`; -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.min.js"] = (()=>{return(e,t)=>{(async()=>{const s={"日本語":"ja-JP",English:"en-US"};const{map:a}=await t.importAsync(`i18n.${s[e.i18nLanguage]}`);class n{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"){return}const s=a.get(t.trim());if(s===undefined){return}if(typeof s==="string"){this.setValue(e,s)}else if(Array.isArray(s)){let t=null;for(const a of s){if(typeof a==="string"){t=a}else{const{text:s,selector:n}=a;if(this.getElement(e).matches(n)){t=s}}}if(t!==null){this.setValue(e,t)}}else{const{text:t,selector:a}=s;if(this.getElement(e).matches(a)){this.setValue(e,t)}}}static walk(e,t){const s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null,false);let a=s.nextNode();while(a){t(a);a=s.nextNode()}}static translate(e){if(e.nodeType===Node.TEXT_NODE){n.textNode.translate(e);return}n.walk(e,e=>{for(const t of n.allTranslators){if(t.accepts(e)){t.translate(e)}}})}static translateCssMatches(){const e=a.get("*");if(!e){return}for(const{selector:t,text:s}of e){const e=document.querySelector(t);if(e){[...e.childNodes].filter(e=>e.nodeType===Node.TEXT_NODE).forEach(e=>e.nodeValue=s)}}}}class r extends n{accepts(e){return e.nodeType===Node.TEXT_NODE}getElement(e){return e.parentElement}}class l extends n{getValue(e){return e.getAttribute("title")}setValue(e,t){e.setAttribute("title",t)}}class o extends n{accepts(e){return e.nodeName==="INPUT"&&e.type.toUpperCase()==="TEXT"||e.nodeName==="TEXTAREA"}getValue(e){return e.getAttribute("placeholder")}setValue(e,t){e.setAttribute("placeholder",t)}}n.textNode=new r;n.title=new l;n.placeholder=new o;n.allTranslators=[n.textNode,n.title,n.placeholder];n.translate(document.body);n.translateCssMatches();Observer.childListSubtree("body",e=>{e.forEach(e=>{if(e.addedNodes.length>0){n.translateCssMatches()}e.addedNodes.forEach(e=>{n.translate(e)})})})})()}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.min.js"] = (()=>{return(e,t)=>{const s={"日本語":"ja-JP",English:"en-US","正體中文":"zh-TW",Deutsch:"de-DE"};class a{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"){return}const s=map.get(t.trim());if(s===undefined){return}if(typeof s==="string"){this.setValue(e,s)}else if(Array.isArray(s)){let t=null;for(const a of s){if(typeof a==="string"){t=a}else{const{text:s,selector:r}=a;if(this.getElement(e).matches(r)){t=s}}}if(t!==null){this.setValue(e,t)}}else{const{text:t,selector:a}=s;if(this.getElement(e).matches(a)){this.setValue(e,t)}}}static walk(e,t){const s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null,false);let a=s.nextNode();while(a){t(a);a=s.nextNode()}}static translate(e){if(e.nodeType===Node.TEXT_NODE){a.textNode.translate(e);return}a.walk(e,e=>{for(const t of a.allTranslators){if(t.accepts(e)){t.translate(e)}}})}static translateCssMatches(){const e=map.get("*");if(!e){return}for(const{selector:t,text:s}of e){const e=document.querySelector(t);if(e){[...e.childNodes].filter(e=>e.nodeType===Node.TEXT_NODE).forEach(e=>e.nodeValue=s)}}}}class r extends a{accepts(e){return e.nodeType===Node.TEXT_NODE}getElement(e){return e.parentElement}}class l extends a{getValue(e){return e.getAttribute("title")}setValue(e,t){e.setAttribute("title",t)}}class n extends a{accepts(e){return e.nodeName==="INPUT"&&e.type.toUpperCase()==="TEXT"||e.nodeName==="TEXTAREA"}getValue(e){return e.getAttribute("placeholder")}setValue(e,t){e.setAttribute("placeholder",t)}}a.textNode=new r;a.title=new l;a.placeholder=new n;a.allTranslators=[a.textNode,a.title,a.placeholder];(async()=>{const{map:r}=await t.importAsync(`i18n.${s[e.i18nLanguage]}`);a.translate(document.body);a.translateCssMatches();Observer.childListSubtree("body",e=>{e.forEach(e=>{if(e.addedNodes.length>0){a.translateCssMatches()}e.addedNodes.forEach(e=>{a.translate(e)})})})})();return{export:{Translator:a,TextNodeTranslator:r,TitleTranslator:l,PlaceholderTranslator:n}}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.zh-TW.min.js"] = (()=>{return(r,e)=>{const n=new Map([[`*`,[]]]);return{export:{map:n}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/icons.min.css"] = `.icons-enabled [class^=icon-]{width:24px;height:24px;display:inline-block;background-image:none}.icons-enabled [class^=icon-]::after{content:"";width:24px;height:24px;display:inline-block}.icons-enabled .icon-view::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-clear::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-download::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-update::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-info::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-settings::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-widgets::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-cancel::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-ok::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-video::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-style::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-tool::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-touch::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-other::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-arrow::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-rank::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-like::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-danmaku::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-search::after{background-image:url('data:image/svg+xml;utf-8, ')}.compact .primary-menu .nav-menu>li.home>a,.icons-enabled .icon-home::after{background-image:url('data:image/svg+xml;utf-8,')}.compact .primary-menu .nav-menu .side-nav .side-link i.zhuanlan,.icons-enabled .icon-read::after{background-image:url('data:image/svg+xml;utf-8,')}.compact .primary-menu .nav-menu .side-nav .side-link i.square,.icons-enabled .icon-square::after{background-image:url('data:image/svg+xml;utf-8,')}.compact .primary-menu .nav-menu .side-nav .side-link i.live,.icons-enabled .icon-live::after{background-image:url('data:image/svg+xml;utf-8,')}.compact .primary-menu .nav-menu .side-nav .side-link i.blackroom,.icons-enabled .icon-judge::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-medal::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-live-title::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-biliplus::after{background-image:url('data:image/svg+xml;utf-8, ')}`; offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/image-resolution.min.js"] = (()=>{return(t,e)=>{const r=/(.*?)@(.*)\./;const o=["certify-img1","certify-img2"];const s=8;function i(t){if(o.includes(t.id)){return}let e=0;const i=new Observer(t,()=>{e++;if(e>s){i.stop();return}const o=t.getAttribute("src");const c=o.match(r);if(c&&c[1]){i.stop();t.setAttribute("src",c[1])}});i.options={childList:false,attributes:true,subtree:false};i.start()}document.querySelectorAll("img").forEach(t=>i(t));Observer.childListSubtree("body",t=>{for(const e of t){for(const t of e.addedNodes){if(t.nodeName.toLowerCase()==="img"){i(t)}t.querySelectorAll&&t.querySelectorAll("img").forEach(t=>i(t))}}});return{export:{imageResolution:i}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/image-viewer.min.css"] = `body.image-viewer-opened,html.image-viewer-opened{overflow:hidden!important}.image-viewer-container{background:rgba(0,0,0,.85);width:100%;height:100%;position:fixed;top:0;left:0;z-index:100000;display:none;justify-content:center;align-items:center}.image-viewer-container.opened{display:flex}.image-viewer{width:90%;height:90%;display:grid;grid-template-columns:auto 48px;grid-template-rows:48px auto 48px 12px 48px 18px 48px;grid-template-areas:"image close" "image ." "image copy-link" "image ." "image new-tab" "image ." "image download";grid-column-gap:12px;justify-items:center;justify-content:stretch;align-items:center;align-content:stretch}.image-viewer .image{grid-area:image;width:auto;height:auto;max-width:100%;max-height:100%}.image-viewer .close{grid-area:close}.image-viewer .download{grid-area:download}.image-viewer .copy-link{grid-area:copy-link;transform:scale(.95)}.image-viewer .new-tab{grid-area:new-tab;transform:scale(.85)}.image-viewer-icon{cursor:pointer;width:100%;height:100%}.image-viewer-icon svg{max-width:48px;max-height:48px}.image-viewer-icon path{fill:#eee;transition:.2s;transform-origin:center}.image-viewer-icon:hover path{fill:var(--theme-color);transform:scale(1.1)}`; @@ -1598,6 +1601,12 @@ Resource.manifest = { i18nJapanese: { path: "i18n.ja-JP.min.js", }, + i18nTraditionalChinese: { + path: "i18n.zh-TW.min.js", + }, + i18nGerman: { + path: "i18n.de-DE.min.js", + }, i18n: { path: "i18n.min.js", style: "important", @@ -1939,6 +1948,7 @@ class ResourceManager } } await Promise.all(Object.values(Resource.manifest) + .concat(Object.values(Resource.all)) .filter(it => it.dropdown) .map(it => applyDropdownOption(it.dropdown)) ); diff --git a/bilibili-evolved.preview-offline.user.js b/bilibili-evolved.preview-offline.user.js index 176d3db6d..880d339a2 100644 --- a/bilibili-evolved.preview-offline.user.js +++ b/bilibili-evolved.preview-offline.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name Bilibili Evolved (Preview Offline) -// @version 253.91 +// @version 254.07 // @description Bilibili Evolved 的预览离线版, 可以抢先体验新功能, 并且所有功能都已内置于脚本中. // @author Grant Howard, Coulomb-G // @copyright 2019, Grant Howard (https://github.com/the1812) & Coulomb-G (https://github.com/Coulomb-G) @@ -360,6 +360,7 @@ function loadResources() { const resource = new Resource(data.path, data.styles); resource.key = key; + resource.dropdown = data.dropdown; if (data.displayNames) { resource.displayName = data.displayNames[key]; @@ -868,10 +869,12 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/gui-settings.min.js"] = (()=>{return(e,t)=>{const{ThemeColors:n}=t.import("theme-colors");const{SettingsSearch:i}=t.import("settings-search");const{Validator:c}=t.import("text-validate");function o(e){let t=e.nextElementSibling;const n=[];while(t!==null&&!t.classList.contains("category")){n.push(t);t=t.nextElementSibling}return n}function r(e,t){const n=document.querySelector(`input[type='checkbox'][key='${e}']`);if(n){n.checked=t;return}const i=document.querySelector(`input[type='text'][key='${e}']`);if(i){i.value=t;return}}function s(){for(const[t,n]of Object.entries(e)){r(t,n)}}function u(){document.querySelector(".gui-settings-mask").addEventListener("click",()=>{document.querySelectorAll(".gui-settings-widgets-box,.gui-settings-box,.gui-settings-mask").forEach(e=>e.classList.remove("opened"))});document.querySelectorAll("input[type='text'][key]").forEach(t=>{t.setAttribute("placeholder",e[t.getAttribute("key")])});document.querySelectorAll(".gui-settings-content ul li.category").forEach(e=>{e.addEventListener("click",e=>{const t=document.querySelector(".gui-settings-search");if(t.value!==""){t.value="";raiseEvent(t,"input")}e.currentTarget.classList.toggle("folded");o(e.currentTarget).forEach(e=>e.classList.toggle("folded"))})});document.querySelectorAll(".gui-settings-dropdown>input").forEach(e=>{e.addEventListener("click",e=>{e.currentTarget.parentElement.classList.toggle("opened")})});onSettingsChange((t,n,i)=>{if(e[t]!==i){e[t]=i;const n=document.querySelector(`input[type='checkbox'][key='${t}']`);if(n){n.checked=i;raiseEvent(n,"change");return}const c=document.querySelector(`input[type='text'][key='${t}']`);if(c){c.value=i;raiseEvent(c,"change");return}}})}function l(){const t=e=>{};document.querySelectorAll("input[type='checkbox'][key]").forEach(n=>{n.addEventListener("change",()=>{const i=n.getAttribute("key");const c=n.checked;e[i]=c;t(i);saveSettings(e)})});document.querySelectorAll("input[type='text'][key]").forEach(n=>{n.addEventListener("change",()=>{const i=n.getAttribute("key");const o=c.getValidator(i).validate(n.value);e[i]=o;n.value=o;t(i);saveSettings(e)})})}function a(){const e={};document.querySelectorAll(`input[dependencies]`).forEach(t=>{const n=t.getAttribute("dependencies");if(n){e[t.getAttribute("key")]=n}});const t=t=>{const n=t.checked;for(const i in e){const c=e[i].split(" ");if(c.indexOf(t.getAttribute("key"))!==-1){let e=true;if(n&&c.every(e=>document.querySelector(`input[key='${e}']`).checked)){e=false}let t=document.querySelector(`input[key='${i}']`);while(t.nodeName.toLowerCase()!=="li"){t=t.parentElement}const o=e?"add":"remove";t.classList[o]("disabled");const r=document.querySelector(`input[key='${i}'][type='text']`);r&&r.parentElement.classList[o]("disabled")}}};document.querySelectorAll(`input[type='checkbox'][key]`).forEach(e=>{e.addEventListener("change",e=>t(e.target));t(e)})}function d(){if(typeof offlineData!=="undefined"){document.querySelector(".gui-settings-checkbox-container>input[key=useCache]").parentElement.parentElement.classList.add("disabled");document.querySelector("input[key=useCache]").disabled=true}}function y(){document.querySelectorAll(".gui-settings-content ul li.category").forEach(e=>{e.click()})}function g(){if(!CSS.supports("backdrop-filter","blur(24px)")&&!CSS.supports("-webkit-backdrop-filter","blur(24px)")){document.querySelector("input[key=blurVideoControl]").disabled=true;e.blurVideoControl=false;saveSettings(e)}if(window.devicePixelRatio===1){document.querySelector("input[key=harunaScale]").disabled=true;e.harunaScale=false;saveSettings(e)}if(e.defaultPlayerLayout==="旧版"){const t=document.querySelector("input[key=overrideNavBar]");t.disabled=true;raiseEvent(t,"change");if(e.overrideNavBar){t.checked=false;raiseEvent(t,"change");e.overrideNavBar=false;saveSettings(e)}}}function p(){for(const[e,t]of Object.entries(Resource.displayNames)){const n=document.querySelector(`input[key=${e}]`);if(!n){continue}switch(n.type){case"checkbox":n.nextElementSibling.nextElementSibling.innerHTML=t;break;case"text":const e=n.parentElement;if(e.classList.contains("gui-settings-textbox-container")){n.previousElementSibling.innerHTML=t}else if(e.classList.contains("gui-settings-dropdown")){e.previousElementSibling.innerHTML=t}break;default:break}}}(async()=>{t.applyStyle("guiSettingsStyle");const e=(t.data.guiSettingsDom||t.data.guiSettingsHtml).text;document.body.insertAdjacentHTML("beforeend",e);new SpinQuery(()=>document.body,e=>e&&!(unsafeWindow.parent.window===unsafeWindow),e=>document.querySelector(".gui-settings-icon-panel").style.display="none").start();u();d();s();a();l();y();g();p();(new n).setupDom();new i})()}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/haruna-scale.min.js"] = (()=>{return(n,t)=>{const a="bilibili-haruna-scale";if($(a).length===0){t.applyStyleFromText(`\n \n `)}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/hide-top-search.min.js"] = (()=>{return(e,r)=>{const t=[".nav-search-keyword",".search-keyword"];for(const e of t){new SpinQuery(()=>$(e),e=>e!==undefined&&e.length>0&&e.attr("placeholder").length>0,e=>e.attr("placeholder","搜索")).start()}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.de-DE.min.js"] = (()=>{return(r,e)=>{const n=new Map([[`*`,[]]]);return{export:{map:n}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.en-US.min.js"] = (()=>{return(e,o)=>{const t=new Map([[`主站`,`Home`],[`画友`,`Painting`],[`音频`,`Music`],[`游戏中心`,`Game`],[`直播`,`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`],[`专栏`,`Blog`],[`转发`,`Forward`],[`评论`,`Reviews`],[`赞`,`Like`],[`视角:`,`View: `],[`我自己`,`Myself`],[`新访客`,`New visitors`],[`我的粉丝`,`Followers`],[`暂时没有新动态了哦!`,`Nothing new at this moment...`],[`历史动态`,`History`],[`投稿了`,`posted`],[`更新了`,`updated`],[`番剧`,`Bangumi`],[`样式`,`Style`],[`工具`,`Tools`],[`触摸`,`Touch`],[`其他`,`Other`],[`正在直播`,`Live broadcasting`],[`投稿视频`,`Posted video`],[`展开全文`,`Expand`],[`*`,[]]]);return{export:{map:t}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.ja-JP.min.js"] = (()=>{return(r,e)=>{const n=new Map([[`主站`,`ホーム`],[`画友`,`絵画`],[`音频`,`音楽`],[`游戏中心`,`ゲーム`],[`直播`,`生放送`],[`会员购`,`ショップ`],[`漫画`,`漫画`],[`下载APP`,`アプリ`],[`大会员`,`会員`],[`消息`,`通知`],[`动态`,`マイフィード`],[`稍后再看`,`後で鑑賞`],[`收藏`,`お気に入り`],[`历史`,`視聴履歴`],[`投稿`,`投稿`],[`*`,[]]]);return{export:{map:n}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.min.css"] = `.up-info .up-focus-btn{width:auto!important;padding:0 4px!important}`; -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.min.js"] = (()=>{return(e,t)=>{(async()=>{const s={"日本語":"ja-JP",English:"en-US"};const{map:a}=await t.importAsync(`i18n.${s[e.i18nLanguage]}`);class n{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"){return}const s=a.get(t.trim());if(s===undefined){return}if(typeof s==="string"){this.setValue(e,s)}else if(Array.isArray(s)){let t=null;for(const a of s){if(typeof a==="string"){t=a}else{const{text:s,selector:n}=a;if(this.getElement(e).matches(n)){t=s}}}if(t!==null){this.setValue(e,t)}}else{const{text:t,selector:a}=s;if(this.getElement(e).matches(a)){this.setValue(e,t)}}}static walk(e,t){const s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null,false);let a=s.nextNode();while(a){t(a);a=s.nextNode()}}static translate(e){if(e.nodeType===Node.TEXT_NODE){n.textNode.translate(e);return}n.walk(e,e=>{for(const t of n.allTranslators){if(t.accepts(e)){t.translate(e)}}})}static translateCssMatches(){const e=a.get("*");if(!e){return}for(const{selector:t,text:s}of e){const e=document.querySelector(t);if(e){[...e.childNodes].filter(e=>e.nodeType===Node.TEXT_NODE).forEach(e=>e.nodeValue=s)}}}}class r extends n{accepts(e){return e.nodeType===Node.TEXT_NODE}getElement(e){return e.parentElement}}class l extends n{getValue(e){return e.getAttribute("title")}setValue(e,t){e.setAttribute("title",t)}}class o extends n{accepts(e){return e.nodeName==="INPUT"&&e.type.toUpperCase()==="TEXT"||e.nodeName==="TEXTAREA"}getValue(e){return e.getAttribute("placeholder")}setValue(e,t){e.setAttribute("placeholder",t)}}n.textNode=new r;n.title=new l;n.placeholder=new o;n.allTranslators=[n.textNode,n.title,n.placeholder];n.translate(document.body);n.translateCssMatches();Observer.childListSubtree("body",e=>{e.forEach(e=>{if(e.addedNodes.length>0){n.translateCssMatches()}e.addedNodes.forEach(e=>{n.translate(e)})})})})()}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.min.js"] = (()=>{return(e,t)=>{const s={"日本語":"ja-JP",English:"en-US","正體中文":"zh-TW",Deutsch:"de-DE"};class a{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"){return}const s=map.get(t.trim());if(s===undefined){return}if(typeof s==="string"){this.setValue(e,s)}else if(Array.isArray(s)){let t=null;for(const a of s){if(typeof a==="string"){t=a}else{const{text:s,selector:r}=a;if(this.getElement(e).matches(r)){t=s}}}if(t!==null){this.setValue(e,t)}}else{const{text:t,selector:a}=s;if(this.getElement(e).matches(a)){this.setValue(e,t)}}}static walk(e,t){const s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null,false);let a=s.nextNode();while(a){t(a);a=s.nextNode()}}static translate(e){if(e.nodeType===Node.TEXT_NODE){a.textNode.translate(e);return}a.walk(e,e=>{for(const t of a.allTranslators){if(t.accepts(e)){t.translate(e)}}})}static translateCssMatches(){const e=map.get("*");if(!e){return}for(const{selector:t,text:s}of e){const e=document.querySelector(t);if(e){[...e.childNodes].filter(e=>e.nodeType===Node.TEXT_NODE).forEach(e=>e.nodeValue=s)}}}}class r extends a{accepts(e){return e.nodeType===Node.TEXT_NODE}getElement(e){return e.parentElement}}class l extends a{getValue(e){return e.getAttribute("title")}setValue(e,t){e.setAttribute("title",t)}}class n extends a{accepts(e){return e.nodeName==="INPUT"&&e.type.toUpperCase()==="TEXT"||e.nodeName==="TEXTAREA"}getValue(e){return e.getAttribute("placeholder")}setValue(e,t){e.setAttribute("placeholder",t)}}a.textNode=new r;a.title=new l;a.placeholder=new n;a.allTranslators=[a.textNode,a.title,a.placeholder];(async()=>{const{map:r}=await t.importAsync(`i18n.${s[e.i18nLanguage]}`);a.translate(document.body);a.translateCssMatches();Observer.childListSubtree("body",e=>{e.forEach(e=>{if(e.addedNodes.length>0){a.translateCssMatches()}e.addedNodes.forEach(e=>{a.translate(e)})})})})();return{export:{Translator:a,TextNodeTranslator:r,TitleTranslator:l,PlaceholderTranslator:n}}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/i18n.zh-TW.min.js"] = (()=>{return(r,e)=>{const n=new Map([[`*`,[]]]);return{export:{map:n}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/icons.min.css"] = `.icons-enabled [class^=icon-]{width:24px;height:24px;display:inline-block;background-image:none}.icons-enabled [class^=icon-]::after{content:"";width:24px;height:24px;display:inline-block}.icons-enabled .icon-view::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-clear::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-download::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-update::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-info::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-settings::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-widgets::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-cancel::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-ok::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-video::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-style::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-tool::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-touch::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-other::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-arrow::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-rank::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-like::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-danmaku::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-search::after{background-image:url('data:image/svg+xml;utf-8, ')}.compact .primary-menu .nav-menu>li.home>a,.icons-enabled .icon-home::after{background-image:url('data:image/svg+xml;utf-8,')}.compact .primary-menu .nav-menu .side-nav .side-link i.zhuanlan,.icons-enabled .icon-read::after{background-image:url('data:image/svg+xml;utf-8,')}.compact .primary-menu .nav-menu .side-nav .side-link i.square,.icons-enabled .icon-square::after{background-image:url('data:image/svg+xml;utf-8,')}.compact .primary-menu .nav-menu .side-nav .side-link i.live,.icons-enabled .icon-live::after{background-image:url('data:image/svg+xml;utf-8,')}.compact .primary-menu .nav-menu .side-nav .side-link i.blackroom,.icons-enabled .icon-judge::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-medal::after{background-image:url('data:image/svg+xml;utf-8, ')}.icons-enabled .icon-live-title::after{background-image:url('data:image/svg+xml;utf-8,')}.icons-enabled .icon-biliplus::after{background-image:url('data:image/svg+xml;utf-8, ')}`; offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/image-resolution.min.js"] = (()=>{return(t,e)=>{const r=/(.*?)@(.*)\./;const o=["certify-img1","certify-img2"];const s=8;function i(t){if(o.includes(t.id)){return}let e=0;const i=new Observer(t,()=>{e++;if(e>s){i.stop();return}const o=t.getAttribute("src");const c=o.match(r);if(c&&c[1]){i.stop();t.setAttribute("src",c[1])}});i.options={childList:false,attributes:true,subtree:false};i.start()}document.querySelectorAll("img").forEach(t=>i(t));Observer.childListSubtree("body",t=>{for(const e of t){for(const t of e.addedNodes){if(t.nodeName.toLowerCase()==="img"){i(t)}t.querySelectorAll&&t.querySelectorAll("img").forEach(t=>i(t))}}});return{export:{imageResolution:i}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/image-viewer.min.css"] = `body.image-viewer-opened,html.image-viewer-opened{overflow:hidden!important}.image-viewer-container{background:rgba(0,0,0,.85);width:100%;height:100%;position:fixed;top:0;left:0;z-index:100000;display:none;justify-content:center;align-items:center}.image-viewer-container.opened{display:flex}.image-viewer{width:90%;height:90%;display:grid;grid-template-columns:auto 48px;grid-template-rows:48px auto 48px 12px 48px 18px 48px;grid-template-areas:"image close" "image ." "image copy-link" "image ." "image new-tab" "image ." "image download";grid-column-gap:12px;justify-items:center;justify-content:stretch;align-items:center;align-content:stretch}.image-viewer .image{grid-area:image;width:auto;height:auto;max-width:100%;max-height:100%}.image-viewer .close{grid-area:close}.image-viewer .download{grid-area:download}.image-viewer .copy-link{grid-area:copy-link;transform:scale(.95)}.image-viewer .new-tab{grid-area:new-tab;transform:scale(.85)}.image-viewer-icon{cursor:pointer;width:100%;height:100%}.image-viewer-icon svg{max-width:48px;max-height:48px}.image-viewer-icon path{fill:#eee;transition:.2s;transform-origin:center}.image-viewer-icon:hover path{fill:var(--theme-color);transform:scale(1.1)}`; @@ -1598,6 +1601,12 @@ Resource.manifest = { i18nJapanese: { path: "i18n.ja-JP.min.js", }, + i18nTraditionalChinese: { + path: "i18n.zh-TW.min.js", + }, + i18nGerman: { + path: "i18n.de-DE.min.js", + }, i18n: { path: "i18n.min.js", style: "important", @@ -1939,6 +1948,7 @@ class ResourceManager } } await Promise.all(Object.values(Resource.manifest) + .concat(Object.values(Resource.all)) .filter(it => it.dropdown) .map(it => applyDropdownOption(it.dropdown)) ); diff --git a/bilibili-evolved.preview.user.js b/bilibili-evolved.preview.user.js index 89b6ba733..fb712c58a 100644 --- a/bilibili-evolved.preview.user.js +++ b/bilibili-evolved.preview.user.js @@ -359,6 +359,7 @@ function loadResources() { const resource = new Resource(data.path, data.styles); resource.key = key; + resource.dropdown = data.dropdown; if (data.displayNames) { resource.displayName = data.displayNames[key]; @@ -1545,6 +1546,12 @@ Resource.manifest = { i18nJapanese: { path: "i18n.ja-JP.min.js", }, + i18nTraditionalChinese: { + path: "i18n.zh-TW.min.js", + }, + i18nGerman: { + path: "i18n.de-DE.min.js", + }, i18n: { path: "i18n.min.js", style: "important", @@ -1886,6 +1893,7 @@ class ResourceManager } } await Promise.all(Object.values(Resource.manifest) + .concat(Object.values(Resource.all)) .filter(it => it.dropdown) .map(it => applyDropdownOption(it.dropdown)) ); diff --git a/bilibili-evolved.user.js b/bilibili-evolved.user.js index 9dae28576..d09dacda5 100644 --- a/bilibili-evolved.user.js +++ b/bilibili-evolved.user.js @@ -359,6 +359,7 @@ function loadResources() { const resource = new Resource(data.path, data.styles); resource.key = key; + resource.dropdown = data.dropdown; if (data.displayNames) { resource.displayName = data.displayNames[key]; @@ -1545,6 +1546,12 @@ Resource.manifest = { i18nJapanese: { path: "i18n.ja-JP.min.js", }, + i18nTraditionalChinese: { + path: "i18n.zh-TW.min.js", + }, + i18nGerman: { + path: "i18n.de-DE.min.js", + }, i18n: { path: "i18n.min.js", style: "important", @@ -1886,6 +1893,7 @@ class ResourceManager } } await Promise.all(Object.values(Resource.manifest) + .concat(Object.values(Resource.all)) .filter(it => it.dropdown) .map(it => applyDropdownOption(it.dropdown)) ); diff --git a/client/resource-loader.js b/client/resource-loader.js index 53d175917..c57633a81 100644 --- a/client/resource-loader.js +++ b/client/resource-loader.js @@ -11,6 +11,7 @@ export function loadResources() { const resource = new Resource(data.path, data.styles); resource.key = key; + resource.dropdown = data.dropdown; if (data.displayNames) { resource.displayName = data.displayNames[key]; diff --git a/client/resource-manager.js b/client/resource-manager.js index 6777a62cb..882423dcf 100644 --- a/client/resource-manager.js +++ b/client/resource-manager.js @@ -250,6 +250,7 @@ export class ResourceManager } } await Promise.all(Object.values(Resource.manifest) + .concat(Object.values(Resource.all)) .filter(it => it.dropdown) .map(it => applyDropdownOption(it.dropdown)) ); diff --git a/client/resource-manifest.js b/client/resource-manifest.js index 8c6b99cad..70c8fff12 100644 --- a/client/resource-manifest.js +++ b/client/resource-manifest.js @@ -493,6 +493,12 @@ Resource.manifest = { i18nJapanese: { path: "i18n.ja-JP.min.js", }, + i18nTraditionalChinese: { + path: "i18n.zh-TW.min.js", + }, + i18nGerman: { + path: "i18n.de-DE.min.js", + }, i18n: { path: "i18n.min.js", style: "important", diff --git a/min/i18n.de-DE.min.js b/min/i18n.de-DE.min.js new file mode 100644 index 000000000..7730434fd --- /dev/null +++ b/min/i18n.de-DE.min.js @@ -0,0 +1 @@ +(()=>{return(r,e)=>{const n=new Map([[`*`,[]]]);return{export:{map:n}}}})(); \ No newline at end of file diff --git a/min/i18n.min.js b/min/i18n.min.js index cf6c1e758..ea2f3ec2f 100644 --- a/min/i18n.min.js +++ b/min/i18n.min.js @@ -1 +1 @@ -(()=>{return(e,t)=>{(async()=>{const s={"日本語":"ja-JP",English:"en-US"};const{map:a}=await t.importAsync(`i18n.${s[e.i18nLanguage]}`);class n{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"){return}const s=a.get(t.trim());if(s===undefined){return}if(typeof s==="string"){this.setValue(e,s)}else if(Array.isArray(s)){let t=null;for(const a of s){if(typeof a==="string"){t=a}else{const{text:s,selector:n}=a;if(this.getElement(e).matches(n)){t=s}}}if(t!==null){this.setValue(e,t)}}else{const{text:t,selector:a}=s;if(this.getElement(e).matches(a)){this.setValue(e,t)}}}static walk(e,t){const s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null,false);let a=s.nextNode();while(a){t(a);a=s.nextNode()}}static translate(e){if(e.nodeType===Node.TEXT_NODE){n.textNode.translate(e);return}n.walk(e,e=>{for(const t of n.allTranslators){if(t.accepts(e)){t.translate(e)}}})}static translateCssMatches(){const e=a.get("*");if(!e){return}for(const{selector:t,text:s}of e){const e=document.querySelector(t);if(e){[...e.childNodes].filter(e=>e.nodeType===Node.TEXT_NODE).forEach(e=>e.nodeValue=s)}}}}class r extends n{accepts(e){return e.nodeType===Node.TEXT_NODE}getElement(e){return e.parentElement}}class l extends n{getValue(e){return e.getAttribute("title")}setValue(e,t){e.setAttribute("title",t)}}class o extends n{accepts(e){return e.nodeName==="INPUT"&&e.type.toUpperCase()==="TEXT"||e.nodeName==="TEXTAREA"}getValue(e){return e.getAttribute("placeholder")}setValue(e,t){e.setAttribute("placeholder",t)}}n.textNode=new r;n.title=new l;n.placeholder=new o;n.allTranslators=[n.textNode,n.title,n.placeholder];n.translate(document.body);n.translateCssMatches();Observer.childListSubtree("body",e=>{e.forEach(e=>{if(e.addedNodes.length>0){n.translateCssMatches()}e.addedNodes.forEach(e=>{n.translate(e)})})})})()}})(); \ No newline at end of file +(()=>{return(e,t)=>{const s={"日本語":"ja-JP",English:"en-US","正體中文":"zh-TW",Deutsch:"de-DE"};class a{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"){return}const s=map.get(t.trim());if(s===undefined){return}if(typeof s==="string"){this.setValue(e,s)}else if(Array.isArray(s)){let t=null;for(const a of s){if(typeof a==="string"){t=a}else{const{text:s,selector:r}=a;if(this.getElement(e).matches(r)){t=s}}}if(t!==null){this.setValue(e,t)}}else{const{text:t,selector:a}=s;if(this.getElement(e).matches(a)){this.setValue(e,t)}}}static walk(e,t){const s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null,false);let a=s.nextNode();while(a){t(a);a=s.nextNode()}}static translate(e){if(e.nodeType===Node.TEXT_NODE){a.textNode.translate(e);return}a.walk(e,e=>{for(const t of a.allTranslators){if(t.accepts(e)){t.translate(e)}}})}static translateCssMatches(){const e=map.get("*");if(!e){return}for(const{selector:t,text:s}of e){const e=document.querySelector(t);if(e){[...e.childNodes].filter(e=>e.nodeType===Node.TEXT_NODE).forEach(e=>e.nodeValue=s)}}}}class r extends a{accepts(e){return e.nodeType===Node.TEXT_NODE}getElement(e){return e.parentElement}}class l extends a{getValue(e){return e.getAttribute("title")}setValue(e,t){e.setAttribute("title",t)}}class n extends a{accepts(e){return e.nodeName==="INPUT"&&e.type.toUpperCase()==="TEXT"||e.nodeName==="TEXTAREA"}getValue(e){return e.getAttribute("placeholder")}setValue(e,t){e.setAttribute("placeholder",t)}}a.textNode=new r;a.title=new l;a.placeholder=new n;a.allTranslators=[a.textNode,a.title,a.placeholder];(async()=>{const{map:r}=await t.importAsync(`i18n.${s[e.i18nLanguage]}`);a.translate(document.body);a.translateCssMatches();Observer.childListSubtree("body",e=>{e.forEach(e=>{if(e.addedNodes.length>0){a.translateCssMatches()}e.addedNodes.forEach(e=>{a.translate(e)})})})})();return{export:{Translator:a,TextNodeTranslator:r,TitleTranslator:l,PlaceholderTranslator:n}}}})(); \ No newline at end of file diff --git a/min/i18n.zh-TW.min.js b/min/i18n.zh-TW.min.js new file mode 100644 index 000000000..7730434fd --- /dev/null +++ b/min/i18n.zh-TW.min.js @@ -0,0 +1 @@ +(()=>{return(r,e)=>{const n=new Map([[`*`,[]]]);return{export:{map:n}}}})(); \ No newline at end of file diff --git a/utils/i18n/i18n.de-DE.js b/utils/i18n/i18n.de-DE.js new file mode 100644 index 000000000..83da648d7 --- /dev/null +++ b/utils/i18n/i18n.de-DE.js @@ -0,0 +1,9 @@ +export const map = new Map([ + /* Your translation here */ + [`*`, [ + /* CSS translation here */ + ]], +]); +export default { + export: { map }, +}; \ No newline at end of file diff --git a/utils/i18n/i18n.js b/utils/i18n/i18n.js index 838b9ead4..cf12fcf7d 100644 --- a/utils/i18n/i18n.js +++ b/utils/i18n/i18n.js @@ -1,139 +1,143 @@ +const languageCodeMap = { + "日本語": "ja-JP", + "English": "en-US", + "正體中文": "zh-TW", + "Deutsch": "de-DE", +}; +export class Translator +{ + accepts(node) { return node.nodeType === Node.ELEMENT_NODE; } + getValue(node) { return node.nodeValue; } + setValue(node, value) { node.nodeValue = value; } + getElement(node) { return node; } + translate(node) + { + const value = this.getValue(node); + if (!value || typeof value !== "string") + { + return; + } + const translation = map.get(value.trim()); + if (translation === undefined) + { + return; + } + if (typeof translation === "string") + { + this.setValue(node, translation); + } + else if (Array.isArray(translation)) + { + let finalTranslation = null; + for (const subTranslation of translation) + { + if (typeof subTranslation === "string") + { + finalTranslation = subTranslation; + } + else + { + const { text, selector } = subTranslation; + if (this.getElement(node).matches(selector)) + { + finalTranslation = text; + } + } + } + if (finalTranslation !== null) + { + this.setValue(node, finalTranslation); + } + } + else + { + const { text, selector } = translation; + if (this.getElement(node).matches(selector)) + { + this.setValue(node, text); + } + } + } + // https://stackoverflow.com/questions/10730309/find-all-text-nodes-in-html-page + static walk(rootElement, action) + { + const walker = document.createTreeWalker(rootElement, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT, null, false); + let node = walker.nextNode(); + while (node) + { + action(node); + node = walker.nextNode(); + } + } + static translate(rootElement) + { + if (rootElement.nodeType === Node.TEXT_NODE) + { + Translator.textNode.translate(rootElement); + return; + } + Translator.walk(rootElement, node => + { + for (const translator of Translator.allTranslators) + { + if (translator.accepts(node)) + { + translator.translate(node); + } + } + }); + } + static translateCssMatches() + { + const selectors = map.get("*"); + if (!selectors) + { + return; + } + for (const { selector, text } of selectors) + { + const element = document.querySelector(selector); + if (element) + { + [...element.childNodes].filter(it => it.nodeType === Node.TEXT_NODE).forEach(it => it.nodeValue = text); + } + } + } +} +export class TextNodeTranslator extends Translator +{ + accepts(node) { return node.nodeType === Node.TEXT_NODE; } + getElement(node) + { + return node.parentElement; + } +} +export class TitleTranslator extends Translator +{ + getValue(node) { return node.getAttribute("title"); } + setValue(node, value) + { + node.setAttribute("title", value); + } +} +export class PlaceholderTranslator extends Translator +{ + accepts(node) { return node.nodeName === "INPUT" && node.type.toUpperCase() === "TEXT" || node.nodeName === "TEXTAREA"; } + getValue(node) { return node.getAttribute("placeholder"); } + setValue(node, value) + { + node.setAttribute("placeholder", value); + } +} + +Translator.textNode = new TextNodeTranslator; +Translator.title = new TitleTranslator; +Translator.placeholder = new PlaceholderTranslator; +Translator.allTranslators = [Translator.textNode, Translator.title, Translator.placeholder]; + (async () => { - const languageCodeMap = { - "日本語": "ja-JP", - "English": "en-US", - }; const { map } = await import(`./i18n.${languageCodeMap[settings.i18nLanguage]}`); - class Translator - { - accepts(node) { return node.nodeType === Node.ELEMENT_NODE; } - getValue(node) { return node.nodeValue; } - setValue(node, value) { node.nodeValue = value; } - getElement(node) { return node; } - translate(node) - { - const value = this.getValue(node); - if (!value || typeof value !== "string") - { - return; - } - const translation = map.get(value.trim()); - if (translation === undefined) - { - return; - } - if (typeof translation === "string") - { - this.setValue(node, translation); - } - else if (Array.isArray(translation)) - { - let finalTranslation = null; - for (const subTranslation of translation) - { - if (typeof subTranslation === "string") - { - finalTranslation = subTranslation; - } - else - { - const { text, selector } = subTranslation; - if (this.getElement(node).matches(selector)) - { - finalTranslation = text; - } - } - } - if (finalTranslation !== null) - { - this.setValue(node, finalTranslation); - } - } - else - { - const { text, selector } = translation; - if (this.getElement(node).matches(selector)) - { - this.setValue(node, text); - } - } - } - // https://stackoverflow.com/questions/10730309/find-all-text-nodes-in-html-page - static walk(rootElement, action) - { - const walker = document.createTreeWalker(rootElement, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT, null, false); - let node = walker.nextNode(); - while (node) - { - action(node); - node = walker.nextNode(); - } - } - static translate(rootElement) - { - if (rootElement.nodeType === Node.TEXT_NODE) - { - Translator.textNode.translate(rootElement); - return; - } - Translator.walk(rootElement, node => - { - for (const translator of Translator.allTranslators) - { - if (translator.accepts(node)) - { - translator.translate(node); - } - } - }); - } - static translateCssMatches() - { - const selectors = map.get("*"); - if (!selectors) - { - return; - } - for (const { selector, text } of selectors) - { - const element = document.querySelector(selector); - if (element) - { - [...element.childNodes].filter(it => it.nodeType === Node.TEXT_NODE).forEach(it => it.nodeValue = text); - } - } - } - } - class TextNodeTranslator extends Translator - { - accepts(node) { return node.nodeType === Node.TEXT_NODE; } - getElement(node) - { - return node.parentElement; - } - } - class TitleTranslator extends Translator - { - getValue(node) { return node.getAttribute("title"); } - setValue(node, value) - { - node.setAttribute("title", value); - } - } - class PlaceholderTranslator extends Translator - { - accepts(node) { return node.nodeName === "INPUT" && node.type.toUpperCase() === "TEXT" || node.nodeName === "TEXTAREA"; } - getValue(node) { return node.getAttribute("placeholder"); } - setValue(node, value) - { - node.setAttribute("placeholder", value); - } - } - Translator.textNode = new TextNodeTranslator; - Translator.title = new TitleTranslator; - Translator.placeholder = new PlaceholderTranslator; - Translator.allTranslators = [Translator.textNode, Translator.title, Translator.placeholder]; Translator.translate(document.body); Translator.translateCssMatches(); @@ -151,4 +155,17 @@ }); }); }); -})(); \ No newline at end of file +})(); + +export default { + export: { + Translator, + TextNodeTranslator, + TitleTranslator, + PlaceholderTranslator, + }, + // dropdown: { + // key: "i18nLanguage", + // items: Object.keys(languageCodeMap), + // }, +}; \ No newline at end of file diff --git a/utils/i18n/i18n.zh-TW.js b/utils/i18n/i18n.zh-TW.js new file mode 100644 index 000000000..83da648d7 --- /dev/null +++ b/utils/i18n/i18n.zh-TW.js @@ -0,0 +1,9 @@ +export const map = new Map([ + /* Your translation here */ + [`*`, [ + /* CSS translation here */ + ]], +]); +export default { + export: { map }, +}; \ No newline at end of file