跳到主要內容

高級自定義選項

你可以在擴展配置頁面 -> 開發者設置 -> User Config 裡編輯更多 UI 裡無法編輯的自定義配置,適用於高級用戶,參數講解詳見最後的說明。當前內置的 config 可以在這裡,點擊 Click to expand the final config 找到。## 用戶規則

通過 Rules 可以對特定的網站進行自定義配置,決定哪些內容是否需要被翻譯,或調整網頁樣式等。

[
{
"matches": "www.google.com",
"selectors": [".title"]
},
{
"matches": "twitter.com",
"selectors": [".text"],
"excludeSelectors": ["nav", "footer"]
}
]

使用 matches 來匹配對應的網站。允許通配符,如 *.google.com,www.google.com/test/*,file://*

使用 selectors 會覆蓋智能翻譯範圍,僅翻譯該選擇器匹配到的元素。

使用 excludeSelectors 可以排除元素,不翻譯該位置。

使用 selectors.add 會在默認的基礎上添加一些 selectors

使用 selectors.remove 會在默認的基礎上減少一些 selectors

[
{
"matches": "www.google.com",
"selectors.add": ["baidu.com"],
"excludeSelectors": ["buzzing.cc"]
}
]

如果希望翻譯某個區域時,將元素視為一個整體,不將其分行,可以用 atomicBlockSelectors 選擇器。比如 Instagram 的個人簡介。要注意的是,使用 atomicBlockSelectors 前需要先用 selectors 進行選擇。

{
"matches": "https://www.instagram.com/*",
"selectors": ["div._aa_c h1", "li._acaz div[role=\"menuitem\"]"],
"atomicBlockSelectors": ["div._aa_c h1", "li._acaz div[role=\"menuitem\"]"]
}

如果譯文導致頁面錯位,文字重疊等邊緣情況,可以使用 globalStyles 調整網頁樣式來修復。比如 youtube 的標題,用來移除原網頁的最大高度。

{
"matches": "www.google.com",
"globalStyles": { ".title": "max-height:unset;" }
}

注入式 CSS

透過注入式 CSS 可以向全局注入自定義網頁樣式。可以搭配 RulestranslationClasses 一起使用。

.immersive-translate-target-wrapper img {
width: 16px;
height: 16px;
}

也可以像常規的網頁樣式管理器那樣,對網站進行更加個性化的樣式設計。(甚至利用 display:none 去廣告)

.title {
color: red;
}
```## 用戶配置

通過 Config 可以自定義此插件的相關配置,如翻譯服務、特定語言語言翻譯選項等。

```json
{
"translationService": "tencent",
"translationServices": {
"tencent": {
"secretId": "xxx",
"secretKey": "xxx",
"matches": ["twitter.com"]
}
},
"translationUrlPattern": {
"excludeMatches": ["www.google.com"]
},
"translationLanguagePattern": {
"matches": ["en"]
},
"translationTheme": "none",
"translationThemePatterns": {
"underline": {
"matches": ["discord.com"]
}
},
"sourceLanguageUrlPattern": {
"en": {
"matches": ["*.google.com"]
}
},
"generalRule": {
"_comment": "",
"normalizeBody": "",
"injectedCss": [],
"additionalInjectedCss": [],
"wrapperPrefix": "smart",
"wrapperSuffix": "smart",
"isPdf": false,
"isTransformPreTagNewLine": false,
"urlChangeDelay": 20,
"isShowUserscriptPagePopup": true,
"observeUrlChange": true,
"paragraphMinTextCount": 8,
"paragraphMinWordCount": 2,
"blockMinTextCount": 32,
"blockMinWordCount": 5,
"containerMinTextCount": 18,
"lineBreakMaxTextCount": 0,
"globalAttributes": {},
"globalStyles": {},
"selectors": [],
"preWhitespaceDetectedTags": ["DIV", "SPAN"],
"stayOriginalSelectors": [],
"additionalSelectors": [],
"atomicBlockTags": [],
"excludeSelectors": [],
"additionalExcludeSelectors": [],
"translationClasses": [],
"atomicBlockSelectors": [],
"excludeTags": [],
"metaTags": ["META", "SCRIPT", "STYLE", "NOSCRIPT"],
"additionalExcludeTags": [],
"stayOriginalTags": ["CODE", "TT", "IMG", "SUP"],
"additionalStayOriginalTags": [],
"inlineTags": [],
"additionalInlineTags": [],
"extraInlineSelectors": [],
"additionalInlineSelectors": [],
"extraBlockSelectors": [],
"allBlockTags": [],
"pdfNewParagraphLineHeight": 2.4,
"pdfNewParagraphIndent": 1.2,
"pdfNewParagraphIndentRightIndentPx": 130,
"fingerCountToToggleTranslagePageWhenTouching": 4
},
"rules": [
{
"matches": "www.google.com",
"selectors": [".class"]
}
]
}

其中,rules 裡的規則字段,可以使用 generalRule 裡的全部字段。rules 擁有最高優先級,當匹配到特定網站的某一條 rule 時,會合併 generalRule 和該 rule 的規則。

介紹一些 Config 常見的字段。### 允許渲染普通 HTML 標籤 去 開發設置 -> Edit Full User Config

編輯 "enableRenderHtmlTag": true

不在 popup 面板裡展示未配置的翻譯服務

"showUnconfiguredTranslationServiceInPopup": false### 翻譯服務配置

使用 translationService 選擇默認的翻譯引擎,當前支持:

| "bing"
| "transmart"
| "google"
| "deepl"
| "openai"
| "gemini"
| "baidu"
| "volc"
| "youdao"
| "caiyun"
| "tencent"
| "openl"

使用 translationServices 配置各家翻譯服務的 apikey,不同服務商需要的參數不一樣,它們的 API 密鑰均可在各自官網的開發者中心申請。

如騰訊翻譯君,需要配置 secretId, secretKey。你可以前往騰訊雲申請 API 密鑰,每月免費字符 500 萬。具體申請過程參考這裡

"translationServices": {
"tencent": {
"secretId": "xxx",
"secretKey": "xxx",
"matches":["twitter.com"],
"limit": 3,
"apiUrl":"",
"maxTextGroupLengthPerRequest": 25,
"maxTextLengthPerRequest": 1800
}
}

matches 字段,為特定網站使用該翻譯服務。

limit字段,指定該翻譯服務的每秒最多請求數(有些服務會限制每秒最大請求數)。

maxTextGroupLengthPerRequest 字段,每次請求最大的段落數

maxTextLengthPerRequest 字段,每次請求最大的字符數

apiUrl 可以自定義翻譯接口的地址。### 總是翻譯特定網站

translationUrlPattern 配置總是翻譯的網站,以及永不翻譯的網站。

  • matches 配置總是翻譯的網站,
  • excludeMatches 配置永不翻譯的網站。

配置值可以是域名或帶有 * 的網址,比如:www.google.com/mail/*

"translationUrlPattern": {
"matches": ["stackoverflow.com"],
"excludeMatches": ["www.google.com/mail/*"]
}

總是翻譯特定語言

translationLanguagePattern, 配置總是翻譯的語言,以及永不翻譯的語言。

  • matches 配置總是翻譯的語言,比如 en,
  • excludeMatches 配置永不翻譯的語言。### 譯文顯示格式

translationTheme 為譯文的顯示格式,當前支持以下樣式:

| "none"
| "dashed"
| "dotted"
| "underline"
| "mask"
| "paper"
| "highlight"
| "blockquote"
| "weakening"
| "italic"
| "bold"
| "thinDashed";

對應的中文名:

{
"none": "無",
"dashed": "虛線下劃線",
"dotted": "點狀下劃線",
"underline": "直線下劃線",
"mask": "模糊效果",
"paper": "白紙陰影效果",
"highlight": "高亮",
"blockquote": "引用樣式",
"weakening": "弱化",
"italic": "斜體",
"bold": "加粗",
"thinDashed": "細虛線下劃線"
}

translationThemePatterns 可以為不同網站配置不同的譯文樣式。

"translationThemePatterns": {
"underline": {
"matches": ["discord.com"]
}
}

類 gpt 頁面流消息翻譯

{
"matches": ["chat.openai.com"], //類 gpt 網址
"excludeSelectors": [".markdown *"],
"aiRule": {
"streamingSelector": ".result-streaming.markdown",
"messageWrapperSelector": ".markdown",
"streamingChange": true
}
}
```### 規則

`rules` 為數組對象,可以配置針對特別網站的規則,比如讓推特只翻譯某一部分區域:

```json
{
"rules": [
{
"id": "twitter",
"matches": ["twitter.com", "mobile.twitter.com", "tweetdeck.twitter.com"],
"selectors": [
"[data-testid='tweetText']",
".tweet-text",
".js-quoted-tweet-text",
"[data-testid='card.layoutSmall.detail'] > div:nth-child(2)",
"[data-testid='developerBuiltCardContainer'] > div:nth-child(2)",
"[data-testid='card.layoutLarge.detail'] > div:nth-child(2)"
],
"extraInlineSelectors": ["[data-testid=\"tweetText\"] div"]
}
]
}

當前內置的 rules 可以在這裡 找到。

以下挑選部分重要字段進行說明:

export interface Rule {
// 匹配網站
id?: string; //系統每個適配的規則都有自己的id,如果用戶想要複用這條規則在此基礎之上變動的話,需要在自己的規則上加上這個相應的id就可以複用了
matches?: string | string[]; // 該條Rule將僅匹配此處的網站。
excludeMatches?: string | string[]; // 排除特定的網站。
selectorMatches?: string | string[]; // 用選擇器來匹配,而無需指定所有url
excludeSelectorMatches?: string | string[]; // 排除規則,同上。

// 指定翻譯範圍
selectors?: string | string[]; // 僅翻譯匹配到的元素
excludeSelectors?: string | string[]; // 排除元素,不翻譯匹配的元素
excludeTags?: string | string[]; // 排除Tags,不翻譯匹配的Tag

// 追加翻譯範圍,而不是覆蓋
additionalSelectors?: string | string[]; // 追加翻譯範圍。在智能翻譯的區域,追加翻譯位置。
additionalExcludeSelectors?: string | string[]; // 追加排除元素,讓智能翻譯不翻譯特定位置。
additionalExcludeTags?: string | string[]; // 追加排除Tags

// 保持原樣
stayOriginalSelectors?: string | string[]; // 匹配的元素將保持原樣。常用於論壇網站的標籤。
stayOriginalTags?: string | string[]; // 匹配到的Tag將保持原樣,比如 `code`

// 區域翻譯
atomicBlockSelectors?: string | string[]; // 區域選擇器, 匹配的元素將被視為一個整體, 不會分段翻譯
}
```markdown
atomicBlockTags?: string | string[]; // 區域Tag選擇器, 同上

// Block or Inline
extraBlockSelectors?: string | string[]; // 額外的選擇器,匹配的元素將作為 block 元素,獨佔一行。
extraInlineSelectors?: string | string[]; // 額外的選擇器,匹配的元素將作為 inline 元素。

inlineTags?: string | string[]; // 匹配的 Tag 將作為 inline 元素
preWhitespaceDetectedTags?: string | string[]; // 匹配的 Tag 將自動換行

// 譯文樣式
translationClasses?: string | string | string[]; // 為譯文添加額外的 Class

// 全局樣式
globalStyles?: Record<string, string>; // 修改頁面樣式,若譯文導致頁面錯亂,這個很有用。
globalAttributes?: Record<string, Record<string, string>>; // 修改頁面元素的屬性

// 嵌入樣式
injectedCss?: string | string[]; // 嵌入CSS樣式
additionalInjectedCss?: string | string[]; // 追加CSS樣式,而不是直接覆蓋。

// 上下文
wrapperPrefix?: string; // 譯文區域的前綴,默認為 smart,根據字數決定是否換行。
wrapperSuffix?: string; // 譯文區域的後綴

// 譯文換行字數
blockMinTextCount?: number; // 將譯文作為 block 的最小字符數,否則譯文為 inline 元素。
blockMinWordCount?: number; // 同上。如果希望它們始終換行, 可以都填0.

// 內容可翻譯的最小字數
containerMinTextCount?: number; // 智能識別時,元素最少包含的字符數,才會被翻譯,默認為18
paragraphMinTextCount?: number; // 原文段落的最小字符數, 大於數字的內容將被翻譯
paragraphMinWordCount?: number; // 原文段落的最小單詞數

// 長段落強制換行字數
lineBreakMaxTextCount?: number; // 開啟翻譯長段落時,強制進行分行的段落最大字符數。

// 啟動翻譯的時機
urlChangeDelay?: number; // 進入頁面後,延遲多少毫秒開始翻譯。為了等網頁的初始化,目前默認為250ms
observeUrlChange?: boolean; // 檢測url地址發生變化時,再次啟動翻譯,默認為true。

// 移動端
isShowUserscriptPagePopup?: boolean; // 在移動設備上展示頁面內的浮窗, 默認為true.
fingerCountToToggleTranslagePageWhenTouching?: number; // 四指觸摸則翻譯,可以設置為 0,2,3,4,5

// AI streaming 翻譯
aiRule: {
streamingSelector: string; //gpt 網頁中標記正在翻譯元素的選擇器
messageWrapperSelector: string; // 消息正文選擇器
streamingChange: boolean; //類 gpt 網頁反復的消息是增量更新還是全量更新。gpt 是增量
};
}

高級自定義選項實戰

實用小技巧

這部分會介紹一些即插即用的保姆級配置。

將這些配置一鍵複製,打開開發者設置,展開 Edit Full User Config ,複製到最後一項即可,注意不要忘記給前一項加上逗號,以及最後一項不能加逗號

不能用的翻譯服務太多了,如何在插件面板裡只展示能用的翻譯服務

  "showUnconfiguredTranslationServiceInPopup": false
```#### 如何讓不同的站點默認選擇不同的翻譯服務?例如有的網站我想要好一點但要花錢的翻譯效果,有的網站我只需要免費能看的翻譯就行了

注意看,眼前這個配置叫翻譯服務,他配置了谷歌翻譯,讓有關推特的相關站點的翻譯都使用他去翻譯,因為 `google` 翻譯是免費的,推特是衝浪的,只要能看懂就行了。

仔細看,他還配置了 `deepl` 的翻譯服務,他讓 `deepl` 專門去翻譯 `scihub` 這種容錯率低的需要高精確的學術網站

```json
"translationServices": {
"google": {
"matches":["https://twitter.com"]
},
"deepl": {
"matches":["https://www.sci-hub.se"]
}
}

⚠️ 請注意,若您希望翻譯屬於同一域名的所有網站,簡單使用 .twitter.com 或 https://twitter.com/ 是無效的。正確的做法應參照上文所示。這是因為 .twitter.com 僅能匹配子域名如 xxx.twitter.com,而不包括頂級域名本身。### 網站適配案例

這部分會介紹一些插件自己對常見的網站的 rules,通過實際例子來理解高級自定義選項。同時為了簡潔,這裡只會介紹最常用的字段,比如 selectors , excludeSelectors 等等,如果你對這部分內容感興趣的話,歡迎聯繫我們,我們會繼續更新相關的內容。

在介紹之前,一個非常關鍵的東西就是沉浸式翻譯插件的工作原理,同時也是一個插件的工作原理。在此之前,需要有一定的 HTMLCSSJavaScript 基礎,相關基礎可以在 MDN 網站上學習。Okay,話不多說,讓我們走進沉浸式翻譯的內部一探究竟。插件的工作機制簡單來說,就是向網頁中注入第三方腳本,這個腳本可以對網頁結構,樣式,甚至行為進行相當自由地魔改。

我們的沉浸式翻譯插件也不例外,讓我們來簡單分析一下沉浸式翻譯它幹了個什麼事

  • 獲取需要翻譯的元素集合
  • 翻譯元素集合中的文本
  • 將翻譯的結果插入到元素集合中

Okay,但是再仔細想想,自然而然就會帶出接下來兩個問題

  • 我們還需要確定哪些元素需要被翻譯,如果全盤翻譯,往往會破壞用戶的沉浸式體驗,像一些簡單明瞭的按鈕,或者導航欄。
  • 將翻譯的結果插入到元素集合中也會帶來一個新的挑戰,如何保證插入的結果與原生網頁保持一致,不去影響原生網頁的樣式。

我們的 Rules 的核心就是解決上述兩個問題。因為作為插件,沉浸式翻譯面對的是市面上所有的網頁,加起來可能超過幾十萬,甚至幾百萬的網頁,這些網頁的頁面結構,使用的技術也是相差殆盡。因為網頁的不同,導致了一個通用的邏輯是幾乎不可能的,很難找到一套通用的邏輯,能夠去適配所有的網站內容。這樣看來,解決方法似乎只有挨著挨著對每個網站進行單獨的適配。接著為了更方便地適配,我們又利用了配置即代碼的思想,將適配的工作轉換成了配置字段的工作。這樣的另一個好處就是,用戶也可以參與到適配工作起來。

同時,在進行配置的時候,最好不要直接使用下面幾個字段,這樣會導致覆蓋掉原先的配置項,而是採用 selector.add excludeSelector.add 這幾個字段以繼承的方式,在原先的配置項的基礎上進行修改

下面,我們將會介紹沉浸式翻譯對站點的適配工作

下面是推特的 Rules,為了簡潔,我們將關注其中的幾個關鍵字段,剩餘字段可以結合上文中的 Rules 理解

[
{
"id": "twitter",
"matches": [
"twitter.com",
"mobile.twitter.com",
"tweetdeck.twitter.com",
{
"pro.twitter.com",
"https://platform.twitter.com/embed*"
],
"selectors": [
// 指定翻譯的元素,只會翻譯選擇器匹配到的元素
"[data-testid=\"tweetText\"]",
".tweet-text",
".js-quoted-tweet-text",
"[data-testid='card.layoutSmall.detail'] > div:nth-child(2)",
"[data-testid='developerBuiltCardContainer'] > div:nth-child(2)",
"[data-testid='card.layoutLarge.detail'] > div:nth-child(2)",
"[data-testid='cellInnerDiv'] div[data-testid='UserCell'] > div> div:nth-child(2)",
"[data-testid='UserDescription']",
"[data-testid='HoverCard'] div[dir=auto]",
"[data-testid='HoverCard'] span[dir=auto]",
"[data-testid='HoverCard'] [role='dialog'] div[dir=ltr]",
"[data-testid='birdwatch-pivot'] div[dir=ltr]"
],
"excludeSelectors": [
// 不會翻譯的被CSS選擇器選中的元素
"[aria-describedby][role=button]",
"header",
"[data-testid='radioGroupplayback_rate'] div",
"[data-testid='userFollowIndicator']",
"[class='css-901oao r-14j79pv r-37j5jr r-n6v787 r-16dba41 r-1cwl3u0 r-bcqeeo r-qvutc0']",
"[class='css-175oi2r r-1wbh5a2 r-dnmrzs']"
],
"globalStyles": {
// 全球樣式,強制覆蓋掉原樣式
"[data-testid='card.layoutLarge.detail'] > div:nth-child(2)": "-webkit-line-clamp: unset;",
"[data-testid='card.layoutSmall.detail'] > div:nth-child(2)": "-webkit-line-clamp: unset;",
"[data-testid='tweetText']": "-webkit-line-clamp: unset;"
}
}
- `selector`: 指定翻譯的元素集合

為什麼需要這個字段

- 因為不是所有元素都有文字且需要翻譯的,提供這樣一個字段既可以保證性能又可以保證用戶的沉浸式體驗

舉個例子

- 在推特中,如果我們不指定 selector,那麼他將會將頁面中的所有識別為英文的文字都進行翻譯一遍,如下圖,用戶的昵稱往往是不需要翻譯的。

![用戶主頁](twitterUser.png)

字段含義

- ```
"selectors": [ // 會被翻譯的CSS選擇器集合
"[data-testid=\"tweetText\"]",
]
```

這裡數組的每一項都是一個 CSS 選擇器,用來選擇頁面中的需要翻譯的元素,這裡我們以第一個選擇器為例,如下圖所示,第一個選擇器命中的是所有推文的元素

![tweet](tweet.png)

- `excludeSelectors`: 不會被翻譯的元素集合

為什麼需要這個字段

- 因為一個僅翻譯的選擇器是不夠的,可能會出現,匹配中的元素卻不需要翻譯的,即兩者可能存在重合的部分,因此需要再設置一個字段來排除掉不需要翻譯的元素
- 由於頁面結構是非常複雜的,提供這樣兩個配置項,讓配置更加靈活
- 相關的優先級是:對於同等選擇器,selectors > excludeSelectors,剩下的依靠 CSS 優先級來比較

字段含義

- ```
"excludeSelectors": [ // 不會翻譯的被CSS選擇器選中的元素
"[aria-describedby][role=button]",
],
```

還是看第一個,這裡我們排除掉了關注按鈕的這個翻譯
![twitter-follow](twitter-follow.png)

- `globalStyles`: 添加全局樣式,強制覆蓋掉原先的樣式

為什麼需要這個字段

- 在某些情況下,因為原先網頁的相關 CSS 樣式,會導致整個的翻譯展示效果不是很好,出現被截斷,不換行等等效果
- 通過這個字段,提供一種暴力的解決方案,直接修改原生網頁的 CSS 屬性來解決

字段含義

- ```
"globalStyles": {
// 全局樣式,強制覆蓋掉原樣式
"[data-testid='card.layoutLarge.detail'] > div:nth-child(2)": "-webkit-line-clamp: unset;",
"[data-testid='card.layoutSmall.detail'] > div:nth-child(2)": "-webkit-line-clamp: unset;",
"[data-testid='tweetText']": "-webkit-line-clamp: unset;"
}
```

`-webkit-line-clamp` 這個屬性用來控制顯示的行數,多餘的行會被截斷,這裡設置成 `unset` ,可以保證譯文不會被這個屬性所截斷
```### 自訂網站適配

關於適配規則,當然你也可以自定義規則,進入到插件選項頁面,點擊[開發者設置](https://dash.immersivetranslate.com/#developer),展開 `Edit User Rules` ,在這裡進行各個網站的自定義適配。下面結合實際規則進行講解

[ { "selectors.remove": [ "[data-testid=\"tweetText\"]" ], "selectors.add": [ "" ], "excludeSelectors.add":[ "" ], "excludeSelectors.remove":[ "" ], "id": "twitter" } ]


這個規則會讓推特頁面的推文不進行翻譯。下面詳細介紹字段的含義

`id` 是沉浸式翻譯目前已經定義好的相關網站的集合,每個 `id` 都對應相關的站點。`id` 的好處有兩個

- 使用 `id` 能繼承沉浸式翻譯之前的適配規則,用戶可以在這基礎上進行增刪
- 使用 `id` 就不用寫繁瑣的匹配字段了

下面介紹一些沉浸式翻譯內置服務的常見的 `id`

- `"isEbook"` epub 閱讀器頁面的配置
- `"isEbookBuilder"` 生成 epub 雙語書頁面的配置
- `"pdf"` pdf 雙語對照翻譯頁面的配置

完整的 `id` 集合可以在[開發者設置](https://dash.immersivetranslate.com/#developer)中,`Click to expand the final config` 中找到

`selectors` 負責指定需要翻譯的CSS選擇器,建議使用子項 `.add` `.remove` 在原先的基礎上進行增刪

`excludeSelectors` 負責排除不需要翻譯的CSS選擇器,建議使用子項 `.add` `.remove` 在原先的基礎上進行增刪

**更多講解**

Block 和 inline 的區別,如果想了解更多可以看[這裡](https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements#inline)

- block 元素會獨佔一行,多個相鄰的 block 元素會各自新起一行.
- inline 元素不會獨佔一行,多個相鄰的 inline 元素會排列在同一行裡,直到一行排列不下才會新換一行。