-
-
Notifications
You must be signed in to change notification settings - Fork 212
feat(subtitles): add custom prompts support for video subtitles translation #923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…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 detectedLatest commit: 13ab5a0 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 |
|
Related Documentation 1 document(s) may need updating based on files changed in this PR: Custom Translation PromptsThe 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. |
PR Review: feat(subtitles): add custom prompts support for video subtitles translationOverviewThis PR adds custom prompt support for video subtitles translation by extracting a reusable 【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 Complexity: Significant code reduction (~400 lines removed from Risk points: See potential issues below. Detailed Review✅ Positives
|
| Aspect | Rating |
|---|---|
| Code Quality | ✅ Good - Clean extraction and reuse |
| Architecture | ✅ Good - Follows existing patterns |
| Test Coverage | |
| 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.
There was a problem hiding this 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]>
PR Review: feat(subtitles): add custom prompts support for video subtitles translationOverall AssessmentThis is a well-structured PR that extracts a reusable Code Quality & Best PracticesStrengths:
Suggestions:
Potential Bugs / Issues
Performance Considerations
Security Concerns
Test CoverageCurrent State:
Recommendations:
Summary
Verdict: This PR is ready to merge with minor suggestions above. The refactoring to a reusable |
Code Review: feat(subtitles): add custom prompts support for video subtitles translationOverall 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
|
Type of Changes
Description
Add custom prompts support for video subtitles translation:
PromptConfiguratorcomponent from personalized prompts settingscustomPromptsConfigto video subtitles config schemagetSubtitlesTranslatePromptutility to resolve custom/default prompts for subtitlesThis 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?
Checklist
Additional Information
The
PromptConfiguratorcomponent 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
Bug Fixes
Written for commit 13ab5a0. Summary will update on new commits.