Skip to content

Conversation

@df123
Copy link
Contributor

@df123 df123 commented Oct 2, 2025

1.添加批量翻译功能
Snipaste_2025-10-02_23-04-32

开启批量翻译后点击翻译为全文翻译。将段落用\n\n=====\n\n拼接,翻译完成后再分割。
这样可以尽可能吃满模型的翻译速度和减少模型的头token时间长的问题。

2.优化了翻译状态显示栏。批量翻译时可以看到剩余时间。
Snipaste_2025-10-02_23-03-40

Summary by Sourcery

Enable batch translation by aggregating multiple text items into configurable groups to optimize API usage and reduce latency, and enhance the translation status panel with detailed progress metrics including remaining time and speed estimates.

New Features:

  • Introduce batch translation feature that groups multiple text segments for combined API requests and distributes translated results back to their respective DOM nodes
  • Add UI toggles and input controls for enabling/disabling batch translation and configuring batch size

Enhancements:

  • Extend translation queue status with character counts, completion percentage, estimated remaining time, and average speed
  • Enhance translation progress panel to display progress percentage, remaining time, character stats, and real-time progress bar styling based on completion

@sourcery-ai
Copy link

sourcery-ai bot commented Oct 2, 2025

Reviewer's Guide

This PR adds a batch translation feature that groups multiple text nodes to maximize model throughput, extends the translation queue to track character-level progress and expose speed and ETA, introduces a persistent statistics manager to compute average speed and estimate remaining time, revamps the floating UI to display detailed real-time progress and stats, and updates configuration and UI controls to enable and tune batch translation.

Sequence diagram for batch translation process

sequenceDiagram
    actor User
    participant MainVue
    participant BatchTranslationManager
    participant TranslateQueue
    participant TranslationStatsManager
    participant TranslationStatusUI
    User->>MainVue: Enable batch translation & set batch size
    User->>MainVue: Initiate translation
    MainVue->>BatchTranslationManager: Collect text nodes
    BatchTranslationManager->>BatchTranslationManager: Group texts by batch size
    BatchTranslationManager->>TranslateQueue: Enqueue batch translation (with char count)
    TranslateQueue->>TranslationStatsManager: Start translation, track stats
    TranslateQueue->>TranslateQueue: Process translation
    TranslateQueue->>TranslationStatsManager: Complete translation, update stats
    TranslateQueue->>BatchTranslationManager: Return translated batch
    BatchTranslationManager->>MainVue: Apply translation to DOM nodes
    TranslationStatsManager->>TranslationStatusUI: Update progress, speed, ETA
    TranslationStatusUI->>User: Show real-time progress
Loading

File-Level Changes

Change Details Files
Implement batch translation manager and integrate into translation flow
  • Add BatchTranslationManager for grouping, merging, splitting and applying translations
  • Hook batchTranslationManager in trans.ts to collect nodes, debounce and trigger grouped translations
  • Expose batch translation toggle and size input in Main.vue with change handling and validation
entrypoints/utils/batchTranslation.ts
entrypoints/main/trans.ts
components/Main.vue
Extend translation queue to report character-based progress
  • Track total and completed characters and pending tasks in translateQueue
  • Add getExtendedQueueStatus and resetQueueStats APIs for detailed progress
  • Modify translateApi to forward characterCount when enqueuing translations
entrypoints/utils/translateQueue.ts
entrypoints/utils/translateApi.ts
Introduce translation stats manager for speed and ETA estimation
  • Create TranslationStatsManager to persist history, compute averageSpeed and ETA
  • Expose startTranslation and completeTranslation hooks and ready promise
  • Integrate stats manager in queue wrapper to update metrics
entrypoints/utils/translationStats.ts
Revamp translation status UI to show real-time progress and stats
  • Redesign TranslationStatus.vue to display percentage, progress bar, remaining time and detailed stats
  • Implement countdown logic, computed styles and watchers for ETA updates
  • Adjust layout and styling for expanded width and dark mode support
components/TranslationStatus.vue
Update configuration model and options for batch translation
  • Add batchTranslationEnabled and batchTranslationSize defaults in model.ts and option.ts
  • Implement handleBatchSizeChange in Main.vue with validation and user feedback
entrypoints/utils/model.ts
entrypoints/utils/option.ts
components/Main.vue

Possibly linked issues

  • #[ISSUE_ID]: The PR implements a batch translation feature that directly addresses the issue's suggestion to improve translation efficiency by combining multiple text segments into a single request, thereby reducing the time consumed by the first token.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

Blocking issues:

  • User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities (link)
  • User controlled data in a node.innerHTML is an anti-pattern that can lead to XSS vulnerabilities (link)

General comments:

  • TranslationStatus.vue has gotten quite complex with countdown and formatting logic—consider extracting the timer and formatRemainingTime/formatNumber into a reusable composable or utility for clarity and testability.
  • The setInterval in onMounted may fire overlapping updateStatus calls if one takes longer than 500ms—switch to a recursive setTimeout or guard to avoid concurrent async updates.
  • The MutationObserver used for batch translations isn't explicitly disconnected when toggling the feature off—add cleanup logic to disconnect observers and prevent memory leaks.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- TranslationStatus.vue has gotten quite complex with countdown and formatting logic—consider extracting the timer and formatRemainingTime/formatNumber into a reusable composable or utility for clarity and testability.
- The setInterval in onMounted may fire overlapping updateStatus calls if one takes longer than 500ms—switch to a recursive setTimeout or guard to avoid concurrent async updates.
- The MutationObserver used for batch translations isn't explicitly disconnected when toggling the feature off—add cleanup logic to disconnect observers and prevent memory leaks.

## Individual Comments

### Comment 1
<location> `entrypoints/utils/batchTranslation.ts:132-141` </location>
<code_context>
+  const characterCount = origin.length;
+
+  // 使用队列处理翻译请求(支持字符计数)
   return enqueueTranslation(async () => {
     // 创建翻译任务
     const translationTask = async (retryCount: number = 0): Promise<string> => {
@@ -94,7 +97,7 @@ export async function translateText(origin: string, context: string = document.t

     // 开始执行翻译任务
     return translationTask();
-  });
+  }, characterCount);
 }

 /**
diff --git a/entrypoints/utils/translateQueue.ts b/entrypoints/utils/translateQueue.ts
index 7e792bd..de59db6 100644
--- a/entrypoints/utils/translateQueue.ts
+++ b/entrypoints/utils/translateQueue.ts
@@ -1,14 +1,38 @@
 /**
  * 翻译队列管理模块
  * 控制并发翻译任务的数量,避免同时进行过多翻译请求
+ * 扩展支持字符计数和进度监控
  */

 import { config } from './config';
+import { translationStatsManager } from './translationStats';

 // 队列状态
 let activeTranslations = 0; // 当前活跃的翻译任务数量
</code_context>

<issue_to_address>
**issue (bug_risk):** Error handling in batch translation may leave some items untranslated if a group fails.

Consider adding fallback logic to update nodes with the original text or an error message when a translation group fails, to prevent inconsistent states.
</issue_to_address>

### Comment 2
<location> `entrypoints/utils/batchTranslation.ts:189-191` </location>
<code_context>
+    const originalSegments = originalText.split(this.separator);
+    const translatedSegments = translatedText.split(this.separator);
+
+    // 如果分割后的数量不匹配,返回整个翻译文本
+    if (originalSegments.length !== translatedSegments.length) {
+      return [translatedText];
+    }
+
</code_context>

<issue_to_address>
**issue (bug_risk):** Segment mismatch fallback may result in incorrect node updates.

When segment counts differ, all nodes receive the full translated text, which may confuse users. Consider skipping the update or showing a warning to prevent misleading output.
</issue_to_address>

### Comment 3
<location> `entrypoints/utils/translateQueue.ts:91-92` </location>
<code_context>
       }
     };

+    // 更新总字符数
+    totalCharacters += characterCount;
+    
+    // 记录当前任务
</code_context>

<issue_to_address>
**issue (bug_risk):** Accumulating totalCharacters may overcount if tasks are retried or fail.

Increment totalCharacters only after a task completes successfully, or separately track retries to avoid double-counting.
</issue_to_address>

### Comment 4
<location> `entrypoints/utils/batchTranslation.ts:225` </location>
<code_context>
      node.innerHTML = translatedText;
</code_context>

<issue_to_address>
**security (javascript.browser.security.insecure-document-method):** User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 5
<location> `entrypoints/utils/batchTranslation.ts:225` </location>
<code_context>
      node.innerHTML = translatedText;
</code_context>

<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):** User controlled data in a `node.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 6
<location> `entrypoints/utils/batchTranslation.ts:120` </location>
<code_context>
    const combinedText = group.combinedText;

</code_context>

<issue_to_address>
**suggestion (code-quality):** Prefer object destructuring when accessing and using properties. ([`use-object-destructuring`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/TypeScript/Default-Rules/use-object-destructuring))

```suggestion
    const {combinedText} = group;
```

<br/><details><summary>Explanation</summary>Object destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the [Airbnb Javascript Style Guide](https://airbnb.io/javascript/#destructuring--object)
</details>
</issue_to_address>

### Comment 7
<location> `entrypoints/utils/batchTranslation.ts:205` </location>
<code_context>
    const node = item.node;

</code_context>

<issue_to_address>
**suggestion (code-quality):** Prefer object destructuring when accessing and using properties. ([`use-object-destructuring`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/TypeScript/Default-Rules/use-object-destructuring))

```suggestion
    const {node} = item;
```

<br/><details><summary>Explanation</summary>Object destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the [Airbnb Javascript Style Guide](https://airbnb.io/javascript/#destructuring--object)
</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +132 to +141
return enqueueTranslation(async () => {
try {
const result = await Promise.race([
browser.runtime.sendMessage({ context: document.title, origin: combinedText }),

new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error('翻译请求超时')), 60000)
)
]) as string;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Error handling in batch translation may leave some items untranslated if a group fails.

Consider adding fallback logic to update nodes with the original text or an error message when a translation group fails, to prevent inconsistent states.

Comment on lines +189 to +191
// 如果分割后的数量不匹配,返回整个翻译文本
if (originalSegments.length !== translatedSegments.length) {
return [translatedText];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Segment mismatch fallback may result in incorrect node updates.

When segment counts differ, all nodes receive the full translated text, which may confuse users. Consider skipping the update or showing a warning to prevent misleading output.

Comment on lines +91 to +92
// 更新总字符数
totalCharacters += characterCount;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Accumulating totalCharacters may overcount if tasks are retried or fail.

Increment totalCharacters only after a task completes successfully, or separately track retries to avoid double-counting.

node.appendChild(translationNode);
} else {
// 单语模式
node.innerHTML = translatedText;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (javascript.browser.security.insecure-document-method): User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

node.appendChild(translationNode);
} else {
// 单语模式
node.innerHTML = translatedText;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (javascript.browser.security.insecure-innerhtml): User controlled data in a node.innerHTML is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

return;
}

const combinedText = group.combinedText;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Prefer object destructuring when accessing and using properties. (use-object-destructuring)

Suggested change
const combinedText = group.combinedText;
const {combinedText} = group;


ExplanationObject destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the Airbnb Javascript Style Guide

return;
}

const node = item.node;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Prefer object destructuring when accessing and using properties. (use-object-destructuring)

Suggested change
const node = item.node;
const {node} = item;


ExplanationObject destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the Airbnb Javascript Style Guide

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant