Skip to content

Conversation

@taiiiyang
Copy link
Collaborator

@taiiiyang taiiiyang commented Jan 27, 2026

Type of Changes

  • ✨ New feature (feat)

Description

Add custom prompts support for video subtitles translation:

  • Extract reusable PromptConfigurator component from personalized prompts settings
  • Add customPromptsConfig to video subtitles config schema
  • Add migration script v051-to-v052 for config schema update
  • Add i18n keys for video subtitles custom prompts (en, zh-CN, zh-TW, ja, ko, ru, tr, vi)
  • Add getSubtitlesTranslatePrompt utility to resolve custom/default prompts for subtitles

This allows users to customize translation prompts specifically for video subtitles, similar to the existing personalized prompts feature for web page translation.

Related Issue

N/A

How Has This Been Tested?

  • Added unit tests
  • Verified through manual testing

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

The PromptConfigurator component is now a reusable UI component that can be used for different prompt configuration scenarios (web page translation, video subtitles, etc.).


Summary by cubic

Adds custom prompts for video subtitles translation with a reusable PromptConfigurator and a subtitles-specific prompt resolver, letting users tailor subtitle translations separately from webpage prompts. Upgrades the config schema to v52 and auto-migrates existing configs.

  • New Features

    • Configure subtitle prompts in Options > Video Subtitles (add, edit, import, export).
    • New videoSubtitles.customPromptsConfig in schema and default config.
    • Subtitles prompt resolver (getSubtitlesTranslatePrompt) integrated into translation queues and executeTranslate.
  • Bug Fixes

    • Prevent double-toggle when selecting prompts in export mode.

Written for commit 13ab5a0. Summary will update on new commits.

…lation

- Extract reusable PromptConfigurator component from personalized prompts
- Add custom prompts config to video subtitles settings
- Add migration script v051-to-v052 for config schema
- Add i18n keys for video subtitles custom prompts

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@changeset-bot
Copy link

changeset-bot bot commented Jan 27, 2026

🦋 Changeset detected

Latest commit: 13ab5a0

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 Patch

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:XXL This PR changes 1000+ lines, ignoring generated files. label Jan 27, 2026
@github-actions github-actions bot added the feat label Jan 27, 2026
@dosubot
Copy link

dosubot bot commented Jan 27, 2026

Related Documentation

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

Custom Translation Prompts

The documentation describes the custom translation prompts feature for web page translation, including UI, configuration schema, import/export, and integration. The PR adds a parallel custom prompts feature for video subtitles translation, with a separate config schema, UI, and i18n keys. The documentation does not mention subtitle-specific custom prompts, nor does it explain the new options page section, config schema, or workflow for video subtitles custom prompts. To remain accurate and complete, the documentation should be updated to cover both translation and video subtitles custom prompts, their configuration, UI, and integration.

View Suggested Changes
@@ -1,40 +1,33 @@
 ## Options Page: Configuring Custom Prompts
-Custom prompts are managed on the options page via the `PersonalizedPrompts` section. This UI presents a card-based list of all available prompts, each with controls for selection, editing, and deletion. Users can add new prompts or edit existing ones using a form presented in a modal sheet. The form requires a prompt name and prompt text, both of which are validated to ensure they are not empty. The default prompt is visually distinguished and cannot be deleted or renamed.
+Custom prompts are managed on the options page via dedicated sections for both **Webpage Translation** and **Video Subtitles Translation**. Each section presents a card-based list of available prompts, with controls for selection, editing, and deletion. Users can add new prompts or edit existing ones using a form presented in a modal sheet. The form requires a prompt name and prompt text, both of which are validated to ensure they are not empty. The default prompt is visually distinguished and cannot be deleted or renamed.
 
-### Improved Interaction Design
-The prompt editing form now features two separate fields: **System Prompt** and **Prompt**. Both fields support quick-insert buttons for supported tokens (such as `{{input}}` and `{{targetLang}}`). Each button includes a tooltip explaining the token's meaning, making it easier for users to construct prompts correctly and understand how tokens are replaced during translation. These buttons are available when editing or creating a prompt, and are disabled for the default prompt. The tooltips are localized for all supported languages.
+### Webpage Translation Custom Prompts
+The `PersonalizedPrompts` section allows users to manage custom prompts for webpage translation. The UI features:
+- Card-based prompt list with selection, editing, and deletion controls.
+- Modal sheet for adding/editing prompts, with separate **System Prompt** and **Prompt** fields.
+- Quick-insert buttons for supported tokens (such as `{{input}}` and `{{targetLang}}`), with localized tooltips.
+- Export mode for selecting and exporting prompts to JSON.
+- Import functionality for merging prompts from a JSON file.
+- All user-facing text is localized.
 
-- **System Prompt:** Used to provide high-level translation instructions and context to the LLM. This field is especially important for batch translation and context-aware translation.
-- **Prompt:** Used for the main translation instruction and input text.
+### Video Subtitles Custom Prompts
+The `Custom Subtitle Prompts` section allows users to manage prompts specifically for video subtitles translation. This section is independent from webpage translation prompts and provides:
+- Card-based prompt list and modal editing UI, identical in interaction to the webpage translation prompts.
+- Separate configuration schema (`customPromptsConfig` under video subtitles config).
+- Export and import functionality for subtitle prompts, using the same JSON format.
+- All UI text and tooltips are localized, with dedicated i18n keys for subtitle prompts.
 
-Both fields are required for custom prompts. The default prompt provides built-in values for both fields, which are shown as read-only when editing the default prompt.
+#### Prompt Editing and Selection
+Both sections feature:
+- **System Prompt:** High-level instructions/context for the LLM.
+- **Prompt:** Main translation instruction and input text.
+- Quick-insert tokens for constructing prompts.
+- Required fields for custom prompts; default prompt is read-only.
+- Selection of the active prompt for translation/subtitles.
+- Export mode for batch exporting selected prompts (default prompt cannot be exported).
 
-#### Prompt Selection and Export Mode
-The prompt list UI now supports two distinct modes:
-
-- **Normal Mode:**
-  - Each prompt card displays its name, a preview of the prompt text, and action buttons for editing and (if not default) deleting the prompt.
-  - The currently selected prompt is visually indicated with a badge (e.g., "in use").
-  - Clicking a card selects it as the active prompt for translation. The default prompt is visually distinguished, shown as a view-only card, and cannot be deleted, renamed, or exported. Selection of the default prompt uses a UI-only sentinel ID, but in configuration, the default is represented by `promptId: null`.
-
-- **Export Mode:**
-  - Activated by clicking the "Export" button.
-  - Cards display checkboxes for selecting prompts to export, except for the default prompt, which cannot be selected or exported.
-  - Users can select multiple custom prompts and then click "Export Selected" to download them as a JSON file.
-  - A "Cancel" button exits export mode and clears the selection.
-  - Edit and delete actions are disabled in export mode.
-
-All user-facing text, including button labels, badges, and dialog messages, is localized using the i18n system, ensuring a consistent experience across supported languages. The UI structure and localization keys are updated to reflect the new export mode and selection logic. The default prompt is always available as a view-only option and is not persisted in user storage.
-
-## Popup Page: Selecting a Prompt for Translation
-The prompt selection dropdown is available both in the popup page and in the Translation Hub (accessible via the Tools sidebar or options page). The `TranslatePromptSelector` component provides a dropdown menu listing all configured prompts. Users can select which prompt to use for the current translation session. The selected prompt is stored in the translation configuration and is used for subsequent translation requests. The dropdown and its labels are fully localized. Only providers that support LLM-based translation expose this selector; for other providers, the selector is hidden.
-
-This ensures a consistent prompt selection experience whether translating from the popup or from the Translation Hub interface. All prompt management and selection logic is shared between both entry points.
-
-## Importing and Exporting Prompts
-Users can import prompts from a JSON file using the import button on the options page. The import process reads the file, parses the JSON, assigns new UUIDs to each imported prompt, and merges them into the current configuration. If an imported prompt does not include a `systemPrompt` field (for backward compatibility), it is backfilled with an empty string. Success and error notifications are displayed using toast messages. Exporting prompts works by entering export mode, selecting one or more prompts via checkboxes, and clicking the "Export Selected" button, which downloads a JSON file containing the selected prompts' names, system prompts, and texts. The import/export format is a simple array of objects with `name`, `systemPrompt`, and `prompt` fields.
-
-Example export format:
+#### Importing and Exporting Prompts
+Users can import prompts from a JSON file, which assigns new UUIDs and merges them into the current configuration. Exporting prompts downloads a JSON file containing selected prompts' names, system prompts, and texts. The format is:
 ```json
 [
   {
@@ -49,12 +42,10 @@
   }
 ]
 ```
-
-When importing, any missing `systemPrompt` field is set to an empty string for compatibility.
+Missing `systemPrompt` fields are set to empty strings for compatibility.
 
 ## Configuration Schema
-Custom prompts are stored in the translation configuration under `customPromptsConfig`. The schema is defined using [zod](https://github.com/colinhacks/zod) and includes:
-
+Custom prompts are stored in the configuration under `customPromptsConfig` for both translation and video subtitles. The schema is:
 ```ts
 export const translatePromptObjSchema = z.object({
   name: z.string(),
@@ -63,8 +54,8 @@
   prompt: z.string(),
 });
 export const customPromptsConfigSchema = z.object({
-  promptId: z.string().nullable(), // currently selected prompt ID (null means default)
-  patterns: z.array(translatePromptObjSchema), // list of all custom prompts
+  promptId: z.string().nullable(), // selected prompt ID (null means default)
+  patterns: z.array(translatePromptObjSchema), // list of custom prompts
 }).superRefine((data, ctx) => {
   if (data.promptId !== null) {
     const patternIds = data.patterns.map(p => p.id)
@@ -79,12 +70,12 @@
   }
 })
 ```
-Each prompt object contains an `id` (string, UUID), `name` (string), `systemPrompt` (string), and `prompt` (string). The configuration enforces that all fields are present and non-empty. The default prompt is not stored in the patterns array and is selected by setting `promptId` to `null`.
+Each prompt object contains an `id` (UUID), `name`, `systemPrompt`, and `prompt`. The default prompt is not stored in the patterns array and is selected by setting `promptId` to `null`.
 
-## Integration with the Translation Workflow
-When a translation is requested, the system retrieves the currently selected prompt by checking `customPromptsConfig.promptId`. If `promptId` is `null`, the default prompt (defined as a code constant) is used. Otherwise, the system looks up the custom prompt in `customPromptsConfig.patterns` by ID. If the prompt is not found, it falls back to the default prompt. Each prompt now consists of two fields: `systemPrompt` and `prompt`. Both may contain tokens such as `{{targetLang}}` and `{{input}}`, which are replaced at runtime with the actual target language and input text. This allows for highly customizable translation instructions sent to the LLM provider.
+## Integration with Translation and Subtitles Workflow
+When a translation or subtitle translation is requested, the system retrieves the currently selected prompt by checking `customPromptsConfig.promptId` in the relevant config (translation or video subtitles). If `promptId` is `null`, the default prompt is used. Otherwise, the system looks up the custom prompt in `customPromptsConfig.patterns` by ID. If not found, it falls back to the default prompt. Both `systemPrompt` and `prompt` fields may contain tokens such as `{{targetLang}}` and `{{input}}`, which are replaced at runtime.
 
-Example usage in code:
+Example usage:
 ```ts
 let systemPrompt: string
 let prompt: string
@@ -103,11 +94,10 @@
   .replaceAll('{{targetLang}}', targetLang)
   .replaceAll('{{input}}', inputText)
 ```
-
-For LLM-based providers, both the resolved `systemPrompt` and `prompt` are included in the translation request and in the hash for cache invalidation when either changes. The translation API now passes both fields to the LLM provider.
+For LLM-based providers, both fields are included in translation/subtitle requests and cache hashes.
 
 ## Localization Support
-All UI strings related to custom prompts are localized using the i18n system. The English localization file, for example, defines keys for titles, descriptions, button labels, dialog messages, and export mode actions under `options.translation.personalizedPrompts` and `exportPrompt`. This ensures that users can manage and select prompts in their preferred language, and that prompt instructions are clearly explained in the UI. The token tooltips and export mode controls are also localized for all supported languages.
+All UI strings related to custom prompts for both translation and video subtitles are localized using the i18n system. Each section uses dedicated localization keys for titles, descriptions, button labels, dialog messages, and export mode actions. Token tooltips and export controls are localized for all supported languages.
 
 Example localization keys:
 ```yaml
@@ -116,21 +106,11 @@
     personalizedPrompts:
       title: Personalized Prompts
       description: Customizing different types of Prompts allows you to adjust the Prompt type yourself during translation. A Prompt represents the text that the user sends to the LLM.
-      addPrompt: Add Prompt
-      import: Import
-      export: Export
-      current: in use
-      editPrompt:
-        promptCellInput:
-          input: Text content to translate
-          targetLang: Target language
-      exportPrompt:
-        exportSelected: Export Selected
-        cancel: Cancel
       # ...
-translatePrompt:
-  title: AI Translation Style
-  description: Select a Prompt to use during translation. Add or modify custom Prompts on the options page.
+  videoSubtitles:
+    customPrompts:
+      title: Custom Subtitle Prompts
+      description: Customize prompt templates for subtitle translation (separate from webpage translation prompts)
 ```
 
-This design enables a flexible, user-friendly, and internationalized workflow for managing and applying custom translation prompts in Read Frog, with an improved and intuitive export and selection experience.
+This design enables a flexible, user-friendly, and internationalized workflow for managing and applying custom prompts in Read Frog, for both translation and video subtitles, with an intuitive export and selection experience.

How did I do? Any feedback?  Join Discord

@claude
Copy link

claude bot commented Jan 27, 2026

PR Review: feat(subtitles): add custom prompts support for video subtitles translation

Overview

This PR adds custom prompt support for video subtitles translation by extracting a reusable PromptConfigurator component and creating a parallel prompt system for subtitles independent of webpage translation prompts.


【Taste Score】

🟢 Good taste

The refactoring follows good patterns: extracting shared UI into a reusable component, using composition over inheritance via context/atoms pattern, and maintaining clear separation of concerns.


【Key Insights】

Data structure: Clean extraction of customPromptsConfig schema reuse. The atoms factory pattern (createPromptAtoms) elegantly handles the difference between translate.customPromptsConfig and videoSubtitles.customPromptsConfig.

Complexity: Significant code reduction (~400 lines removed from personalized-prompt/index.tsx) while adding functionality. DRY principle well applied.

Risk points: See potential issues below.


Detailed Review

✅ Positives

  1. Excellent component extraction: The PromptConfigurator component uses React Context + Jotai atoms cleanly, allowing the same UI to work with different config paths.

  2. Migration script is correct: v051-to-v052.ts properly adds the new field with sensible defaults.

  3. Test coverage: The v052 example file contains both test series with the new customPromptsConfig field properly added to videoSubtitles.

  4. i18n coverage: All 8 locale files updated with appropriate translations.

  5. Proper type reuse: Using customPromptsConfigSchema from translate config for subtitles maintains consistency.


⚠️ Potential Issues

1. Duplicated prompt resolution logic (Code smell)

src/utils/prompts/subtitles.ts is nearly identical to src/utils/prompts/translate.ts. The only difference is which config path to read from:

  • config.translate.customPromptsConfig vs
  • config.videoSubtitles.customPromptsConfig

Suggestion: Consider extracting a shared resolvePrompt(customPromptsConfig, targetLang, input, options) function that both can use. This would make the code more maintainable and reduce future drift between the two implementations.

2. Missing edge case in migration (Minor)

The migration script doesn't handle the case where videoSubtitles itself might be undefined (though this would be unusual given the schema):

// Current:
videoSubtitles: {
  ...oldConfig.videoSubtitles,
  customPromptsConfig: { promptId: null, patterns: [] },
}

// Safer:
videoSubtitles: {
  ...(oldConfig.videoSubtitles ?? {}),
  customPromptsConfig: { promptId: null, patterns: [] },
}

This is minor since previous migrations should have already created videoSubtitles, but defensive coding never hurts.

3. File rename breaks backward compatibility of exported prompts (Potential UX issue)

The export filename changed from Read Frog: translate_prompts.json to Read Frog_prompts.json (src/components/ui/prompt-configurator/utils/prompt-file.ts).

Users who have existing exported files with the old name won't be affected on import, but this is a subtle breaking change in exported file naming.

4. Activity component usage (Question)

I see Activity being used from react directly (line 422 in prompt-grid.tsx):

import { Activity, useId } from 'react'

Is Activity a custom component in this codebase, or is this a React 19 experimental feature? If it's custom, it should be imported from the correct location. If it's React 19 experimental, ensure the project supports it.

5. Missing unit test for getSubtitlesTranslatePrompt

While migration tests exist, there's no dedicated unit test for the new getSubtitlesTranslatePrompt function to verify:

  • Default prompt fallback behavior
  • Custom prompt selection
  • Token replacement
  • Batch mode behavior

🔒 Security

No security concerns identified. The code handles user-provided prompt templates safely through the existing sanitization patterns.


📊 Performance

No performance concerns. The prompt resolver is async and fetches config once per call, consistent with existing patterns.


Summary

Aspect Rating
Code Quality ✅ Good - Clean extraction and reuse
Architecture ✅ Good - Follows existing patterns
Test Coverage ⚠️ Adequate - Migration tested, but utility function lacks unit tests
Documentation ✅ Good - i18n and PR description complete
Backward Compat ✅ Good - Migration handles upgrade path

Recommendation: Approve with minor suggestions. The duplication between translate.ts and subtitles.ts is acceptable for now but worth tracking for future consolidation.

Copy link
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.

2 issues found across 33 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/components/ui/prompt-configurator/prompt-grid.tsx">

<violation number="1" location="src/components/ui/prompt-configurator/prompt-grid.tsx:86">
P2: Clicking the checkbox in export mode will also trigger the CardHeader onClick, so the selection is toggled twice and ends up unchanged. Prevent the parent click when the checkbox is the target.</violation>
</file>

<file name="src/components/ui/prompt-configurator/import-prompts.tsx">

<violation number="1" location="src/components/ui/prompt-configurator/import-prompts.tsx:27">
P2: Use the functional setter to merge against the latest config; the current code can overwrite newer changes after the async import completes.</violation>
</file>

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

Stop click event propagation on checkbox to prevent CardHeader's onClick
from triggering a second toggle.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@claude
Copy link

claude bot commented Jan 27, 2026

PR Review: feat(subtitles): add custom prompts support for video subtitles translation

Overall Assessment

This is a well-structured PR that extracts a reusable PromptConfigurator component and adds custom prompts support for video subtitles. The approach follows good software design principles by promoting code reuse through composition.


Code Quality & Best Practices

Strengths:

  • Good extraction of reusable PromptConfigurator component using React Context + Jotai atoms pattern
  • The createPromptAtoms factory function (src/components/ui/prompt-configurator/create-atoms.ts) is a clean abstraction that enables type-safe reuse across different config sections
  • Consistent use of existing patterns (migration scripts, i18n, schema updates)
  • useId() for generating unique IDs in import-prompts.tsx and prompt-grid.tsx - proper React 18+ pattern

Suggestions:

  1. Code Duplication in Prompt Resolvers: getSubtitlesTranslatePrompt and getTranslatePrompt are nearly identical (lines 1-54 in both files). Consider extracting a shared createPromptResolver(configPath) factory to reduce duplication and ensure consistency.

  2. Unnecessary async on handleCardClick (prompt-grid.tsx:49): The function is marked async but contains no await calls. This causes React to create an implicit Promise that isn't handled.


Potential Bugs / Issues

  1. Bug Fix in Original Code - The PR correctly adds onClick={e => e.stopPropagation()} to the Checkbox (prompt-grid.tsx:95) which prevents double-toggle when clicking the checkbox in export mode. This fixes a real issue that existed in the original code where the card click handler would also trigger.

  2. Migration Script Edge Case (v051-to-v052.ts:11-18): The migration assumes oldConfig.videoSubtitles exists. If a user has a corrupted config where videoSubtitles is undefined, this would create { customPromptsConfig: {...}, undefined: spread }. Consider adding a defensive check:

    videoSubtitles: {
      ...(oldConfig.videoSubtitles ?? {}),
      customPromptsConfig: { promptId: null, patterns: [] },
    },
  3. Potential Stale Config Issue (subtitles.ts:11): The getSubtitlesTranslatePrompt function calls getLocalConfig() on every invocation during translation. This should be fine for correctness but may cause unnecessary storage reads. This matches existing behavior in translate.ts so it's consistent.


Performance Considerations

  • No Major Concerns: The component extraction doesn't introduce new performance issues
  • Atom Creation: The createPromptAtoms creates new atom instances per call, so it's important these are called at module level (as done in the PR) rather than inside components

Security Concerns

  • No Security Issues Identified: The PR doesn't introduce new attack vectors. Prompt templates are user-configured and stored locally, which is the existing pattern.

Test Coverage

Current State:

  • Migration tests exist via the automated all-migrations.test.ts which tests all version migrations
  • v052 example configs have been added with proper test data
  • The PR states unit tests were added and manual testing was done

Recommendations:

  1. Consider adding unit tests for getSubtitlesTranslatePrompt to verify:
    • Default prompt fallback when promptId is null
    • Custom prompt resolution when promptId matches a pattern
    • Batch mode appending behavior
    • Token replacement correctness

Summary

Aspect Rating
Code Quality ✅ Good
Architecture ✅ Clean extraction, follows DRY
Migration ✅ Properly versioned
i18n ✅ All 8 locales updated
Test Coverage ⚠️ Migration tests present; could add unit tests for prompt resolver

Verdict: This PR is ready to merge with minor suggestions above. The refactoring to a reusable PromptConfigurator is well-executed and will make future prompt customization features easier to implement.

@claude
Copy link

claude bot commented Jan 28, 2026

Code Review: feat(subtitles): add custom prompts support for video subtitles translation

Overall Assessment

🟢 Good taste - This is a well-structured refactoring that extracts reusable components while adding new functionality. The approach follows SOLID principles, particularly SRP and DIP.

👍 Strengths

  1. Excellent Component Extraction: The PromptConfigurator component is cleanly abstracted with proper dependency injection via atoms context. This enables reuse for both webpage translation and video subtitles.

  2. Clean Atom Architecture: The createPromptAtoms factory function (create-atoms.ts:15-28) elegantly creates derived atoms from parent config atoms, maintaining proper state management boundaries.

  3. Proper Migration Script: The v051-to-v052 migration correctly adds customPromptsConfig with sensible defaults ({ promptId: null, patterns: [] }).

  4. Complete i18n Coverage: All 8 locale files updated with appropriate translations.

  5. Bug Fix Included: The Checkbox in prompt-grid.tsx:511-519 now uses onClick={e => e.stopPropagation()} preventing double-toggle - a subtle but important fix.

⚠️ Issues to Address

1. Code Duplication Between Prompt Resolvers

src/utils/prompts/subtitles.ts duplicates nearly all logic from src/utils/prompts/translate.ts. Consider extracting a shared helper:

// utils/prompts/shared.ts
export function createPromptResolver(
  getConfig: () => CustomPromptsConfig
): PromptResolver {
  return async (targetLang, input, options) => {
    const { patterns, promptId } = getConfig()
    // ... shared logic
  }
}

This would eliminate ~40 lines of duplicated code and ensure both resolvers stay in sync.

2. Missing Test Coverage for getSubtitlesTranslatePrompt

The new src/utils/prompts/subtitles.ts has no unit tests. Given that:

  • getTranslatePrompt appears to also lack dedicated tests
  • This is a critical path for translation quality

I'd recommend adding tests covering:

  • Default prompt resolution
  • Custom prompt selection by ID
  • Fallback when promptId not found
  • Token replacement in batch mode

3. Hardcoded Label ID Prefix

In prompt-grid.tsx:422:

import { Activity, useId } from 'react'

This is good use of useId(), but note the import from react includes Activity which appears to be a custom component, not a React API. Verify this import is correct.

4. Context Provider Naming

<PromptConfiguratorContext value={atoms}>

Using value prop directly on Context suggests this is using React 19's new Context API. Ensure compatibility with your React version (documented as React 19, so this is fine - just noting it).

💡 Suggestions

  1. Export Types from Index: Consider re-exporting the PromptResolver type from a central location since it's now part of the public API for aiTranslate.

  2. Consistent File Naming:

    • export-prompts.tsx vs original export-prompt.tsx
    • import-prompts.tsx vs original import-prompt.tsx

    The plural form is more accurate, so this is an improvement, but verify no external references break.

  3. Type Safety in Migration: The migration script uses any type. While pragmatic for migrations, consider at least a minimal type guard:

    if (!oldConfig.videoSubtitles) {
      throw new Error('Invalid config: missing videoSubtitles')
    }

🔒 Security

No security concerns identified. The prompt configuration is properly stored in extension storage and doesn't introduce any injection vectors.

⚡ Performance

No performance concerns. The atom derivation pattern is efficient, and the prompt resolution is only called when needed during translation.

✅ Verdict

Approve with minor suggestions. The core architecture is sound, code quality is high, and the feature is well-implemented. The main improvement opportunity is reducing code duplication in prompt resolvers.


Reviewed by Claude Code

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

Labels

feat size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants