# FluentRead Content Script Explained: How content.ts Orchestrates Page Translation

> Discover how FluentRead's content.ts script orchestrates page translation by injecting UI components and managing translation triggers on matched websites.

- Repository: [ThinkStu/fluentread](https://github.com/bistutu/fluentread)
- Tags: internals
- Published: 2026-02-26

---

**The [`content.ts`](https://github.com/bistutu/fluentread/blob/main/content.ts) script serves as the central orchestrator that injects UI components, registers translation triggers, and manages the lifecycle of FluentRead's page translation features on every matched website.**

FluentRead is an open-source browser extension that translates web content in real-time. At the heart of this functionality lies [`entrypoints/content.ts`](https://github.com/bistutu/fluentread/blob/main/entrypoints/content.ts), the **content script** that runs inside every web page the extension matches. This script coordinates configuration loading, UI mounting, event handling, and cleanup to deliver seamless translation experiences.

## What Is the FluentRead Content Script?

Browser extensions use content scripts to execute JavaScript in the context of web pages. In FluentRead, [`entrypoints/content.ts`](https://github.com/bistutu/fluentread/blob/main/entrypoints/content.ts) acts as the primary entry point that bridges the extension's background logic with the user's browsing experience. It runs on `<all_urls>` matches, meaning it activates on virtually every website the user visits.

## Core Responsibilities of content.ts

The script organizes its workflow into four distinct operational areas.

### Initialization and Configuration Validation

Before mounting any UI elements, [`content.ts`](https://github.com/bistutu/fluentread/blob/main/content.ts) waits for the extension's configuration to load using `await configReady`. It immediately aborts execution if the user has disabled the extension:

```typescript
await configReady;
if (config.on === false) return;

```

This early exit prevents unnecessary resource consumption when FluentRead is toggled off.

### UI Component Mounting

Once validated, the script dynamically injects interactive elements based on user preferences. It conditionally mounts four primary components:

```typescript
if (config.disableFloatingBall !== true) {
  mountFloatingBall();               // Draggable quick-toggle button
}
if (config.disableSelectionTranslator !== true) {
  mountSelectionTranslator();        // Hover-to-translate functionality
}
mountTranslationStatusComponent();   // Visual feedback overlay
mountNewApiComponent();              // Advanced settings interface

```

Each mount function resides in dedicated utility files under `entrypoints/utils/`.

### Event Wiring and Translation Triggers

The content script registers multiple input mechanisms for triggering translations. It sets up manual translation hotkeys through `setupManualTranslationTriggers()` and configures the floating ball shortcut via `setupFloatingBallHotkey()`.

For automatic translation of English pages, it invokes `autoTranslationEvent()`. Additionally, it listens for background script messages to handle cache clearing, floating ball toggles, and context menu actions:

```typescript
browser.runtime.onMessage.addListener((msg, _, reply) => {
  if (msg.type === 'contextMenuTranslate') {
    if (msg.action === 'fullPage') {
      autoTranslateEnglishPage();
      reply({ status: 'success', action: 'translated' });
    } else if (msg.action === 'restore') {
      restoreOriginalContent();
      reply({ status: 'success', action: 'restored' });
    }
    return true;
  }
  return false;
});

```

### Lifecycle Management and Cleanup

To prevent memory leaks and orphaned processes, [`content.ts`](https://github.com/bistutu/fluentread/blob/main/content.ts) registers a `beforeunload` listener that cancels pending translations, unmounts UI components, and clears caches when the user navigates away:

```typescript
window.addEventListener('beforeunload', () => {
  // Cleanup logic: cancel translations, unmount UI, clear caches
});

```

## Integration with the FluentRead Architecture

The content script does not operate in isolation. It imports core translation logic from [`entrypoints/main/trans.ts`](https://github.com/bistutu/fluentread/blob/main/entrypoints/main/trans.ts), which provides `handleTranslation`, `autoTranslateEnglishPage`, and `restoreOriginalContent`. Configuration management resides in [`entrypoints/utils/config.ts`](https://github.com/bistutu/fluentread/blob/main/entrypoints/utils/config.ts), while UI components are modularized into [`floatingBall.ts`](https://github.com/bistutu/fluentread/blob/main/floatingBall.ts), [`selectionTranslator.ts`](https://github.com/bistutu/fluentread/blob/main/selectionTranslator.ts), and related utilities.

This separation of concerns allows [`content.ts`](https://github.com/bistutu/fluentread/blob/main/content.ts) to focus solely on orchestration—deciding when to load, what to display, and how to respond to user input—while delegating implementation details to specialized modules.

## Summary

- **content.ts** serves as the primary content script entry point for FluentRead, executing on every matched web page.
- It validates configuration before mounting any UI components to respect user preferences and disabled states.
- The script dynamically injects four key UI elements: the floating ball, selection translator, status overlay, and advanced settings interface.
- It wires multiple translation triggers including hotkeys, context menu actions, and automatic page translation.
- Comprehensive cleanup logic prevents memory leaks when users navigate away from pages.

## Frequently Asked Questions

### What happens if I disable FluentRead in the settings?

When the extension is disabled (`config.on === false`), [`content.ts`](https://github.com/bistutu/fluentread/blob/main/content.ts) exits immediately after the configuration loads. This prevents any UI injection, event registration, or background processing, ensuring zero performance impact on your browsing experience.

### Can I use FluentRead without the floating ball interface?

Yes. The content script checks `config.disableFloatingBall` before calling `mountFloatingBall()`. If you disable this feature in settings, the draggable toggle button will not appear, though you can still trigger translations via hotkeys or the selection translator.

### How does the content script handle page navigation?

[`content.ts`](https://github.com/bistutu/fluentread/blob/main/content.ts) registers a `beforeunload` event listener that executes cleanup routines when you leave a page. This cancels pending translation requests, removes injected UI components, and clears temporary caches to free memory and prevent orphaned processes.

### Where does the actual translation logic reside?

While [`content.ts`](https://github.com/bistutu/fluentread/blob/main/content.ts) orchestrates the user interface and events, the core translation engine lives in [`entrypoints/main/trans.ts`](https://github.com/bistutu/fluentread/blob/main/entrypoints/main/trans.ts). This module exports functions like `handleTranslation` and `autoTranslateEnglishPage`, which the content script imports and invokes based on user interactions.