Guides

Translating subtitle files, markdown and resource files

Three translation clients – subtitle, markdown, resource file – the key from an environment variable, the --check and --dry-run modes, and exit codes.

6 min read needs a GPU (NVIDIA on Windows, Apple silicon on a Mac) Updated 2026-09-23

The three clients

Besides LiveCaption's live translation, three standalone command-line clients also connect to the translator service (translatorserver) – to its front end, never directly to the engine running behind it. Every request carries the access key (lcp_…), so without a key the service rejects at the first step. The launchers are in the TranslatorServer folder: they find (and if necessary publish) the executable client, and pass the command line on unchanged.

Launcher Client (executable) What it translates
translate-subtitle.ps1 translate-subtitle subtitles: .srt, .vtt, .ass/.ssa
translate-markdown.ps1 translate-markdown markdown: .md
translate-resx.ps1 translate-resx resource files: .resx resources, PowerShell messages.psd1

All three send only the text to translate; whatever is not (timing, formatting tags, code, table structure, key names, header, the comments of subtitle and resource files) is written back byte-identical. The exception is a comment in a markdown code block: translate-markdown translates it by default (see below). A client's full switch list is its own help (translate-subtitle --help on the published executable); the launcher's -Help prints the launcher's help, not the client's.

The key from an environment variable

The key is issued by the account service (the web Keys page or the start-accountserver.ps1 -KeyAdd command, see the accounts, keys and permissions guide). A key written into the command line would end up in the shell history and the process list, so the recommended way is -ApiKeyEnv <variable name>: the name of an environment variable, not the key itself. The command line printed before the start masks the key as ***.

$env:LCP_TRANSLATE_KEY = "lcp_..."

TranslatorServer\translate-subtitle.cmd "C:\videok\01 - Bevezetes.eng.srt" -ApiKeyEnv LCP_TRANSLATE_KEY
TranslatorServer\translate-markdown.cmd "C:\Projects\docs\README.md" -ApiKeyEnv LCP_TRANSLATE_KEY
TranslatorServer\translate-resx.cmd "Strings.resx" -ApiKeyEnv LCP_TRANSLATE_KEY --to hu

--from and --to give the language pair; --server the front end's address (by default http://127.0.0.1:8080).

Subtitles: the timing does not slip

The ground rule of translate-subtitle: the output's cue count and timestamps are identical to the input's, only the text body changes, everything else – line endings, byte order mark, encoding, the WebVTT header and its NOTE/STYLE blocks, the ASS style definitions – stays byte-identical. Measured on a 12,994-file subtitle library, an earlier translation made with another tool had slipped in 1,054 of them. Formatting tags (<i>, {\an8}, \N) are protected; if the translation breaks their order, the sentence group's original text stays in place, and the closing report says so. Without an output name it writes next to the input, swapping the language code: 01 - Introduction.eng.srt → 01 - Introduction.hu.srt. With a folder input the whole tree is translated; files already done are skipped, --force retranslates them; an interrupted run is continued by the same command.

Markdown: the structure stays

translate-markdown translates the text of paragraphs, headings, list items, table cells, link captions and callouts, and the comments in code blocks too – the code itself, every structural mark, the table's separator row, link URLs, the front matter, formulas and HTML blocks stay byte-identical. Code spans and URLs inside prose are shielded: the model sees a [[n]] marker in their place. Where the structure is ambiguous, the line stays raw: the worst failure mode is untranslated text, never a broken structure. README.md → README.hu.md; --no-code-comments turns off the translation of comments.

Resource files: the placeholders are protected

The three ground rules of translate-resx: by default only the missing keys are translated (--all asks for all of them); a failed key is not written but stays missing, so that the next run retries it; the file's form is preserved. Every translation passes three checks: the set and shape of the placeholders ({0}, {Name}), the protected words (the parts marked as code and the switch names), and the line breaks. --keep-placeholder-order enforces the order too.

Source Target
Strings.resx Strings.hu.resx
Strings.en.resx Strings.hu.resx
Resources\en\messages.psd1 Resources\hu\messages.psd1

Checking without translating: --check and --dry-run

--check runs in all three clients without translation and without a server. For subtitles and markdown it parses the file, writes it back, and compares the two byte sequences; for resource files it compares the source with the target: missing key, superfluous key, differing placeholder. On a difference the exit code is 4, usable as a script condition. --dry-run shows what it would translate and how it batches, without translating.

translate-subtitle "C:\videok" --check
translate-subtitle "F:\videok\Blazor" --dry-run
translate-markdown "C:\Projects\docs" --check
translate-markdown bemenet.md --dry-run
.\translate-resx.exe .\LiveCaption --check

Exit codes

The repository's common table, because the code is a contract with the scripts; 3 is deliberately missing, it belongs to the caption client's FFmpeg error.

Code Meaning
0 done
1 wrong usage, or the explicitly requested help
2 missing input
4 other error (a partially successful folder run and a --check difference too)
5 interrupted (Ctrl+C)
6 the service is unreachable, or the engine is not ready

Making the subtitle files: batch subtitling a video folder; starting the services: first start.

All guides

Hiba történt az oldal futtatásakor. / An error occurred while running the page. Újratöltés / Reload 🗙