VIEW THIS AS

Auto mode follows the Route Engine until you choose a viewpoint.

YOU ARE HERE

ROUTE CHECK

CONNECTED TO

WHAT NEXT

Use the canonical route for this room, or HELP if you are unsure.

Translate Like a Pro | 7760 — Haskell optparse-applicative Localization, ParserInfo, Help, Subcommands, Errors and CLI QA

Haskell optparse-applicative localization is the practical work of translating command-line help, option descriptions, usage guidance and application errors without changing the flags that scripts depend on. If you need multilingual Haskell CLI help, localized ParserInfo descriptions, optparse-applicative subcommand documentation, terminal-safe Unicode or a reliable release QA checklist, the first distinction is between text people read and syntax a program accepts.

The optparse-applicative library composes typed parsers and generates help and many parser diagnostics. Its familiar pieces—strOption, switch, help, metavar, info, helper, subparser and execParser—have different responsibilities. A translated help string changes guidance; it does not, by itself, rename a --input flag, translate every generated error or establish a policy for language selection.

This guide is for developers, open-source maintainers, technical writers, translators, build engineers and learners anywhere in the world. We follow a fictional, read-only inspection utility from a small parser to a tested multilingual release. Every example separates human-readable messages from stable machine behavior, because translation only helps when the next command a reader copies actually works.

Quick answer: translate explanations, preserve the executable contract

Start by building a language-resource table for descriptions, headers, footers, examples and application-owned errors. Pass the selected translations into the parser construction step, leave canonical flag and subcommand tokens stable, and inspect generated parser failures independently. Use the actual installed optparse-applicative version as the authority for advanced rendering behavior. Test complete terminal output, not only isolated strings.

  • Localize help, progDesc, header, footer and your own diagnostic prose.
  • Treat long, short, command names and output keys as interfaces, not ordinary sentences.
  • Distinguish a display-only metavar from a positional value or accepted option spelling.
  • Check root help, nested commands, completion, unknown flags, missing arguments and unsuccessful exits.
  • Freeze a locale-precedence rule; provide a reviewed fallback for missing translations.
  • Preserve JSON/CSV structures, numerical results and error codes when the presentation language changes.

Contents and the learning route

Begin with a small working command and the terminology used by optparse-applicative. The middle chapters work through design decisions, failures that appear only in multilingual terminals and concrete experiments. The final chapters provide a four-week adoption plan, frequently asked questions, source documentation and a release gate. Readers can use one section as a reference without reading the entire article from beginning to end.

A read-only example: the same command in two languages

Imagine a program called atlas-check. It accepts a required path and an optional verbose switch, validates the request and prints a summary. The example does not open or modify real data. A user who sees the German help should still be able to run the same atlas-check --input observations.csv --verbose command. The localized description may say what the file means, but the accepted flag stays recognizable in shell history, examples and scripts.

import Options.Applicative

data Args = Args
  { inputPath :: FilePath
  , verbose   :: Bool
  }

parser :: String -> String -> Parser Args
parser inputHelp verboseHelp =
  Args
    <$> strOption (long "input" <> metavar "FILE" <> help inputHelp)
    <*> switch (long "verbose" <> help verboseHelp)

settings :: String -> String -> String -> ParserInfo Args
settings description inputHelp verboseHelp =
  info (parser inputHelp verboseHelp <**> helper)
       (fullDesc <> progDesc description)

main :: IO ()
main = do
  opts <- execParser (settings
    "Inspect an input without changing it"
    "Path of the input to inspect"
    "Show additional details")
  putStrLn ("Selected input: " ++ inputPath opts)

The snippet demonstrates how application-owned strings can enter the parser as arguments. It is deliberately small: real localization resources should not be scattered through conditionals in main, and a genuine production tool should validate path inputs before reading anything. Avoid confusing a demonstration of string injection with a claim that every internal optparse-applicative sentence is customizable through the same parameters.

For a second language, build an equivalent ParserInfo with reviewed alternatives for the three descriptions. Run exactly the same valid command under both settings. When the parsed Args values match but the visible explanations differ appropriately, you have tested an important boundary. Repeat with an invalid flag, because generated failure messages may come from a separate rendering layer.

Understand the library before planning translation

optparse-applicative’s design is compositional. An option or argument parses an input value. A modifier such as help contributes display metadata. ParserInfo describes the command at a higher level; parser preferences influence aspects of error and help rendering. Confusing these layers creates localization bugs that look like grammar mistakes but are really interface mistakes.

There are also two distinct audiences. A human reader needs a natural sentence and a working example. A shell, automation job, completion script or another program needs reliable tokens and predictable output. A multilingual CLI must serve both, and cannot assume that translated text is a substitute for compatibility testing.

Thirty-two practical localization decisions

Each decision below is deliberately tied to something a real Haskell CLI may parse, display, log or ship. The problem statement explains why a reader encounters it; the design response explains what to change; the test says how to tell a careful solution from a merely fluent sentence. Use the sections that match your product rather than treating every mechanism as mandatory.

1. Option names are interface keys

A maintainer translates –input into a word that reads beautifully in Spanish, but scheduled jobs still send –input and stop working. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Keep the canonical flag unchanged and explain its meaning in translated help. If there is a strong usability case for a new alias, add and test it explicitly rather than silently replacing the old spelling. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Compare parses of saved command fixtures before and after the language change; record argv, exit status, and parsed values. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

2. Long and short forms

A long flag can be understandable while its one-letter short alias collides with a letter desired by another language. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Preserve published short aliases by default. A translated description can mention both forms without implying that every possible initial letter is a supported alias. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Run help and invocation tests for both –verbose and any published -v alias, including combined options if your parser permits them. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

3. Metavars are not actual values

A translator changes FILE to a phrase that looks like two separate arguments, although the parser takes one path. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Use a concise localized display placeholder when it helps, but document whether it represents one token, a path with spaces, or a repeated value. Do not alter parser arity. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Copy the displayed example into a shell and confirm that its quoting and number of inputs match the option reader. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

4. Required and optional values

The text says an argument is optional while the strOption parser requires it, so the first run fails unexpectedly. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Align the resource text with parser combinators, not with an outdated specification. Read the actual help and validate the behavior of omitted values before approving translation. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Create cases with no arguments, only –verbose, and –input followed by a valid path; compare the error conditions. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

5. The help modifier

Writers expect help to affect runtime validation, even though it is display metadata. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Treat help as a contextual explanation: what the option does, what values it accepts, and whether the action has consequences. Keep type checking in the parser and domain validation in application logic. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Feed an invalid value after changing only the help string and verify that the same validation rule still operates. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

6. The helper parser

An author translates the displayed help heading and accidentally removes the functional –help pathway from the parser definition. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Retain helper in the appropriate parser composition. Build a localized ParserInfo without removing the behavior users rely on to discover options. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Execute –help in every locale and confirm it exits through the expected help path rather than treating it as an unknown flag. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

7. Program descriptions

A description claims the utility edits input files, even though the program only inspects them. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Use progDesc for a short accurate purpose statement. Translate the verb describing the operation carefully: inspecting, validating, exporting and changing data have different implications. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Pair each translated description with a safe read-only example and ensure the result is consistent with the promised operation. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

8. Headers and footers

The top line becomes a marketing slogan and pushes the actual usage instructions below the first screen of a small terminal. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Use header and footer for context that supports action: a concise identity, limitations or documentation pointer. Put verbose tutorials in a separately linked manual. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Capture –help at a narrow and a wide column setting; measure whether the command and required flags remain discoverable. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

9. Full help versus brief help

Readers see one line of help in a subcommand and assume that options listed elsewhere do not apply. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Choose help rendering policies deliberately and provide a route to full documentation. Avoid asserting that a description appears in every context unless the installed library renders it there. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Inspect the root, parent and child help displays and record what each actually includes. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

10. Subcommand names

A team translates a command name in prose and then publishes an example using that translated word though only the original name is accepted. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

With subparser and command, separate the name used in argv from the description displayed to readers. Decide explicitly whether aliases are supported and document the canonical syntax. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Run the root command, each child, and an invalid child name. Ensure help examples are executable in every language. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

11. Nested help routes

A user can view main help but cannot find how to ask for help on a child action. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Inspect whether your configuration uses subparser or hsubparser, and test child-level help behavior on the installed version. Show the exact working invocation in the translated guide. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Capture the output of parent –help and child –help separately; do not assume that identical English wording means identical parser structure. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

12. Conflicting language switches

One person expects –language to select only messages, another expects it to change file parsing and result values. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Define the locale option as presentation policy unless the product explicitly offers localized input formats. Document interactions with environment and configuration preferences; avoid ambiguous terminology such as universal regional mode. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Under two language selections, compare parsed numerical values and machine results and inspect the rendered descriptions. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

13. Locale chosen before parser construction

The program needs translated help before the full parser has been evaluated, but –language is itself part of that parser. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Choose a controlled bootstrap strategy: a small documented preliminary option parser, a configuration choice or an environment-derived locale. Do not scan arbitrary argv substrings in a way that changes security or quoting rules. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Test –language at the start and end of argv, duplicate values, invalid values and presence of –help; verify precedence. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

14. Fallback language resources

A missing regional catalog produces empty strings in otherwise complete help output. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Define a fallback chain such as a supported regional catalog followed by its base language and an explicitly chosen final fallback. Treat unsupported choices as a documented condition rather than pretending a translation exists. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Remove one optional message and one required message in a test build; check that no raw resource key or blank description leaks. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

15. Missing versus intentionally blank text

A literal empty string may mean an omitted optional footer, whereas a missing string may be a packaging error. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Differentiate these states in the language-resource loader. Give translators a way to mark intentionally absent copy without masking a missing required description. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Inject both cases and inspect logs, help output and the packaged catalogs; a passing build should expose genuine omissions. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

16. Plural and agreement choices

A message reports ‘1 files inspected’ because a template interpolates a number into a single invariant English sentence. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Use a localization format or typed message function that supports grammatical variation by language; avoid reusing one sentence template for every count. Format meaning, not English word order. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Test zero, one, two and many inspected files, including languages with more than two plural categories. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

17. Option readers and localized numerals

A translated example uses a comma decimal separator, while the installed option reader still accepts only a dot. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Keep the input grammar visible and stable unless localized parsing is an intentional product feature. Separate human-formatted reports from machine accepted syntax, and document any exception precisely. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Try 1.5 and 1,5, a negative number, non-ASCII digits and an invalid symbol; compare reader outcomes with documentation. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

18. Custom read errors

A developer writes a friendly translated error that hides which value was rejected or how to correct it. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Keep a structured error identity and a safe, localized explanation, including the expected value type. Avoid echoing secrets or untrusted raw inputs into public diagnostics. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Exercise custom readers with a valid value, malformed value and a potentially sensitive token; inspect stderr, status and redaction. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

19. Generated parse errors

Only option help was translated, so built-in missing-argument messages remain in English. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Inventory framework-generated diagnostics separately from application text. Review supported customization surfaces rather than assuming help changes all errors; use consistent language policy in wrapper messages. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Run unknown-option, absent-value, bad-reader and wrong-command fixtures; classify which sentences are library-owned. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

20. Pure parser execution

Tests that invoke the process end to end become flaky because terminal width and locale environment vary. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Use documented pure parsing facilities such as execParserPure where suitable to test acceptance independently of IO. Render failures separately and keep integration tests for actual stdout, stderr and exit codes. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Assert getParseResult outcomes for fixed argv and then run packaged binaries for user-facing text. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

21. Error rendering preferences

A project assumes every error prints full help, leaving users with lengthy diagnostics and hiding the actual reason. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Treat ParserPrefs, including help-on-error and column preferences, as output design choices. Confirm the API against the installed release because preference types and details can change. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Compare output for a single unknown flag with brief and full-help settings; record which choice helps the user recover. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

22. Unknown option suggestions

A localized error suggests a translated flag that the parser does not recognize. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Suggest only executable canonical options. If your application builds supplementary hints, derive the tokens from parser definitions or a reviewed registry instead of translating arbitrary strings. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Insert a plausible typo in –input and verify the proposed replacement is an accepted argv token. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

23. Shell completion

A completion script presents option names and descriptions; language changes can inadvertently alter a user’s workflow. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Preserve the accepted token set and review completion generation as a separate integration surface. If completion descriptions are localized, test how the target shell displays and caches them. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Generate or invoke bash, zsh and fish completions as supported; check the results in a real shell and an automated fixture. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

24. Terminal wrapping

A German compound or a long translated explanation wraps badly under a narrow help width. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Use library formatting preferences and concise reviewed text. Do not count bytes as display cells; combining characters and wide glyphs have different terminal widths. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Capture the same help at 40, 60, 80 and 120 columns, including Unicode and a long path metavar. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

25. Unicode normalization

Two visually identical identifiers may use different Unicode sequences, confusing tests and copied examples. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Avoid using translated prose as a lookup key. Normalize only where a clearly defined data contract requires it, and never silently alter file names or externally meaningful option values. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Compare composed and decomposed accented text in filenames, output and message resources without changing the bytes of accepted command flags. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

26. Bidirectional text

Right-to-left explanations may reorder flags, punctuation or arrows when displayed beside Latin command tokens. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Keep code tokens visibly isolated in translated documentation and test actual RTL terminal rendering. Avoid claiming that simple string concatenation guarantees readable results in every terminal emulator. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Inspect –help with Arabic or Hebrew resources in supported terminals, including quoted paths, numbers and colon punctuation. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

27. Quotes and escaping

A translator inserts typographic quotation marks into a copyable shell example, and the command fails. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Use natural punctuation in prose but preserve ASCII syntax inside command blocks when the shell requires it. Provide separately formatted working examples so punctuation is not mistaken for a token. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Copy the command from the published page into a fresh shell and compare argv received by the program. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

28. Structured output

A localized banner appears before JSON output, breaking users who pipe stdout to a parser. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Separate interactive explanations from machine-readable stdout. Consider an explicit –format=json contract and put diagnostics on stderr, retaining stable field names and semantic types. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Parse stdout as JSON under every supported locale and ensure no translated header, progress text or stray newline contaminates the payload. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

29. Sensitive errors

A path validation failure repeats an access token embedded in the argument value. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Translate a safe message pattern rather than exposing the original untrusted value by default. Decide deliberately what may be logged, shown or redacted, including in debug mode. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Feed a synthetic secret into a rejected option and search both stderr and diagnostic logs for the token. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

30. Accessibility and screen readers

A dense help table aligns visually but reads in confusing order when captured by assistive software. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Prefer short sentences, descriptive headings and predictable sequences. Offer plain-text alternatives to elaborate formatting and avoid relying on color or spacing to carry an instruction. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Review output through a text-to-speech or linear reading workflow, and have a user follow the steps without relying on layout cues. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

31. Cross-platform packaging

The source checkout includes catalogs but the released executable omits a language file, so fallback masks the failure. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Declare resources in the build and package manifest, test installed artifacts, and document whether messages are embedded or read from disk. Confirm that Windows and Unix paths resolve correctly. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Build clean release packages on supported platforms; inspect the resource inventory and compare hashes with intended language files. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

32. Documentation and examples

A translated README describes a flag from a previous release and a correct help screen contradicts it. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Generate or review help examples from one source of truth. Distinguish tutorial context from definitive parser behavior, and keep versioned examples with the version they describe. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Execute every published command example in CI against the release artifact, including child command paths. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

33. Compatibility and deprecation

The multilingual release removes a legacy spelling because it is not natural in one language. This is a translation problem and an interface-contract problem at the same time: readers must understand what they can do, while existing automation must continue to receive the same meaning.

Treat localization as compatible presentation work unless an explicit migration is approved. Deprecate accepted tokens through a separate versioned contract and preserve an actionable message for users. In optparse-applicative, distinguish parser definitions and modifiers from text supplied by the application. A change belongs in the layer that actually owns its behavior, not in an unrelated translation string.

Replay production-safe historical argv fixtures, compare exit codes and require release-note approval for any deliberate syntax change. Keep the successful and unsuccessful cases side by side in a small regression fixture; a visually improved help screen alone is not sufficient evidence.

Failure investigations: from a confusing help screen to a verified fix

Investigation 1: The French user copies a non-existent flag

Help text translated the canonical –input token as though it were an instruction. Restore the actual token inside code formatting, keep the explanatory phrase outside it, and run the example from the published documentation. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Check a real command invocation and an existing batch job; the translation passes only when both use the same accepted argv. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 2: The –help route vanishes in a child command

The child was built with a different parser composition than the root. Review the subparser setup and whether hsubparser is appropriate for the installed version. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Verify root help and child help independently, not by looking only at the parent synopsis. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 3: A missing value prints English while all descriptions are localized

Option descriptions came from resources, but the failure renderer remained library-owned. Separate the two inventories and review the API instead of searching a catalog that never contained that sentence. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Run an explicit missing-value fixture and record which messages are under application control. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 4: A displayed placeholder looks like a default

The metavar is written as a concrete example and readers assume they need not supply it. Show an abstract placeholder in usage and put an explicit example in prose. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Invoke with and without the actual required option and check that help correctly predicts both results. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 5: A locale option works only before another flag

Language selection was performed by a fragile early scan. Replace it with a documented bootstrap rule or structured preliminary parser that does not misread option values. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Test ordering, duplicates and a path whose name resembles a locale string. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 6: Help looks good in development but broken in a container

The developer terminal supported UTF-8, while the deployed runtime lacked an equivalent locale or font configuration. Test the real runtime and state limitations. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Compare terminal encoding, captured output and fallback behavior in the package users actually install. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 7: A line of help collides with the next column

The translated string grew longer than the fixed width expected by a custom formatter. Prefer tested wrapping or a concise sentence that retains its meaning. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Render at several column widths and inspect alignment without relying solely on screenshots. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 8: An Arabic example reverses the apparent argument order

Mixed RTL prose and LTR option tokens interacted with bidi display. Isolate the command in a code block, keep ASCII tokens as typed, and review with a native speaker. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Copy the command from the rendered document into a shell and inspect its received argv. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 9: Shell completion suggests a text label rather than a token

A completion description was used as if it were the option identifier. Separate the returned completion value from its displayed explanation. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Compare completion candidates against all accepted flags and confirm selected candidates execute. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 10: JSON suddenly contains a human-facing greeting

A translated startup message was added to stdout before structured data. Move optional chatter to stderr or omit it in machine-output mode. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Pipe stdout through a JSON parser under two locales and compare keys and types. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 11: A release omits one message catalog

The developer workspace carried the file but the package recipe did not. Add resource inventory checks at the artifact boundary. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Install from a clean package, remove checkout-only paths and test the missing locale deliberately. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 12: An error exposes a private input path

An English string was replaced with a localized interpolation that includes the entire argument. Keep a redacted error schema and translate only the safe explanation. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Feed a synthetic sensitive path and scan all output channels for unapproved details. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 13: A translation changes unit interpretation

Documentation says metres while the parser and calculation still expect feet. Translate the semantic unit accurately or change the product contract through a separate, tested release. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Compare numeric calculations and displayed units across languages using known inputs. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 14: Two independent locale sources disagree

The process environment requests one language and a command option requests another. Define precedence once and apply it to help, errors and application-owned output. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Test conflicting inputs, invalid locale, inherited environment and a missing catalog. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 15: A subcommand is renamed only in the manual

The documentation page shows a localized command, but command still defines the original token. Correct the example or implement a deliberate alias with compatibility review. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Execute all examples in the manual and replay existing scripts before releasing. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

Investigation 16: A translated warning sounds like success

A translator softened a cautionary ‘not verified’ message into ‘completed’. Restore uncertainty, authority and operational consequences; linguistic fluency cannot alter outcome status. The distinction matters because language and program behavior must agree: readers cannot recover safely when one claims an operation succeeded and the other rejects it.

Ask a second reviewer to compare the original condition, the new message and the observed exit code. Save a compact before-and-after transcript, including the exact locale, command, expected status and observed result, so a later maintainer can reproduce the finding.

A four-week implementation and review plan

Week 1 — capture the real interface

List every accepted option, short alias, child command, positional input, metavar, default, output field and exit status. Save successful and failing examples, including no-argument use and –help. Inventory descriptions and messages with owners: parser modifiers, application output, library-generated diagnostics, manuals and completion. Choose the primary supported locales from actual reader needs rather than language marketing. A reliable baseline lets you change text while proving that syntax and results remain stable.

A useful deliverable at the end of this week is a short evidence record: what was tested, what changed, which limitations remain, and who confirmed the result. That record should be intelligible to a translator and to a maintainer who did not write the original parser.

Week 2 — create and review language resources

Give every message a stable resource key, translator context and a representative command invocation. Review plural forms, values, units, conditional meaning and safety language. Inject reviewed strings during parser construction for the surfaces it supports. Do not assume changing help fields localizes library-generated errors. Establish the selection and fallback policy, then have a native-language reviewer run examples instead of checking grammar in isolation.

A useful deliverable at the end of this week is a short evidence record: what was tested, what changed, which limitations remain, and who confirmed the result. That record should be intelligible to a translator and to a maintainer who did not write the original parser.

Week 3 — test on terminals and in automation

Build fixtures for two languages, one missing catalog, Unicode filenames, narrow widths, child commands, completion, invalid options, numeric values and mixed-direction text if supported. Capture both stdout and stderr with exit codes. Compare the parsed configuration and machine-readable results across languages; test that resource loading neither changes file access nor leaks sensitive values. Run both pure parser tests and the actual packaged executable.

A useful deliverable at the end of this week is a short evidence record: what was tested, what changed, which limitations remain, and who confirmed the result. That record should be intelligible to a translator and to a maintainer who did not write the original parser.

Week 4 — release, explain and maintain

Rebuild from a clean environment and verify resource files are included. Execute all documentation commands, publish a truthful supported-locale list and state the canonical argv syntax. Record the parser library version used during QA and save transcripts as regression assets. Ask users to report confusing text with command and locale, but never require them to disclose secrets. Schedule copy reviews when new flags or subcommands are added.

A useful deliverable at the end of this week is a short evidence record: what was tested, what changed, which limitations remain, and who confirmed the result. That record should be intelligible to a translator and to a maintainer who did not write the original parser.

Frequently asked questions

Does optparse-applicative translate help automatically?

It generates help from parser definitions, but that does not mean it supplies reviewed translations for every language. Your descriptions and policies need an explicit resource strategy. Generated diagnostics require separate testing. Where the result depends on a parser version, run the documented command against the release you ship and keep that evidence alongside the language review.

Should I translate –input or –verbose?

Usually no. Those strings are accepted command tokens, not merely UI labels. Explain their purpose naturally in a translated sentence; introduce aliases only after a deliberate compatibility review. Where the result depends on a parser version, run the documented command against the release you ship and keep that evidence alongside the language review.

What is ParserInfo?

It wraps a parser with command-level presentation information such as descriptions and headers. It is a useful place to inject selected application-owned messages but not a guarantee that every failure sentence is localizable. Where the result depends on a parser version, run the documented command against the release you ship and keep that evidence alongside the language review.

What does helper do?

It supports standard help behavior when combined with a parser as documented. Check that the root and child command configurations actually expose the help route you document. Where the result depends on a parser version, run the documented command against the release you ship and keep that evidence alongside the language review.

What if a translated metavar contains spaces?

A metavar is a display label, not a way of changing the number of accepted argv values. Prefer concise placeholders and use a properly quoted example when the path or value may contain spaces. Where the result depends on a parser version, run the documented command against the release you ship and keep that evidence alongside the language review.

How should I choose a locale?

Document a predictable source: for example an explicit option, a configuration field, then an environment preference and a reviewed fallback. Test conflicts and invalid values, especially when help must be built before normal parsing. Where the result depends on a parser version, run the documented command against the release you ship and keep that evidence alongside the language review.

Can a translator change error severity?

No. A message must preserve whether the command succeeded, failed, warned or did not perform an action. The program’s actual status and security implications take priority over stylistic smoothness. Where the result depends on a parser version, run the documented command against the release you ship and keep that evidence alongside the language review.

Is Unicode terminal testing necessary?

Yes for a world-facing program. Rendering varies with encoding, width, glyph support and directionality. Test the actual terminals and packaged binaries used by supported audiences. Where the result depends on a parser version, run the documented command against the release you ship and keep that evidence alongside the language review.

Can I localize JSON field names?

Only as an intentional breaking interface change, which is usually inappropriate for a display-language setting. Keep field keys and schema stable; localize human-readable reports separately. Where the result depends on a parser version, run the documented command against the release you ship and keep that evidence alongside the language review.

What confirms a safe multilingual release?

The same valid commands parse the same way, invalid commands fail with the same semantics, human prose is understandable, fallback is defined, copied examples work and every packaged language resource is present. Where the result depends on a parser version, run the documented command against the release you ship and keep that evidence alongside the language review.

Official technical documentation and further reading

The optparse-applicative project documentation explains its parser builders, help screens, custom parsing and completions. The Hackage API reference for version 0.19.0.0 documents ParserInfo, ParserPrefs, subparsers, pure execution and failure rendering. Confirm APIs against the installed version; these links explain the library rather than promising that it has a full built-in translation catalog.

Related eduKateSG translation routes

Explore the Translate Like a Pro series index and the Master Art of Translation complete system. For a related typed parser in another ecosystem, see clap Rust CLI localization. This guide is intentionally specific to Haskell optparse-applicative and does not replace general translation theory.

Final release acceptance checklist

Approve the release only after a human reader can explain the command, copy every shown invocation, distinguish options from placeholders, recover from a failure and understand whether anything changed. Confirm that the locale setting changes presentation rather than the accepted argument grammar; that structured data and exit statuses remain compatible; that missing resources follow a documented fallback; and that a clean installation reproduces the tested behavior. Clear localized help is not the longest sentence or the most literal wording. It is the instruction that tells a reader exactly what works.