Translated subtitles only lived in ~/.cache/qtpotato/translations, and mpv's sub-auto only looks in the video's folder, so reopening a video lost the translation. Now the translation is saved as <video>.vi.srt next to the video. mpv and other players pick it up, and QtPotato turns it on when the video opens.
If the folder is read-only or the video is a stream, the copy stays in the cache. QtPotato adds it as "Vietnamese (translated)" when the video opens.
Your own subtitles are never overwritten. QtPotato keeps a list of the files it wrote, with a hash of each (~/.local/share/qtpotato/translations.json). If <video>.vi.srt is someone else's file, or a QtPotato file you edited by hand, the translation goes to <video>.qtpotato.vi.srt instead. Glossary edits also leave edited files alone.
Translating again with another preset, model or other setting replaces QtPotato's own file. The cache still keeps one file per settings combination, so going back to earlier settings doesn't call the LLM again.
On open, the saved translation wins over mpv's own pick and the fallback languages. A subtitle in "Preferred subtitle languages" still wins over it, and with automatic subtitles off mpv's choice is kept.
Translate always starts from the original subtitle, even while the translation is the one on screen.
TranslationStore::savedTranslation() / Registry::find() answer "where is video X's translation" and "is X translated yet", which #9 needs.
Proof: new translationstoretest and an extended trackselectiontest, all 7 tests pass. I also ran the real app (offscreen, Union style, isolated XDG dirs, a fake local OpenAI server) on The King's Avatar episodes. Translating writes the sidecar, reopening selects it, and translating again hits the cache from the English source. A user .vi.srt is kept and .qtpotato.vi.srt is chosen. In a read-only folder the cache copy is loaded and selected.
Reopened from a read-only folder (cache copy added and selected), and next to a user's own .vi.srt (QtPotato's .qtpotato.vi.srt selected):
Follow-up: after you change the target language, older translations in other languages count as originals when they are the subtitle on screen.
Reviewed with sol-loop: 2 rounds with gpt-6.1-sol. Sol verdict: approved.
Created with Claude Opus 5.5 in Claude Code (T3 Code), reviewed by GPT-6.1 Sol.
Translated subtitles only lived in `~/.cache/qtpotato/translations`, and mpv's `sub-auto` only looks in the video's folder, so reopening a video lost the translation. Now the translation is saved as `<video>.vi.srt` next to the video. mpv and other players pick it up, and QtPotato turns it on when the video opens.
- If the folder is read-only or the video is a stream, the copy stays in the cache. QtPotato adds it as "Vietnamese (translated)" when the video opens.
- Your own subtitles are never overwritten. QtPotato keeps a list of the files it wrote, with a hash of each (`~/.local/share/qtpotato/translations.json`). If `<video>.vi.srt` is someone else's file, or a QtPotato file you edited by hand, the translation goes to `<video>.qtpotato.vi.srt` instead. Glossary edits also leave edited files alone.
- Translating again with another preset, model or other setting replaces QtPotato's own file. The cache still keeps one file per settings combination, so going back to earlier settings doesn't call the LLM again.
- On open, the saved translation wins over mpv's own pick and the fallback languages. A subtitle in "Preferred subtitle languages" still wins over it, and with automatic subtitles off mpv's choice is kept.
- Translate always starts from the original subtitle, even while the translation is the one on screen.
- `TranslationStore::savedTranslation()` / `Registry::find()` answer "where is video X's translation" and "is X translated yet", which #9 needs.
Proof: new `translationstoretest` and an extended `trackselectiontest`, all 7 tests pass. I also ran the real app (offscreen, Union style, isolated XDG dirs, a fake local OpenAI server) on The King's Avatar episodes. Translating writes the sidecar, reopening selects it, and translating again hits the cache from the English source. A user `.vi.srt` is kept and `.qtpotato.vi.srt` is chosen. In a read-only folder the cache copy is loaded and selected.
Reopened from a read-only folder (cache copy added and selected), and next to a user's own `.vi.srt` (QtPotato's `.qtpotato.vi.srt` selected):
 
Follow-up: after you change the target language, older translations in other languages count as originals when they are the subtitle on screen.
Closes #8
Reviewed with sol-loop: 2 rounds with gpt-6.1-sol. Sol verdict: approved.
Created with Claude Opus 5.5 in Claude Code (T3 Code), reviewed by GPT-6.1 Sol.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Translated subtitles only lived in
~/.cache/qtpotato/translations, and mpv'ssub-autoonly looks in the video's folder, so reopening a video lost the translation. Now the translation is saved as<video>.vi.srtnext to the video. mpv and other players pick it up, and QtPotato turns it on when the video opens.~/.local/share/qtpotato/translations.json). If<video>.vi.srtis someone else's file, or a QtPotato file you edited by hand, the translation goes to<video>.qtpotato.vi.srtinstead. Glossary edits also leave edited files alone.TranslationStore::savedTranslation()/Registry::find()answer "where is video X's translation" and "is X translated yet", which #9 needs.Proof: new
translationstoretestand an extendedtrackselectiontest, all 7 tests pass. I also ran the real app (offscreen, Union style, isolated XDG dirs, a fake local OpenAI server) on The King's Avatar episodes. Translating writes the sidecar, reopening selects it, and translating again hits the cache from the English source. A user.vi.srtis kept and.qtpotato.vi.srtis chosen. In a read-only folder the cache copy is loaded and selected.Reopened from a read-only folder (cache copy added and selected), and next to a user's own
.vi.srt(QtPotato's.qtpotato.vi.srtselected):Follow-up: after you change the target language, older translations in other languages count as originals when they are the subtitle on screen.
Closes #8
Reviewed with sol-loop: 2 rounds with gpt-6.1-sol. Sol verdict: approved.
Created with Claude Opus 5.5 in Claude Code (T3 Code), reviewed by GPT-6.1 Sol.