Skip to content

feat(translation-hub): persist selected translation providers in tran…#1186

Open
zhanxiaoge wants to merge 2 commits intomengxi-ream:mainfrom
zhanxiaoge:feat/add-translation-hub-config
Open

feat(translation-hub): persist selected translation providers in tran…#1186
zhanxiaoge wants to merge 2 commits intomengxi-ream:mainfrom
zhanxiaoge:feat/add-translation-hub-config

Conversation

@zhanxiaoge
Copy link
Copy Markdown

@zhanxiaoge zhanxiaoge commented Mar 21, 2026

…slation center dropdown

Type of Changes

  • ✨ New feature (feat)
  • 🐛 Bug fix (fix)
  • 📝 Documentation change (docs)
  • 💄 UI/style change (style)
  • ♻️ Code refactoring (refactor)
  • ⚡ Performance improvement (perf)
  • ✅ Test related (test)
  • 🔧 Build or dependencies update (build)
  • 🔄 CI/CD related (ci)
  • 🌐 Internationalization (i18n)
  • 🧠 AI model related (ai)
  • 🔄 Revert a previous commit (revert)
  • 📦 Other changes that do not modify src or test files (chore)

Description

In Vivaldi, you can set the translation center page as a panel tool. I added this function because I hope to retain my previous settings every time I open the panel.

Related Issue

Closes #

How Has This Been Tested?

  • Added unit tests
  • Verified through manual testing

Screenshots

image

Checklist

  • I have tested these changes locally
  • I have updated the documentation accordingly if necessary
  • My code follows the code style of this project
  • My changes do not break existing functionality
  • If my code was generated by AI, I have proofread and improved it as necessary.

Additional Information


Summary by cubic

Persists selected translation providers in the translation hub dropdown across sessions. Adds translate.translationHubConfig.selectedIds and migrates configs to v67.

  • New Features

    • selectedProviderIdsAtom now reads/writes translate.translationHubConfig.selectedIds.
    • Default is empty; users must choose providers. Only enabled IDs in selectedIds are applied.
  • Migration

    • v066→v067 adds translationHubConfig.selectedIds: [] to existing configs; no action needed.

Written for commit a21c2da. Summary will update on new commits.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 21, 2026

🦋 Changeset detected

Latest commit: a21c2da

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@read-frog/extension Minor

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

@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Mar 21, 2026
@github-actions github-actions bot added the feat label Mar 21, 2026
@dosubot dosubot bot added the app: browser extension Related to browser extension label Mar 21, 2026
@dosubot
Copy link
Copy Markdown

dosubot bot commented Mar 21, 2026

Related Documentation

2 document(s) may need updating based on files changed in this PR:

Read Frog - Open Source Immersive Translate

API Providers Configuration
View Suggested Changes
@@ -15,6 +15,11 @@
 - `temperature`: (Optional, LLM translation providers only) Number controlling randomness/creativity in AI responses. Lower values (e.g., 0) are more deterministic, higher values are more creative. Leave empty to use provider default.
 - `providerOptions`: (Optional, LLM translation providers only) Object containing provider-specific advanced options (e.g., for enabling special API features). This is a JSON object passed directly to the provider; see provider documentation for supported keys.
 - `connectionOptions`: (Optional) Object containing provider-specific connection settings (e.g., AWS region for Bedrock)
+
+### Translation Hub Configuration
+The translation hub (translation center) configuration is stored in `translate.translationHubConfig` and includes:
+
+- `selectedIds`: Array of provider IDs that are selected/active in the translation hub dropdown. These selections are persisted across sessions, allowing users to maintain their preferred set of translation providers. When a user selects or deselects providers in the translation hub UI, those changes are automatically saved to this array. The default value is an empty array, meaning users need to explicitly select providers on first use, but those selections will persist in subsequent sessions.
 
 Example configuration schema:
 ```ts
@@ -449,6 +454,11 @@
 - The vocabulary insight feature has been fully removed and replaced by Custom AI Action's Dictionary feature
 - Converts `translate.page.shortcut` from string[] to portable hotkey string
 
+**v066 to v067 migration:**
+- Adds `translationHubConfig` to `translate` configuration
+- Adds `selectedIds` field to `translationHubConfig` (default: empty array `[]`)
+- Provider selections in the translation hub are now persisted across sessions
+
 ---
 
 ## Custom AI Actions

[Accept] [Decline]

Configuration Schema and Migration
View Suggested Changes
@@ -33,7 +33,7 @@
 
 **Note:** The schema version and last modified time are tracked in the configuration's metadata (`meta`), not as fields inside the config object itself. This improves separation of user settings and system metadata, and is reflected in all import/export and sync operations.
 
-**Current schema version:** The latest `CONFIG_SCHEMA_VERSION` is **66**.
+**Current schema version:** The latest `CONFIG_SCHEMA_VERSION` is **67**.
 
 #### Configuration Initialization Optimization
 The `initializeConfig()` function optimizes storage operations by tracking changes during initialization:
@@ -909,6 +909,46 @@
 
 This migration enables users to adjust selection toolbar visibility based on their preferences, making the toolbar less intrusive when needed while maintaining full functionality.
 
+#### Example: v66 to v67 Migration (Translation Hub Selected Providers)
+The migration from v66 to v67 adds a new `translationHubConfig` object to the `translate` configuration. This configuration persists the user's selected translation providers in the translation center (translation hub) dropdown.
+
+**Key changes:**
+- Adds `translationHubConfig` object to `translate` configuration
+- The object contains a `selectedIds` array that stores the IDs of selected translation providers
+- Default value is an empty array `[]`
+- This enables the translation center panel to remember which providers the user has selected across sessions
+
+The migration script adds this field with an empty array as the default:
+
+```ts
+// migration-scripts/v066-to-v067.ts
+export function migrate(oldConfig: any): any {
+  const translate = oldConfig.translate
+
+  if (!translate) {
+    return oldConfig
+  }
+
+  return {
+    ...oldConfig,
+    translate: {
+      ...translate,
+      translationHubConfig: {
+        selectedIds: [],
+      },
+    },
+  }
+}
+```
+
+**Implementation details:**
+- The `translationHubConfig.selectedIds` array stores provider IDs that correspond to entries in `providersConfig`
+- When the translation hub is opened (e.g., as a Vivaldi panel), previously selected providers are automatically restored
+- Provider selection state is synchronized across all translation hub instances
+- Empty array indicates no providers have been explicitly selected (defaults to showing all enabled providers)
+
+This migration improves the user experience for users who frequently use the translation center, especially when it's set as a browser panel, by preserving their provider selection preferences.
+
 #### Example: v65 to v66 Migration (Page Translation Shortcut Format and Vocabulary Insight Removal)
 The migration from v65 to v66 performs two changes:
 1. Converts the `translate.page.shortcut` field from a string array format to a portable hotkey string format
@@ -1614,6 +1654,28 @@
 }
 ```
 
+#### v67 Example (Translation Hub Selected Providers)
+```ts
+export const testSeries = {
+  'complex-config-from-v020': {
+    description: 'Adds translationHubConfig to translate configuration',
+    config: {
+      // ... other config fields
+      translate: {
+        providerId: 'openai-default',
+        mode: 'translationOnly',
+        // ...
+        translationHubConfig: { // New field added in v067
+          selectedIds: [],
+        },
+        // ...
+      },
+      // ...
+    },
+  },
+}
+```
+
 #### v66 Example (Page Translation Shortcut Format and Vocabulary Insight Removal)
 ```ts
 export const testSeries = {

[Accept] [Decline]

Note: You must be authenticated to accept/decline updates.

How did I do? Any feedback?  Join Discord

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8014959099

ℹ️ 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".

Comment on lines +20 to +21
translationHubConfig: {
selectedIds: [],
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Seed the v067 migration from enabled translate providers

When upgrading an existing v66 profile, this migration hard-codes selectedIds: [], which wipes out the translation hub’s effective selection. Before this change the hub selected every enabled translate provider by default via selectedProviderIdsAtom, so the first open after upgrade now lands on the “No Translation Services Selected” empty state and Translate produces no cards until the user manually rebuilds that list. If the goal is to persist the previous dropdown state, the migration needs to derive the initial selectedIds from the currently enabled translate providers instead of clearing it.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-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.

1 issue found across 6 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/utils/config/migration-scripts/v066-to-v067.ts">

<violation number="1" location="src/utils/config/migration-scripts/v066-to-v067.ts:21">
P1: The migration seeds `selectedIds` with an empty array, but the atom's read function now filters enabled providers against this list (`translateEnabledProviders.filter(id => selectedIds.includes(id))`). Since the previous behavior selected all enabled translate providers by default, upgrading users will land on an empty selection with no translation cards. Populate `selectedIds` from the existing enabled translate providers to preserve the pre-upgrade behavior.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

translate: {
...translate,
translationHubConfig: {
selectedIds: [],
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 21, 2026

Choose a reason for hiding this comment

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

P1: The migration seeds selectedIds with an empty array, but the atom's read function now filters enabled providers against this list (translateEnabledProviders.filter(id => selectedIds.includes(id))). Since the previous behavior selected all enabled translate providers by default, upgrading users will land on an empty selection with no translation cards. Populate selectedIds from the existing enabled translate providers to preserve the pre-upgrade behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/utils/config/migration-scripts/v066-to-v067.ts, line 21:

<comment>The migration seeds `selectedIds` with an empty array, but the atom's read function now filters enabled providers against this list (`translateEnabledProviders.filter(id => selectedIds.includes(id))`). Since the previous behavior selected all enabled translate providers by default, upgrading users will land on an empty selection with no translation cards. Populate `selectedIds` from the existing enabled translate providers to preserve the pre-upgrade behavior.</comment>

<file context>
@@ -0,0 +1,25 @@
+    translate: {
+      ...translate,
+      translationHubConfig: {
+        selectedIds: [],
+      },
+    },
</file context>
Fix with Cubic

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a21c2da213

ℹ️ 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".

Comment on lines 42 to 44
const override = get(selectedProviderIdsOverrideAtom)
if (override !== null)
return override
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Stop ignoring config changes after the first selection

Once setSelectedIds runs, selectedProviderIdsOverrideAtom stays non-null for the rest of the page lifetime, so this getter never re-applies filterEnabledProvidersConfig or re-reads the persisted translate.translationHubConfig.selectedIds. In the common Vivaldi-panel workflow where the hub stays mounted, disabling a provider or importing synced config from popup/options leaves the panel on stale ids; selectedProvidersAtom then resolves those ids straight from providersConfig, so a provider disabled elsewhere can still be shown and used until the page reloads.

Useful? React with 👍 / 👎.

Comment on lines 111 to +113
batchQueueConfig: batchQueueConfigSchema,
translationNodeStyle: translationNodeStyleConfigSchema,
translationHubConfig: translationHubConfigSchema,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep startup reads compatible with pre-v67 configs

Adding a required translationHubConfig here makes every stored v66 config fail configSchema.safeParse until migration has finished. getLocalConfig() does not migrate on read—it falls back to DEFAULT_CONFIG on validation failure (src/utils/config/storage.ts)—and both src/entrypoints/translation-hub/main.tsx and src/entrypoints/popup/main.tsx hydrate from that helper. On upgrade, if the user opens the panel/popup before the background ensureInitializedConfig() completes, those UIs boot with a reset config instead of the stored one.

Useful? React with 👍 / 👎.

@mengxi-ream mengxi-ream requested a review from taiiiyang March 23, 2026 22:24
@github-actions github-actions bot added the contrib-trust:moderate PR author trust score is 30-59. label Apr 2, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

Contributor trust score

14/100 — New contributor

This score estimates contributor familiarity with mengxi-ream/read-frog using public GitHub signals. It is advisory only and does not block merges automatically.

Outcome

Score breakdown

Dimension Score Signals
Repo familiarity 0/35 merged PRs, resolved PR history, reviews
Community standing 6/25 account age, followers, repo role
OSS influence 3/20 stars on owned non-fork repositories
PR track record 5/20 merge rate across resolved PRs in this repo

Signals used

  • Repo PR history: merged 0, open 1, closed-unmerged 0
  • Repo reviews: 0
  • Repo permission: read
  • Followers: 3
  • Account age: 118 months
  • Owned non-fork repos considered: max 1, total 2 (zhanxiaoge/usine (1), zhanxiaoge/dsbridge-cocos (1), zhanxiaoge/Adblock-Customize-List (0), zhanxiaoge/vite-vue-pinia-element (0), zhanxiaoge/postcss-unitlist (0), zhanxiaoge/html-webpack-externals (0))

Policy

  • Low-score review threshold: < 30
  • Auto-close: disabled in v1
  • Policy version: v1

Updated automatically when the PR changes or when a maintainer reruns the workflow.

@github-actions github-actions bot added contrib-trust:new PR author trust score is 0-29. needs-maintainer-review Contributor trust automation recommends maintainer review. and removed contrib-trust:moderate PR author trust score is 30-59. labels Apr 2, 2026
Copy link
Copy Markdown
Collaborator

@taiiiyang taiiiyang left a comment

Choose a reason for hiding this comment

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

Right direction, just a few small things to fix up.

  1. When a user first enters the interface, you need to determine whether the user's selectedIds are empty. If they are empty, you should refill selectedIds using the enabled providers from providersConfig.
  2. Additionally, when deleting a provider from providerConfigs, you must also remove the corresponding providerId from selectedIds.

Comment on lines +20 to +21
translationHubConfig: {
selectedIds: [],
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

During migration, you need to read the enable providers from the previous version's providersConfig, then fill in selectedIds to ensure users can see the default selected provider in the new version, avoiding the need to manually re-select after entering the page.

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

Labels

app: browser extension Related to browser extension contrib-trust:new PR author trust score is 0-29. feat needs-maintainer-review Contributor trust automation recommends maintainer review. size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants