feat: right click selection translation#1171
Conversation
๐ฆ Changeset detectedLatest commit: 18ef68f The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Documentation Updates 1 document(s) were updated by changes in this PR: Internationalization and LocalizationView Changes@@ -2,9 +2,9 @@
The project supports internationalization (i18n) and localization (l10n) for both the browser extension and website, enabling a scalable, maintainable multi-language UI.
## Localized UI Elements and Content
-All UI elements, configuration options, provider descriptions, provider groupings, sidebar group labels, translation mode selectors, error recovery interfaces, and blog content are localized using structured locale files. The browser extension uses YAML files (e.g., `en.yml`), while the website uses JSON files (e.g., `en.json`, `zh.json`).
-
-Translations are organized hierarchically by UI section, such as popup dialogs, options pages, side panels, provider descriptions, sidebar navigation, error recovery, and blog pages. For example, the extension's locale files include keys for popup labels (`autoLang`, `sourceLang`, `targetLang`), configuration options (`options.apiProviders.title`, `options.general.title`), translation mode selector labels (`options.translation.translationMode.title`, `options.translation.translationMode.description`, and `options.translation.translationMode.mode.<mode>` for each mode), sidebar group labels (`options.sidebar.settings`, `options.sidebar.product`), command palette UI (`options.commandPalette.placeholder`, `options.commandPalette.noResults`), error recovery UI (`errorRecovery.title`, `errorRecovery.description`), and provider descriptions under `options.apiProviders.description` for each supported provider.
+All UI elements, configuration options, provider descriptions, provider groupings, sidebar group labels, translation mode selectors, error recovery interfaces, context menu items, and blog content are localized using structured locale files. The browser extension uses YAML files (e.g., `en.yml`), while the website uses JSON files (e.g., `en.json`, `zh.json`).
+
+Translations are organized hierarchically by UI section, such as popup dialogs, options pages, side panels, provider descriptions, sidebar navigation, error recovery, context menus, and blog pages. For example, the extension's locale files include keys for popup labels (`autoLang`, `sourceLang`, `targetLang`), configuration options (`options.apiProviders.title`, `options.general.title`), translation mode selector labels (`options.translation.translationMode.title`, `options.translation.translationMode.description`, and `options.translation.translationMode.mode.<mode>` for each mode), sidebar group labels (`options.sidebar.settings`, `options.sidebar.product`), command palette UI (`options.commandPalette.placeholder`, `options.commandPalette.noResults`), error recovery UI (`errorRecovery.title`, `errorRecovery.description`), context menu items (`contextMenu.translate`, `contextMenu.translateSelection`), and provider descriptions under `options.apiProviders.description` for each supported provider.
#### Model Selector UI Keys
The model selector UI uses several i18n keys under `options.apiProviders.form.models`, including:
@@ -978,6 +978,44 @@
- **PR #1127**: Added localized provider descriptions for three new AI providers (alibaba, moonshotai, huggingface) across all 8 supported languages
- **PR #1126**: Added selection toolbar opacity configuration with 2 new keys under `options.floatingButtonAndToolbar.selectionToolbar.opacity` to control transparency of the toolbar and popovers
- **PR #1152**: Added provider options recommendation keys with 5 new keys under `options.apiProviders.form.providerOptionsRecommendation*` to support manual preview and application of recommended provider options
+ - **PR #1171**: Added context menu selection translation and custom action support with 1 new key (`contextMenu.translateSelection`) and updated context menu configuration description
+
+### Context Menu Localization
+The browser context menu (right-click menu) supports page translation, selection translation, and custom AI actions. Context menu entries are localized under the `contextMenu` namespace:
+
+**Context Menu Keys:**
+- **`contextMenu.translate`**: Label for page translation ("Translate")
+- **`contextMenu.translateSelection`**: Label for selection translation with selected text placeholder ("Translate \"%s\"")
+
+When the context menu translate option is enabled in settings (`options.general.contextMenu.translate.title`), users will see different context menu entries depending on the context:
+- **"Translate"** option when right-clicking on the page (for full page translation)
+- **"Translate \"%s\""** option when right-clicking on selected text (for selection translation via the selection toolbar)
+- **Custom action entries** when right-clicking on selected text (if custom actions are configured and enabled)
+
+Custom AI actions appear as individual entries in the browser's context menu when text is selected. These entries use the user-defined action names and trigger the same popover UI and execution flow as the selection toolbar. The context menu integration allows users to access both built-in translation and custom AI actions directly from the right-click menu.
+
+**Context Menu Configuration:**
+The context menu translate feature is configured under `options.general.contextMenu.translate`:
+- **`title`**: "Enable Context Menu Translate"
+- **`description`**: "Add translate options to the browser right-click menu for quick page and selection translation"
+
+**Example:**
+
+```yaml
+contextMenu:
+ translate: Translate
+ translateSelection: Translate "%s"
+
+options:
+ general:
+ contextMenu:
+ title: Context Menu
+ translate:
+ title: Enable Context Menu Translate
+ description: Add translate options to the browser right-click menu for quick page and selection translation
+```
+
+The context menu entries are dynamically updated when configuration changes. Selection translation and custom actions share the same selection snapshot and recovery mechanism, allowing seamless interaction between the context menu and selection toolbar.
### Example: Adding a New Provider Group
**English:** |
There was a problem hiding this comment.
1 issue found across 29 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid โ if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/components/ui/selection-popover/index.tsx">
<violation number="1" location="src/components/ui/selection-popover/index.tsx:117">
P2: `setAnchor` is callback-based now, but `contextValue` memo deps omit it, which can freeze a stale `setAnchor` in context.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| onOpenChange?.(nextOpen) | ||
| }, [onOpenChange, open, openProp]) | ||
|
|
||
| const setAnchor = React.useCallback((value: SelectionPopoverPosition | null) => { |
There was a problem hiding this comment.
P2: setAnchor is callback-based now, but contextValue memo deps omit it, which can freeze a stale setAnchor in context.
Prompt for AI agents
Check if this issue is valid โ if so, understand the root cause and fix it. At src/components/ui/selection-popover/index.tsx, line 117:
<comment>`setAnchor` is callback-based now, but `contextValue` memo deps omit it, which can freeze a stale `setAnchor` in context.</comment>
<file context>
@@ -109,6 +114,14 @@ function SelectionPopoverRoot({
onOpenChange?.(nextOpen)
}, [onOpenChange, open, openProp])
+ const setAnchor = React.useCallback((value: SelectionPopoverPosition | null) => {
+ if (anchorProp === undefined) {
+ setUncontrolledAnchor(value)
</file context>
There was a problem hiding this comment.
๐ก Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 18ef68fafd
โน๏ธ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with ๐.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| return onMessage("openSelectionTranslationFromContextMenu", () => { | ||
| openFromContextMenu() |
There was a problem hiding this comment.
Consume context-menu payload when opening translation
The message handler drops message.data.selectionText and always calls openFromContextMenu() with no payload, so translation depends entirely on selectionSession cached from toolbar state. If the current selection was created without a mouseup-driven session refresh (for example keyboard selection, or selection cleared before click), the request resolves to stale/null session and either translates the wrong text or shows missingSelection even though the background click already provided the selected text. Please use the message payload as a fallback source when building the context-menu request.
Useful? React with ๐ย / ๐.
| return onMessage("openSelectionCustomActionFromContextMenu", (message) => { | ||
| openContextMenuCustomAction(message.data.actionId) |
There was a problem hiding this comment.
Consume context-menu payload when opening custom action
The custom-action handler only forwards actionId and ignores message.data.selectionText, which means execution still relies on selectionSession being previously captured by toolbar logic. In contexts where that session is absent or stale (e.g., non-mouse selection paths), users can get a false missingSelection error or run the action on old text even though the context-menu click delivered the selected text. The open path should incorporate the payload text as a recovery/fallback input.
Useful? React with ๐ย / ๐.
Type of Changes
Description
Related Issue
Closes #292
How Has This Been Tested?
Test Commands
SKIP_FREE_API=true pnpm test -- src/entrypoints/background/__tests__/context-menu.test.ts src/entrypoints/background/__tests__/analytics.test.ts src/entrypoints/selection.content/selection-toolbar/__tests__/request-rerun.test.tsx src/utils/__tests__/analytics.test.ts pnpm type-checkScreenshots
Checklist
Additional Information
docs/pr-right-click-context-menu.mdfile is intentionally left uncommitted for copy/pasteSummary by cubic
Adds rightโclick selection translation and inline custom AI actions to the browser context menu, while keeping the existing page translation flow. This lets users translate selected text or run custom actions directly from the context menu with consistent popover behavior.
New Features
Refactors
action_idandaction_name, and tracks thecontext_menusurface for these flows.openSelectionTranslationFromContextMenuandopenSelectionCustomActionFromContextMenu; exports menu IDs and handles selection-specific clicks in background.Written for commit 18ef68f. Summary will update on new commits.