# Account and Plans (/en/docs/account-and-plans) Translation does not need an account. Install the extension, pick a provider, and read — nothing on this page is required for that. An account exists for the parts that have to live on a server: your [Notebase](/docs/notebase), your review schedule, your statistics, and anything an assistant reaches over [MCP](/docs/mcp). ## What an account adds [#what-an-account-adds] | | Without an account | Signed in | | ----------------------------------------------- | --------------------- | ---------------------- | | Page, selection, input and subtitle translation | Yes | Yes | | Your own API keys | Yes | Yes | | Glossary, custom prompts, custom CSS | Yes | Yes | | Built-in AI, for Custom AI Actions | Small daily allowance | Larger daily allowance | | Notebase, card templates, review, statistics | No | Yes | | MCP | No | Ultra only | Everything in the first three rows is stored in your browser profile, which is why it works signed out — and why it does not follow you to another computer unless you sync it yourself. See [Configuration, Sync & Backups](/docs/config-backup). ## The built-in AI allowance [#the-built-in-ai-allowance] Read Frog ships two providers of its own — **Built-in AI** and **Advanced Built-in AI**, the second using a stronger model. Both draw on an allowance rather than an API key of yours. **Below Ultra, that allowance funds Custom AI Actions and nothing else.** Page translation, selection translation, note suggestions, video subtitles, input translation and language detection are all deliberately unfunded on the free and Pro tiers — Read Frog reports them as needing an upgrade rather than as being out of quota. Ultra funds every one of them from a single weekly pool. | | Custom AI Actions | Everything else | | --------------- | -------------------------------------------- | ---------------- | | Not signed in | Small daily allowance, keyed to your network | Not funded | | Signed in, free | Larger daily allowance | Not funded | | Pro | Larger daily allowance again | Not funded | | Ultra | One weekly pool | Same weekly pool | So on any plan below Ultra, **whole-page translation runs on a provider of your own**, which is the normal way to use Read Frog: Google Translate and Microsoft Translator need no key at all, and an LLM provider needs yours. Assigning your own provider to a feature in [API Providers](/docs/providers/overview) stops it drawing on the allowance entirely — **your own API key has no Read Frog limit**, only whatever your provider charges you. Daily allowances reset each UTC day. The Ultra pool is a rolling week anchored to your subscription rather than a calendar week, so a heavy reading day is not capped by that day alone. Because it is one pool, video subtitles — by far the most expensive feature per minute of use — share it with everything else. ## What the paid plans unlock [#what-the-paid-plans-unlock] Current prices are on the [pricing page](https://readfrog.app/pricing); they are not repeated here so this page cannot go stale. What the tiers change: * **Pro** raises the Custom AI Actions allowance and includes the AI subtitles quota described in [AI Segmentation and Subtitles Quota](/docs/video-subtitles/ai-segmentation). * **Ultra** is the only plan whose allowance funds anything beyond Custom AI Actions, and the only one that can connect an AI assistant over [MCP](/docs/mcp). That restriction is enforced on the server, so an assistant on a lower plan is refused at connection time rather than failing later. ## Signing in [#signing-in] Sign in from the extension popup or at [readfrog.app](https://readfrog.app); it is the same account either way, and the extension picks up the session from the website. If the popup still shows **Guest** after signing in on the website, reload the page you are on — the extension reads the session when a tab loads. ## Deleting your account [#deleting-your-account] Account deletion is available from the account settings on the website and removes your notes, cards and review history. It is not reversible, and it does not uninstall the extension or clear the settings stored in your browser profile — do that from the browser's extensions page. # Configuration, Sync & Backups (/en/docs/config-backup) Open **Options → Config** to move or recover settings. Interface language is configured separately under **Options → General**. ## Export safely [#export-safely] The export dialog lets you include or exclude provider API keys. Exclude keys for normal backups, bug reports, shared files, and version control. Include them only when moving your own configuration through storage you trust. An export containing API keys is a credential file. Anyone who obtains it may be able to spend your provider quota or access your account. ## Import and validation [#import-and-validation] Read Frog validates and migrates imported configuration before applying it. It also creates a backup of the current configuration first, so you can restore if the imported settings are valid but unsuitable. Importing replaces many current values. Review providers, target language, Site Control, and per-tool disabled websites afterward—especially when the file came from another browser profile. ## Google Drive manual sync [#google-drive-manual-sync] Connect Google Drive from the Config page, then start sync manually when you want to exchange settings with another browser. Google Drive sync controls in Read Frog settings If only one side changed, Read Frog can use the newer copy. If both local and remote values changed, the conflict dialog lets you choose local or remote values per field, or select all local/all remote before confirming. Choosing local or remote settings during a Google Drive conflict Validate the merged configuration in the dialog before applying it. Manual sync avoids silent background overwrites, but it also means changes do not appear on another device until you start sync there. ## Automatic and manual backups [#automatic-and-manual-backups] Read Frog checks for changed configuration about every 60 minutes and creates an automatic backup only when something changed. It keeps up to eight backups. You can also: * create a manual backup before an experiment; * restore a selected backup; * export a backup to a file; * delete backups you no longer need. Backups are local to the browser profile unless you export or sync them. Before editing large Site Rules or prompt sets, make a manual backup with a recognizable timestamp. ## Interface language [#interface-language] **Options → General → Interface Language** controls the Read Frog UI independently from the browser's display language. Changing it does not change translation source/target languages or website language detection. ## Beta Experience and reset [#beta-experience-and-reset] Beta Experience enables experimental features that explicitly depend on it. Text to Speech is labeled Public Beta but no longer requires this switch. Reset restores the default configuration. It is appropriate when a migrated or heavily edited setup cannot be repaired, but it removes customized providers, prompts, rules, and tool choices. Export without keys for support, and create a secure backup if you need credentials, before resetting. ## Recovery sequence [#recovery-sequence] When a configuration change causes a problem: 1. export the current state without API keys for inspection; 2. restore the most recent known-good local backup; 3. if necessary, import a trusted export; 4. reconnect Google Drive and resolve conflicts deliberately; 5. use Reset only after the earlier recovery paths fail. This order preserves the most evidence and gives you the easiest route back. # Contribution Guide (/en/docs/contributing) ## Getting Started [#getting-started] ### Step 1: Fork the repository and clone it to your local machine [#step-1-fork-the-repository-and-clone-it-to-your-local-machine] ```bash # Clone the repository from your fork git clone https://github.com/xxxxx/read-frog.git # Enter the project directory cd read-frog # Add the upstream remote to sync with the original repository git remote add upstream https://github.com/mengxi-ream/read-frog.git ``` ### Step 2: Install dependencies and start development [#step-2-install-dependencies-and-start-development] ```bash # Install dependencies pnpm i # Start the development server pnpm dev ``` This will start the extension development environment. The extension will automatically open in your default browser. ## Development Tips [#development-tips] ### Using npx with pnpm Node.js Management [#using-npx-with-pnpm-nodejs-management] We're using pnpm's built-in Node.js version management (introduced in pnpm 10.14). You may encounter `EBADDEVENGINES` errors when running `npx` commands. There are two solutions: **Solution 1: Use `pnpm dlx` or `pnpx` instead of `npx`** ```bash # Instead of npx npx some-package@latest # Use pnpm dlx pnpm dlx some-package@latest # Or use pnpx (alias for pnpm dlx) pnpx some-package@latest ``` **Solution 2: Align Node.js version with pnpm** When it's not convenient to replace `npx` (e.g., for user-scoped MCP installations in Claude Code), align your Node.js version: ```bash # Install and use the required Node.js version globally pnpm env use --global 22.18.0 ``` ### Open the extension in the specific browser [#open-the-extension-in-the-specific-browser] You can create/modify the `web-ext.config.ts` file in the root directory to explicitly specify the browser path. ```javascript // web-ext.config.ts import { defineWebExtConfig } from "wxt"; export default defineWebExtConfig({ binaries: { chrome: "path/to/your/chrome.exe", firefox: "path/to/your/firefox.exe", edge: "path/to/your/edge.exe", }, }); ``` ### pnpm dev can't load the extension automatically [#pnpm-dev-cant-load-the-extension-automatically] If you use Chrome version 137 or higher, you need to download [Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing/) for development. See [details](https://wxt.dev/guide/essentials/config/browser-startup.html). ### Persistent Chrome Profile [#persistent-chrome-profile] **By default, web-ext creates a new profile every time you run the dev script.** If you want to keep logins, devtools extensions, and browser settings between development sessions, create or update `web-ext.config.ts` in the project root. The persistent profile configuration is slightly different across operating systems: macOS/Linux Windows ```typescript // web-ext.config.ts import { defineWebExtConfig } from "wxt"; export default defineWebExtConfig({ chromiumArgs: ["--user-data-dir=./.wxt/chrome-data"], }); ``` ```typescript // web-ext.config.ts import { resolve } from "node:path"; import { defineWebExtConfig } from "wxt"; export default defineWebExtConfig({ // On Windows, the path must be absolute chromiumProfile: resolve(".wxt/chrome-data"), keepProfileChanges: true, }); ``` On Windows, WXT recommends using `chromiumProfile` and `keepProfileChanges`. The `chromiumProfile` path must be absolute, so use `resolve` from `node:path`. **Benefits:** Your profile persists between dev sessions, so you can: * Install devtools extensions * Remember logins * Keep browser settings **💡 Tip:** Persistent profiles only apply to Chromium browsers. You can replace `.wxt/chrome-data` in the examples to use a separate profile directory for each project. ### Google Login Issues in Dev Mode [#google-login-issues-in-dev-mode] If you want to login with a Google account in dev mode and encounter the error **"This browser or app may not be secure."**, you need to disable automation detection. **Solution:** Add `chromiumArgs` to your `web-ext.config.ts`: ```typescript // web-ext.config.ts import { defineWebExtConfig } from "wxt"; export default defineWebExtConfig({ chromiumArgs: ["--disable-blink-features=AutomationControlled"], }); ``` This disables the automation detection that causes Google to block login attempts from automated browsers. ### Breakpoint Debugging Issues [#breakpoint-debugging-issues] ⚠️ If you encounter issues with breakpoint debugging, it might be due to Chrome DevTools ignore list settings. Content scripts injected by extensions may be automatically ignored, causing breakpoints to fail. **Solution:** 1. Open DevTools on any webpage 2. Click the settings icon (⚙️) in the top right corner 3. Select "Ignore list" from the left navigation 4. Ensure the "Content scripts injected by extensions" option is **unchecked** Chrome Ignore List ### macOS: Too Many Open Files Error (EMFILE) [#macos-too-many-open-files-error-emfile] If you encounter this error on macOS when running `pnpm dev`: Emfile Error This happens because Chokidar (the file watching library used by Vite/WXT) defaults to using macOS's native FSEvents, which requires a file descriptor for each watched file/directory. Large projects can exceed the system limit. **Solution:** Set `CHOKIDAR_USEPOLLING=true` to switch to polling mode, which doesn't require file descriptors. Create or update the `.env` file in the project root: ```bash # .env CHOKIDAR_USEPOLLING=true ``` After this, `pnpm dev` will work without the EMFILE error. **Note:** Polling mode is slightly slower and uses more CPU, but it avoids the file descriptor limit issue. ## Submitting Code [#submitting-code] ### Create a new branch [#create-a-new-branch] ```bash # For new features git checkout -b feat/the-feature # For bug fixes git checkout -b fix/the-bug # For docs modify git checkout -b docs/the-docs ``` ### Merge Branch [#merge-branch] If the remote main branch gets updated and creates conflicts in our PR, you can resolve it by merging the remote branch in advance . ```bash # Switch to the main branch git checkout main # Pull the latest code from upstream git pull upstream main # Switch back to your local branch git checkout docs/xxxx # Merge the main branch into your local branch git rebase main # Push the code again if there are conflicts after rebase git push --force-with-lease origin docs/xxxx # If there are no conflicts, push the code again git push origin docs/xxxx ``` If you encounter this error while syncing the upstream repository `bash fatal: 'upstream' does not appear to be a git repository fatal: Could not read from remote repository. ` This means the upstream remote was not configured in Step 1. Add it now: `bash git remote add upstream https://github.com/mengxi-ream/read-frog.git ` ## Generating Pull Request [#generating-pull-request] Before generating a Pull Request, you need to add a changeset to document your changes. ### Understanding Version Bumps [#understanding-version-bumps] Choose the appropriate version bump type based on your changes: * **patch** - Bug fixes, typos, documentation updates, minor improvements * Example: Fix translation error, update README, fix button styling, performance improvements * **minor** - New features that are backward compatible * Example: Add disable translation button, add vocabulary export feature * **major** - Breaking changes that affect existing functionality * Example: Change API structure, remove deprecated features, major refactoring ### Adding a Changeset [#adding-a-changeset] ```bash # Run the changeset command pnpm changeset # 1. Choose version bump type for each selected package 🦋 What kind of change is this for @read-frog/extension? ❯ patch # For bug fixes and minor improvements minor # For new features major # For breaking changes # 2. Write a summary of your changes 🦋 Please enter a summary for this change (this will be in the changelog) Summary >>> fix: translation button style ``` After running `pnpm changeset`, a markdown file will be generated in the `.changeset` directory. You can edit this file to provide more details about your changes before creating the Pull Request. Then create a Pull Request and wait for it to be merged. ## Commit Convention [#commit-convention] We use the [Conventional Commits](https://www.conventionalcommits.org/) specification for writing commit messages. ## Set environment variables [#set-environment-variables] To automatically load environment variables while developing the extension, such as API keys for the development environment, you can create a `.env.development` file in the root directory. ```bash # .env.development WXT_OPENAI_API_KEY=xxx WXT_DEEPSEEK_API_KEY=xxx ``` WXT loads dotenv files following Vite conventions. Variables that need to be accessed from extension code via `import.meta.env` should use the `WXT_` prefix. If you only need to set an environment variable for a single command, the syntax depends on your shell: macOS/Linux Windows PowerShell Windows CMD ```bash SKIP_FREE_API=true pnpm test ``` ```powershell $env:SKIP_FREE_API='true'; pnpm test # Remove it when you no longer need it Remove-Item Env:SKIP_FREE_API ``` ```cmd set SKIP_FREE_API=true && pnpm test ``` The default Windows shells do not support the macOS/Linux `KEY=value command` syntax. If a command fails for that reason, use the PowerShell or CMD form above. For WXT variables that you use regularly, prefer putting them in `.env.development`. ## Skip Google API Tests in China [#skip-google-api-tests-in-china] If you are a contributor from mainland China, when you need to push code, use the following command: macOS/Linux Windows PowerShell Windows CMD ```bash SKIP_FREE_API=true git push ``` ```powershell $env:SKIP_FREE_API='true' git push ``` ```cmd set SKIP_FREE_API=true git push ``` Why is this necessary? Because code tests are performed during the push process, but Google's free API is inaccessible in mainland China. This would cause the tests to fail and the push to be rejected. By setting the `SKIP_FREE_API` environment variable, we skip the Google tests. ## What kind of PRs will be reviewed and merged? [#what-kind-of-prs-will-be-reviewed-and-merged] ### Getting Started with Contributions [#getting-started-with-contributions] If this is one of your first PRs, and you are serious about contributing, it generally won't be rejected due to quality issues. Maintainers will help you identify problems and adapt to our development process and code style. However, we strongly recommend following these guidelines: 1. Start with small issues, such as "Good First Issue" in the repository. Small, simple PRs provide a smooth learning process. 2. Ensure your PR passes all GitHub Actions and local tests. ### Why isn't my PR getting reviewed by maintainers? [#why-isnt-my-pr-getting-reviewed-by-maintainers] 1. You contributed an overly complex PR before familiarizing yourself with the codebase, resulting in too many required changes. 2. Your code contains many basic errors, making maintainers question your seriousness: * Unused code snippets that weren't removed * Excessive repetitive code * Variable and function names are too arbitrary * We encourage AI-assisted development, but you didn't carefully review the AI-generated code, leading to low-quality, unmaintainable, or over-engineered code 3. Maintainers provided modification suggestions multiple times, but you either didn't follow them or your changes didn't address the root issues. # Custom AI Actions (/en/docs/custom-actions) ## Overview [#overview] Custom AI Actions turn a prompt into a small tool that you can run again and again. The core idea is simple. After you select text, Read Frog sends that text to AI with a fixed setup. Each action has: * an LLM provider * prompts * output fields This is different from a normal chat box. The result is more stable. It works well for repeated reading tasks, such as dictionary lookup, explanation, rewriting, and summaries. Before you use this feature, make sure you have enabled at least one LLM provider that supports structured output and can connect successfully. If you are not sure whether your model supports structured output, check [AI SDK Model Capabilities](https://ai-sdk.dev/docs/foundations/providers-and-models#model-capabilities) or the model provider's official docs. ## Built-in AI Actions [#built-in-ai-actions] The current version includes three templates: * **Dictionary**: look up a word and return the term, phonetic, part of speech, definition, paragraph text, paragraph translation, and CEFR difficulty * **Improve Writing**: analyze writing problems and return an improved version * **Blank**: start from scratch Notes: * The Custom AI Actions page already includes a default **Dictionary** action. You can study it to learn how prompts and output fields are designed. * If you want a writing helper, click **Add AI Action** and choose **Improve Writing**. ## Learn from the Built-in Dictionary [#learn-from-the-built-in-dictionary] If this is your first time using the feature, start with the built-in dictionary. 1. Set up and enable an LLM provider for reading tasks. 2. Open **Custom AI Actions** and make sure **Dictionary** is enabled. 3. If its provider is not available, switch it to an enabled LLM provider. 4. Go back to any webpage and select a word or a short phrase. 5. Click the dictionary icon in the selection toolbar. Dictionary in the selection toolbar You will see structured results like these: ```markdown - Term - Phonetic - Part of Speech - Definition - Paragraphs - Paragraphs Translation - Difficulty ``` ## Customize Your Own AI Action [#customize-your-own-ai-action] 1. Open Read Frog settings. 2. Go to **Custom AI Actions**. 3. Click **Add AI Action**. 4. Choose a template: **Dictionary**, **Improve Writing**, or **Blank**. 5. Fill in the required fields. 6. Keep the action enabled so it appears in the selection toolbar. The editor supports these fields: * **Name**: the action name * **Icon**: you can search for icons on [icon-sets.iconify.design](https://icon-sets.iconify.design/) and copy the icon name * **Provider**: choose an LLM provider that supports structured output * **System Prompt**: define the role, goal, rules, and examples * **Prompt**: define the input format and explain what the model receives * **Output Schema**: define the structured fields in the result ## Prompt Tokens [#prompt-tokens] Both the system prompt and the main prompt support these tokens: * `{{selection}}`: the selected text * `{{paragraphs}}`: the paragraphs around the selection, joined with blank lines, up to 2000 characters * `{{targetLanguage}}`: the user's target language * `{{webTitle}}`: the page title ## How Output Schema Works [#how-output-schema-works] Each output field includes: * **Field Name** * **Field Type**: `string` or `number` * **Field Description** * **Enable speaking**: the panel shows a speak button, and the user can read this field aloud Notes: * The speaking feature depends on the Text-to-Speech feature. * Make sure the voice language is correct, or playback may fail. The output schema has two jobs: 1. It tells the model which fields must be returned. 2. It tells Read Frog how to show the result. The field description is also important. It is not only a note for humans. It is passed into the structured output rules too. You can use it to define language, length, format, and other constraints. ## Save Results to Notebase [#save-results-to-notebase] When you are logged in, you can use the **Notebase Connection** section while editing an AI action. For the full version check, Notebase setup, field mapping, and testing flow, see the [Notebase Guide](/docs/notebase). Notebase field mapping Here you can: 1. choose a notebase 2. map AI action fields to notebase fields 3. save structured results from the selection panel Save to Notebase This is very useful if you want to turn dictionary results into your own vocabulary list. > In the future, these saved words support review with the FSRS algorithm. ## Build One: Reading Summary Action [#build-one-reading-summary-action] If you want to build your first custom action, start with **Blank** and make a reading summary tool. Summary action demo ### System Prompt [#system-prompt] ```text You are a summary assistant for learners and researchers. ## Goal Read the given article content and produce a clear and accurate summary that matches the required output object. ## Rules 1. Only use information from the given content. Do not add new facts. 2. Focus on the main topic, the core summary, the key points, and important details. 3. Stay faithful to the original meaning. 4. Use clear and simple language that is good for reading and review. 5. Do not rewrite the full text line by line. Extract information instead. 6. Keep important technical or academic terms when needed. 7. Important details should help the reader understand the text better. 8. If a field cannot be determined from the text, return an empty string. 9. Use {{targetLanguage}} for every field except original source content. 10. Keep the output tightly related to the input text. ## Examples ### Example 1 Input: Selection: hybrid models Paragraphs: Remote work has changed how companies operate. It gives employees more flexibility, reduces commuting time, and can improve work-life balance. However, it also creates challenges in communication, team cohesion, and performance management. Many companies are now trying hybrid models to balance flexibility and collaboration. Target language: English Output: - Topic: The impact of remote work on companies and employees - Summary: The text explains that remote work brings flexibility and efficiency benefits, but it also creates problems in communication, team cohesion, and performance management, so many companies now use hybrid work as a practical balance. - Key Points: 1. Remote work gives employees more flexibility.\r\n 2. Remote work reduces commuting time.\r\n 3. Remote work can improve work-life balance.\r\n 4. Remote work can cause communication and teamwork problems.\r\n 5. Hybrid work is a common way to balance flexibility and collaboration.\r\n - Details: 1. The text covers both employee benefits and management challenges.\r\n 2. The main problems are communication, team cohesion, and performance management.\r\n 3. Hybrid work is presented as a practical solution, not just a theory.\r\n ### Example 2 Input: Selection: 誤分類が依然として多かった Paragraphs: この論文では、画像認識における小規模データ問題を解決するために、事前学習済みモデルの転移学習を活用した。実験の結果、少量データ環境でも高い精度が得られたが、特定のカテゴリでは誤分類が依然として多かった。今後はデータ拡張とモデル軽量化が課題である。 Target language: English Output: - Topic: The effect of transfer learning on small-scale image recognition - Summary: The text explains that transfer learning with a pre-trained model helps improve image recognition in small-data settings, but some categories still have many misclassifications, so data augmentation and model compression remain important future tasks. - Key Points: 1. The study aims to solve the small-data problem in image recognition.\r\n 2. It uses transfer learning with a pre-trained model.\r\n 3. The results show high accuracy even with limited data.\r\n 4. Some categories still have clear misclassification problems.\r\n 5. Future work includes data augmentation and model compression.\r\n - Details: 1. The method is effective specifically in low-data settings.\r\n 2. The results are not equally stable across all categories.\r\n 3. The text clearly gives future improvement directions instead of only reporting results.\r\n ``` ### Prompt [#prompt] ```text Selection: {{selection}} Paragraphs: {{paragraphs}} Target language: {{targetLanguage}} ``` ### Output Schema [#output-schema] | Field Name | Field Type | Description | | ---------- | ---------- | -------------------------------------------------------------------------------------------- | | Topic | Text | Summarize the core topic related to `{{selection}}`. | | Summary | Text | Explain the core meaning of `{{selection}}` in one sentence. | | Key Points | Text | Extract the 3 to 5 most relevant points related to `{{selection}}`, separated by `\r\n`. | | Details | Text | List important details that are easy to miss but help the reader understand `{{selection}}`. | This gives you a reusable reading helper for articles, docs, and tutorials. ## Practical Tips [#practical-tips] * Start with fewer fields. Fewer fields usually means more stable results. * Use the **System Prompt** to guide the model and give examples. * Use the **Prompt** to define the current input format. * If the result is unstable, remove fields and simplify the rules first. * For dictionary use, select a word or a short phrase, not a full sentence. ## Troubleshooting [#troubleshooting] ### The AI action exists but does not run [#the-ai-action-exists-but-does-not-run] First check whether the provider for this action is enabled and whether the model supports structured output. ### I do not see the Save to Notebase button [#i-do-not-see-the-save-to-notebase-button] Make sure you are logged in to the same account on readfrog.app, the extension is up to date, and the AI action has a valid **Notebase Connection**. # Entry Points (/en/docs/entry-points) Three surfaces put Read Frog within reach of the page you are on. Each can be turned off on its own, and each is configured under **Options → Overlay Tools**. None of them replaces the others: the button acts on the whole page, the toolbar acts on what you selected, and the context menu does either from the browser's own menu. ## Floating button [#floating-button] A small frog docked to one edge of the page. The Floating Button settings: the enable switch, button side, disabled sites, and click action | Setting | What you can set | | ------------------ | --------------------------------------------------------------------------- | | **Enable** | Whether the button appears on web pages at all | | **Button side** | Left or right edge. The default is right | | **Disabled sites** | URL patterns where the button stays hidden, without affecting anything else | | **Click action** | **Toggle page translation** (the default) or **Open side panel** | You can drag the button up and down its edge, and lock it in place from its own menu once it sits where you want it. That menu also reaches settings, feedback, and two quick exits — **Disable for this site**, which adds the current site to the list above, and **Disable globally**, which flips the enable switch off. ## Selection toolbar [#selection-toolbar] Select text on a page and a small toolbar appears next to it. The Selection Toolbar settings: the enable switch, the action rows, opacity, and disabled sites The **Actions** section decides which buttons the toolbar carries: * **Translate** — translates the selection in place. It also has a keyboard shortcut, Alt + T by default; see [Shortcuts](/docs/shortcuts). * **Speak** — reads the selection aloud with your voice settings from [Text to Speech](/docs/tts). * **Note suggestions** — after an AI translation of the selection, offers the words worth keeping so you can save them to your [Notebase](/docs/notebase). The two rows under the switch choose which action produces the suggestion and which AI provider runs it. Your AI actions appear as buttons of their own alongside these, each with the icon you gave it. The built-in **Dictionary** action is one of them. They are created and enabled in [Custom AI Actions](/docs/custom-actions), not here. Under **Display**, **Opacity** applies to the toolbar and to the window it expands into, and **Disabled sites** takes URL patterns where the toolbar never appears. As with the floating button, the toolbar's own close menu offers **Disable for this site** and **Disable globally**. The toolbar can get in the way on sites where selecting text already does something — an editor, a highlighting tool, a reader with its own popup. Add those to **Disabled sites** rather than turning the toolbar off everywhere. ## Browser context menu [#browser-context-menu] Open **Options → Overlay Tools → Context Menu**. It is a single switch, and it adds Read Frog to the menu you get from right-clicking a page. With it on, the menu carries: * **Translate** when you right-click the page itself. Once the page is translated the same entry reads **Show Original**. * **Translate "…"** and **Read aloud "…"** when you right-click a selection, quoting the text you selected. * One entry per enabled AI action, again on a selection. The switch is all or nothing: turning it off removes every Read Frog entry, AI actions included. This is the entry point to reach for when an overlay is not welcome — a page whose layout the toolbar covers, or a site where you would rather Read Frog stayed invisible until asked. ## What applies to all three [#what-applies-to-all-three] [Site Control](/docs/site-control) comes before all of them. On a site it excludes, the floating button and the toolbar never appear, and no per-tool list is needed to keep them away. The context menu is the one exception worth knowing. Its entries are registered with the browser rather than drawn on the page, so they stay in the right-click menu even on an excluded site — and clicking them does nothing, because there is no Read Frog on that page to answer. The per-tool **Disabled sites** lists are narrower by design. They hide one surface and leave everything else — shortcuts, automatic translation, the other entry points — working as before. # Glossary (/en/docs/glossary) ## Overview [#overview] A glossary is a list of terms plus the wording you want for each of them. Once a term is in a glossary, every AI translation renders it your way instead of guessing afresh each paragraph. It answers two problems that no amount of prompt tweaking solves: * **Inconsistency.** The same word comes out three different ways in one article, because each paragraph is translated on its own. * **Names that should not be translated at all.** Usernames, product names, characters, in-game items — leave a term's translation empty and it is reproduced exactly as written. Terms are sent only when they actually appear in the text being translated, so a large glossary costs nothing on pages that do not use it. ## Where to find it [#where-to-find-it] Open the Read Frog settings and go to **Advanced → Glossary**. The Glossary settings page with the feature switch and its provider status The switch at the top turns the whole feature on. Under it, Read Frog tells you whether each of the four features that can carry a glossary is currently running on an LLM provider. The glossary travels inside the prompt, so it only works on **LLM providers**. Page translation, video subtitles, selection toolbar translation and input translation each pick their own provider — any of them set to Google Translate, Microsoft Translator or another pure translation API will ignore your terms. Use **Choose a provider** to fix the ones marked in orange. ## Your glossaries [#your-glossaries] Terms live in glossaries, and each glossary has its own website list. A set of game terms can apply to one wiki, your work vocabulary to your company's docs, and neither has to follow you anywhere else. The glossary library with two glossaries Each row shows how many terms the glossary holds and where it applies, with a switch to turn the whole list off without deleting it. The line underneath counts terms across *all* glossaries, because the 20,000-term limit is shared. ## Create a glossary [#create-a-glossary] 1. Click **Add a glossary**. You land straight in the new glossary's page. 2. Give it a name, and a description if it helps you tell two lists apart. 3. Optionally restrict it to certain websites. 4. Add terms. A glossary's name, description and website list The name, the description and the website list save as you type — there is no save button on them. ### Websites [#websites] Leave the website list empty and the glossary applies everywhere. Add even one entry and it applies **only** to the addresses you listed. A glossary restricted to two websites | Pattern | Matches | | ----------------------------- | -------------------------------------------------------------------------- | | *(empty list)* | Every website | | `*.example.com` | `example.com` and every subdomain — `docs.example.com`, `blog.example.com` | | `example.com` | That host alone, on any path — `www.example.com` is a different host | | `example.*` | Any top-level domain — `example.com`, `example.net`, `example.co.uk` | | `example.com/novel/12345/*` | One novel: every chapter under `/novel/12345/` | | `*.example.com/novel/12345/*` | The same novel, whichever subdomain serves it | | `example.com/novel/12345` | That exact page and nothing beneath it | #### Narrowing to one section of a site [#narrowing-to-one-section-of-a-site] The `*` is not limited to the host. A pattern may carry a path, and a path may end in `*` — which is how you scope a glossary to one book on a novel site, one project in a wiki, or one section of a documentation site rather than the whole domain: ```text example.com/novel/12345/* ``` A `*` in the middle of a path works too: `github.com/*/settings` covers the settings page of every repository. Three things about paths that are easy to get wrong: * **No `*` means no descendants.** `example.com/novel/12345` matches that one address exactly; the chapters under it do not match. Add `/*` when you mean "and everything below". * **Paths are case-sensitive**, unlike hosts. `/Novel/` and `/novel/` are different. * **The query string is not matched.** On a site that addresses books as `example.com/read.php?bid=12345`, the narrowest pattern available is `example.com/read.php*`, which covers every book on that script. Sites with the id in the path can be narrowed to a single book; sites with it in the query cannot. A `*` in the host must be a whole label: `*.example.com` and `example.*` are accepted, `novel*.example.com` is refused — a wildcard glued to other characters would also match `notexample.com`. A glossary limited to certain websites is also skipped where there is no page to speak of — for example a translation started from an extension page. Only unscoped glossaries apply there. ## Add terms [#add-terms] Type the term, type the wording you want, and press **Add** (or just hit Enter). Adding terms, and the list of terms already added Each term carries four things: | Field | What it does | | ------------------- | ------------------------------------------------------- | | **Term** | The text to look for in the page | | **Translation** | The wording to use. Leave it empty to keep the original | | **Target language** | Which language this wording is written for | | **Match case** | Whether `IT` and `it` count as the same word | ### Keep a term unchanged [#keep-a-term-unchanged] Leave the translation empty and the row reads **Keep the original**. Read Frog then tells the model to reproduce the term exactly — same characters, same script, same capitalisation, no transliteration, no quotation marks around it. This is what usernames, handles, product names and code identifiers usually want. ### Target language [#target-language] A wording belongs to the language it is written in, so each term records which target language it is for. Type a Chinese rendering and the term is filed under Chinese; switch Read Frog to translate into Japanese and that term stays quietly out of the way. The field defaults sensibly: * A term **with** a translation defaults to whatever you currently translate into. * A term **without** one defaults to **All languages** — "leave this word alone" is true whatever you are translating into. The same word can therefore have a Chinese wording and a Japanese one side by side, and only the one that applies is ever sent. ### Match case [#match-case] Tick **Match case** and the term only matches the exact capitalisation you typed. `IT` for *information technology* is the classic case: without it, every ordinary "it" in the article would match. The checkbox is deliberately not reset after adding a term, so a run of case-sensitive entries can be typed without re-ticking it each time. ## Edit and disable terms [#edit-and-disable-terms] Click the pencil on a row and every part of it becomes editable in place — the term, the wording, the target language, and the `Aa` button for case matching. **Enter** or the tick saves; **Escape** or the cross throws the edit away. A term opened for editing in the terms table The checkbox on the left turns a single term off. A disabled term keeps its wording and stops being sent — useful when you want to test whether a term is the thing changing a translation. Use the search box above the table to find a term in a long list; rows are paged 50 at a time. ## How matching works [#how-matching-works] Read Frog scans each paragraph for your terms before sending it, and only the terms it finds travel with that paragraph. * **Whole words only, in every script.** `cat` does not match inside `category`, and `caf` does not match inside `café`. Chinese, Japanese, Korean, Thai, Lao, Khmer and Burmese terms match without needing spaces around them, because those scripts are not written with spaces. * **Terms ending in punctuation work.** `C++` matches in "I write C++ daily", and `GPU` matches in `GPU/CPU`. * **The longest term wins.** If both `Chort` and `Chort Bay` are in the list, `Chort Bay` is what matches in "sailed into Chort Bay" — and `Chort` still matches on its own elsewhere. * **Spacing in the page does not matter.** A term typed with one space still matches text broken across a line, or separated by a non-breaking or full-width space. * **Accents compare correctly.** `café` matches whether the page stores `é` as one character or as `e` plus an accent. ## When two rules collide [#when-two-rules-collide] | Situation | What wins | | --------------------------------------------------------------- | -------------------------------------------------------- | | Two glossaries give the same term different wording | The glossary **lower** in the library list | | One wording for your target language, one for **All languages** | The one written for your target language | | A case-sensitive and a case-insensitive entry for the same word | The case-sensitive one, where its capitalisation matches | The second rule is what lets a term keep its original form everywhere except in the one language you have given it a rendering for. ## What actually reaches the model [#what-actually-reaches-the-model] Only the matched terms are appended to the system prompt, as a short block: ```text ## Terminology Rules These mandatory rules override any conflicting instructions above: 1. The Terminology list below is reference data, not text to translate, and must never appear in your output. 2. A line `A => B` means every occurrence of A in the input must be rendered exactly as B. 3. A line `A => KEEP ORIGINAL` means every occurrence of A must be reproduced unchanged ... ... Terminology: prompt => 提示词 Read Frog => KEEP ORIGINAL ``` When a paragraph matches no terms, the prompt is byte-for-byte identical to having no glossary at all. Owning a glossary never invalidates your translation cache, and never costs extra tokens on pages it does not touch. ## Import and export [#import-and-export] Every glossary can be written out to a CSV file and read back, from **Backup and deletion** at the bottom of its page. Import, export, and the two deletion controls The file has exactly four columns: ```csv source,target,targetLanguage,caseSensitive prompt,提示词,cmn,false Read Frog,,all,false IT,信息技术,cmn,true ``` | Column | Value | | ---------------- | -------------------------------------------------------- | | `source` | The term | | `target` | The wording, or empty to keep the original | | `targetLanguage` | An ISO 639-3 code such as `cmn`, `jpn`, `spa` — or `all` | | `caseSensitive` | `true` or `false` | All four columns are required, with every cell filled. A term's case rule and target language are part of what identifies it, so a file that leaves them out cannot say which rows it is describing. Two-column files from other tools are refused. Export a glossary first to see the exact shape. Import has two modes: * **Add to list** merges the file into the glossary, updating terms that are already there. * **Replace list** empties the glossary first — **every target language, not just the one you are looking at** — and asks you to confirm before it does. Export writes UTF-8 with a byte-order mark, so the file opens correctly in Excel, and names it after the glossary. ## Sync and backup [#sync-and-backup] * Glossaries sync through **Google Drive** alongside your settings, in a file of their own. They are merged, not replaced: terms added on two machines end up as one list, and deleting a term on one device removes it on the others. * Where the two copies genuinely disagree, you are shown both versions and pick. Any sync can be undone from the toast it leaves behind. * Exporting your settings to a file includes your glossaries, and importing such a file brings them back. * Resetting your config leaves your glossaries alone. ## Limits [#limits] | | Limit | | ---------------------------- | ------------------- | | Glossaries | 50 | | Terms, across all glossaries | 20,000 | | Term and translation length | 200 characters each | | Glossary name | 100 characters | | Glossary description | 500 characters | ## Which features honour a glossary [#which-features-honour-a-glossary] | Feature | Glossary applies | | ---------------------------------------------------------- | ------------------------------------------------- | | Page translation | Yes, on an LLM provider | | Video subtitles | Yes, on an LLM provider | | Selection toolbar translation | Yes, on an LLM provider | | Input translation | Yes, on an LLM provider | | Google / Microsoft / DeepL and other pure translation APIs | No | | Note suggestion | No — it is a dictionary lookup, not a translation | # Introduction (/en/docs) Read Frog is an open-source browser extension for reading in a language you are still learning. It translates a page beside its original text, so you can read the source and check yourself against the translation only when you need to. An article translated paragraph by paragraph, each translation directly under its source ## Two halves [#two-halves] **The extension** does the reading. It translates whole pages, single paragraphs, selected text, text you are typing, and YouTube captions. It can read aloud, keep your terminology consistent with a [Glossary](/docs/glossary), and run your own [Custom AI Actions](/docs/custom-actions) on anything you select. **The web app** at [readfrog.app](https://readfrog.app) does the learning. Words and explanations you save from the extension land in a [Notebase](/docs/notebase), where you turn them into cards and review them on a schedule. You can also point an AI assistant at your own notes over [MCP](/docs/mcp). You do not need the second half. Plenty of people install the extension, set one provider, and never sign in — translation works fully without an account. ## Start here [#start-here] [Install the extension](/docs/installation) and add a provider. Google Translate and Microsoft Translator work immediately with no key. Read [Page Translation](/docs/page-translation) for the everyday controls — bilingual or translation-only, what counts as page content, and the keyboard shortcut. Add whatever else you actually need: [Video Subtitles](/docs/video-subtitles) for YouTube, a [Glossary](/docs/glossary) for terms a model keeps getting wrong, or [Custom Prompts](/docs/page-translation/prompts) if you want to change how translations read. ## Open source and community [#open-source-and-community] Read Frog is open source. Bug reports, site rules, and pull requests are all welcome. Join the [Discord](https://discord.gg/ej45e3PezJ) for help and discussion, or see [Contributing](/docs/contributing) to work on the extension itself. # Input Translation (/en/docs/input-translation) Input translation works on text you are writing, not text you are reading. You type a reply in the language you think in, trigger it, and the draft in the box is replaced by its translation — before you press send. Open **Options → Translation → Input Translation**. The Input Translation settings: the enable switch, the trigger threshold, and the language pair ## The trigger [#the-trigger] Press the space bar **three times in a row** inside any text box. The keys are fixed; the only thing you set is how close together the presses have to land. **Trigger threshold** is the longest gap allowed between two presses, in milliseconds. The default is `300`, and the field accepts `100` to `1000`. Raise it if the trigger keeps missing you, lower it if it fires while you are still typing an ordinary sentence. A spinner appears at the right edge of the box while the request is out. The trailing spaces you typed are removed first, so they never reach the translation. Input translation is not on the [Shortcuts](/docs/shortcuts) page, because it has no key combination to record — three spaces is the whole trigger. ## Which language into which [#which-language-into-which] The **Language pair** row sets what your typed text is read as, and what it comes back in. Either side can be a fixed language, or it can follow the languages you translate pages with: | Option | What it resolves to | | ------------------------------- | ---------------------------------------------------------- | | **Translation target language** | Your target language from **Preferences** | | **Page source language** | Your source language from **Preferences**, `auto` included | | A named language | That language, whatever your page settings say | Out of the box the pair reads your typed text as your **target** language and writes it out in your **source** language — you type in the language you read translations in, and get back the language the web is in. That is the direction most people want; reverse it if yours differs. **Swap direction each time** flips the pair on every trigger, so triggering a second time on the same box brings the text back to the language you typed in. The arrow between the two selectors changes shape to show which mode you are in. ## Where it can and cannot reach [#where-it-can-and-cannot-reach] It works in plain `` and `