How to Translate an SRT File Without Breaking the Timing
Translate an SRT file and keep the timing: why general translators wreck timecodes, four methods that do not, and the one-line check that catches a broken file.
To translate an SRT file and keep the timing, use a tool that parses the subtitle format rather than one that treats the file as prose. A format-aware tool reads the block number, the timecode line and the text as three separate things, translates only the third, and writes the other two back exactly as they were.
Every broken translated subtitle file traces back to the same mistake: the whole file went into a general-purpose translator that had no reason to know which lines were load-bearing.
Why does translating an SRT break the timing?
An SRT block has four parts, and only one of them is language:
2
00:00:04,120 --> 00:00:06,480
The timings live on the line above.
A translator must never touch it.
The number identifies the cue. The timecode line, with its comma-separated milliseconds and its --> arrow, is the timing. The text is the subtitle. The blank line is the separator that tells a parser the block has ended.
A general translator sees one document containing all four. It has no reason to treat 00:00:04,120 --> 00:00:06,480 as syntax, so three things go wrong, usually together:
- Cues get merged. The blank line between blocks is whitespace to a prose translator, and if it does not survive the round trip, two cues become one paragraph. Everything after that point is now misaligned with the audio.
- Blocks get renumbered or reordered. Reflowing paragraphs shuffles the index numbers, and some parsers refuse the file outright while others silently renumber it and shift the cues.
- Timecodes get reformatted. A space added around the arrow, a comma turned into a period, a millisecond field padded differently — any of these is enough to make the line unparseable.
There is a fourth failure that has nothing to do with the translator. Encoding. A file with accented characters or a non-Latin script saved as Latin-1 or Windows-1254 instead of UTF-8 renders as mojibake in half the players that open it. Save every subtitle file as UTF-8 and this problem disappears permanently.
The tell is that a mangled file often still looks fine when you skim it. The text is in the right language, the timecodes are still there, and nothing screams. It fails when a player tries to parse it, or worse, it parses and plays two seconds off.
The four ways to translate an SRT
Fastest to most controlled:
- Subtitle Edit — free, open source, translation built in, runs locally.
- A format-aware online translator — upload the file, get one back.
- An LLM with a strict prompt — best terminology control, needs verification.
- A desktop app that treats translation as a layer — several languages from one timeline.
All four keep the timecodes intact if used correctly. They differ in cost, privacy and how many languages you are producing.
Method 1: Subtitle Edit
The free answer, and the one most people should start with.
Subtitle Edit is open source, runs on Windows, macOS and Linux, and has an Auto-Translate function that substitutes the text in memory and leaves the block structure alone by construction. It offers several engines — DeepL and Google if you have keys, LibreTranslate if you self-host, and local models through Ollama, llama.cpp or any OpenAI-compatible endpoint.
- Open the
.srtin Subtitle Edit. - Choose Auto-Translate and pick an engine and target language.
- Review the result in the list view, where the original and translation sit side by side.
- Save as a new file, UTF-8.
The local-model route is the one worth knowing about: it needs no API key and nothing leaves the machine, which makes it the only free method on this page that is also private. The trade-off is that a small local model translates noticeably less well than DeepL on European pairs, and you will do more editing.
Method 2: A format-aware online translator
Upload the file, choose a language, download the result. DeepL accepts an .srt as a document type and returns a translated .srt with the structure intact; how many documents you can run depends on your plan. Several dedicated subtitle-translation sites do the same thing.
This is the fastest route for one file in one language and the quality on major European pairs is the best of the four without any configuration.
Two things to know before using it. The file is uploaded, so it is the wrong method for anything confidential — an unreleased cut, a client's footage, a recorded internal meeting. And a document translator gives you no control over terminology: product names, character names and jargon get translated along with everything else, which is exactly what you do not want for names.
Method 3: An LLM with a strict prompt
This gives the best terminology control of the four, because you can tell the model what not to translate. It is also the method most likely to quietly corrupt the file, so the verification step is not optional.
A prompt that works:
Translate the subtitle text below from English into German.
Rules:
- Output exactly the same number of subtitle blocks as the input.
- Copy every block number and every timecode line unchanged, character for character.
- Translate only the subtitle text lines.
- Keep the blank line between blocks.
- Do not merge, split, reorder or renumber blocks.
- Do not translate these terms: [list product and character names here]
- Keep each translated line roughly the length of the original.
Work in chunks of 50 to 100 blocks rather than pasting a two-hour film in one go. Long inputs are where models start merging cues and dropping blocks, and they do it without mentioning it.
Then verify. This one-liner counts the timecode lines in both files:
grep -c " --> " original.srt translated.srt
The two numbers must be identical. If the translation is short, blocks were merged, and every cue after the merge is now wrong. Run this check on every LLM translation, every time.
Method 4: Translate as a layer, not as a file
The three methods above all share a shape: you have a file, you produce another file, and if you want eight languages you do it eight times and manage eight files.
A desktop app can keep one timeline instead. In Sablate, a translation is a layer added to an existing transcription rather than a new job — the cue boundaries are created once and every language inherits them, so the timing question does not arise a second time. Each layer carries its own style and its own script font, which matters the moment a language needs a script the caption font does not contain.
Two translation paths are available. Argos runs offline on your machine and never sends anything anywhere; DeepL, OpenAI and Claude are available if you bring your own API key. One honest detail about the offline path: Argos publishes packages that pair with English on one side, so a pair like Turkish to German has no direct package and is composed through English as an intermediate hop. It works, and a Turkish-to-German line reads slightly flatter than a Turkish-to-English one.
The free tier covers one offline translation layer per job on videos up to ten minutes; unlimited layers, the cloud engines and one-click export of every language are part of Pro. Download it for Windows or Mac and translate one file before deciding anything.
Which method should you use?
| Method | Cost | Runs offline | Terminology control | Best for |
|---|---|---|---|---|
| Subtitle Edit | Free | Yes, with a local model | Partial | One file, any language pair |
| Online document translator | Free tier, then paid | No | No | Fastest good result on European pairs |
| LLM with a strict prompt | Varies by model | Yes, with a local model | Yes | Jargon, names, a house glossary |
| Sablate | Free tier, Pro is $29 one-time | Yes | Yes | Several languages from one transcript |
"I have one file and no budget." Subtitle Edit. It is free, it is the most capable subtitle tool on this list for format work, and it will not break your timings.
"I need the best German translation and the file is not sensitive." A document translator. DeepL's output on English to German needs the least editing of anything here.
"The video is confidential." Subtitle Edit with a local model, or Sablate's offline path. Anything that uploads is disqualified regardless of how good it is.
"I am shipping the same video in six languages." Layers, not files. The per-file methods multiply by six; a layered workflow does not, and the multilingual workflow explains why the transcript deserves the careful proofread before any of it starts.
How to keep the timing from breaking again
Three habits, in order of how much time they save.
Verify the block count on every translation. The grep line above takes two seconds and catches the only failure that is invisible on inspection. A translated file with fewer blocks than its source is broken, always.
Check reading speed after translating, not after transcribing. The timings survived; the text did not stay the same length. English into Spanish or French typically runs 20 to 25 percent longer and German up to 35 percent, all of it inside the same number of seconds. A comfortable 14 CPS line becomes a 17.5 CPS line without a single timestamp moving — the reading speed limits cover what to do about it, and the answer is always to change the words or the duration, never the sync.
Keep the source transcript as the master. Correct names, jargon and punctuation there before translating anything. A surname fixed in the source is fixed in every language; the same surname fixed afterwards is one edit per language, and the edits drift.
If any of this ends up burned into a video, do it last. Reading speed in a burned-in copy is permanent, and the format you export to decides whether the viewer can switch languages at all.
Translate the file, not the video. Keep the timeline you already paid for, spend the effort on the words that sit on it, and check the block count before you ship.