OCaml Core.Command localization begins with a distinction that every translator and developer needs: the command tree and its accepted flags are executable contracts, while the summaries, longer explanations and usage examples are communication. People searching for Jane Street Core.Command, Command.Param, Command.basic, Command.group, anonymous arguments, flag documentation and multilingual command-line help need to know which pieces can be translated safely. A pleasant French or Arabic description does not make a new command name valid, and replacing a flag in a sample can break a working tool.
Imagine a read-only library catalogue utility called catalog with a search subcommand, a required query and an optional numeric limit. Its operators may work in Spanish, English, Mandarin or Japanese. The text should explain what the query is and which limits are supported, but the literal command route must match the registered Core.Command group. A negative number may be mistaken for a flag, a shortened flag prefix may become ambiguous, and a Unicode filename may pass through a shell differently. These are problems for documentation and implementation together, not just vocabulary.
This guide explains Core.Command from modern Param-based specifications to typed flags, command groups, help generation, parser failures, testable argv and release packaging. It includes a conservative worked example, independent troubleshooting cases, FAQs and a four-week learning and validation plan. The aim is to let a reader run a safe command, understand the result and recover from a mistake using the actual built executable. It does not require the reader to trust undocumented locale magic.
Quick answer: the stable boundaries
- Preserve registered subcommand and flag names unless real aliases are implemented.
- Use modern Command.Param specifications and state requiredness, types and defaults accurately.
- Separate parser failures, runtime failures, help presentation and shell quoting.
- Test the shipped binary with Unicode values, completion and a missing-language fallback.
A short read-only example using Command.Param
A catalogue search is a useful teaching example because it lets a reader see parsed input without modifying a record. The following OCaml sketch shows a required positional query and optional typed limit. The query is data supplied by the user, while the flag name is part of the program’s registered grammar. The source code is illustrative: compile it using a project configured with the matching Core and ppx_let versions, and rely on its generated help to verify the displayed syntax before publishing a command example.
open Core
let search =
Command.basic ~summary:"Preview catalogue search results"
(let%map_open.Command query = anon ("QUERY" %: string)
and limit = flag "-limit" (optional_with_default 20 int)
~doc:"N maximum number of matches to preview"
in
fun () ->
printf "Query: %s; limit: %d\n" query limit)
let command =
Command.group ~summary:"Read-only catalogue commands"
[ "search", search ]
let () = Command.run command
This sketch demonstrates one readable route rather than a claim that Core.Command provides automatic locale detection. In a localized program, construct the summary and doc strings from your own chosen resources and show the exact syntax that the program accepts. Never translate the word search into an executable alias without registering it. Keep the initial task harmless and visible: print the received query and limit and inspect whether the result matches the guide.
Core.Command field guide: parsing, explanation and verification
1. Why Core.Command has a distinct role
How it works. Jane Street Core.Command offers a structured way to build OCaml command trees, typed parameters and generated help. It does not perform the broader work of translating an organization’s terminology, examples or cultural assumptions. The program owns that editorial policy. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A search tool can have a fixed route named search and a summary written in a target language. Users should see the route literally, then its purpose as prose. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Render the current help and compare it with a clean installed invocation. If a translation recommends a different route, correct the documentation or explicitly implement a new route. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
2. Modern Command.Param rather than legacy Spec
How it works. Modern Core.Command documentation identifies Command.Param as the preferred approach and labels the older Command.Spec interface deprecated. Param specifications combine input declarations with the eventual command body. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. An example that uses let%map_open with anon and flag describes current structured usage more clearly than teaching a new learner only the deprecated basic_spec interface. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Select and pin the actual installed Core version. Build the example using the API that version exposes; do not mix snippets from different release generations. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
3. Command.basic summary
How it works. Command.basic constructs a command with a short summary and a parameter specification. That summary is public help content, not a route identifier. It may be localized without modifying how the command parses inputs. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. For a safe catalogue search, the summary can tell users that the command prints a list of matching records. It should not promise a network search if the application only reads a local fixture. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Check that a target-language summary appears in help and that the exact registered invocation still works. Test the binary rather than a text-only translation file. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
4. Command.group and its child names
How it works. Command.group composes a hierarchy of named subcommands. The group summary and optional readme describe what the group does, while the subcommand name is the token typed by the user. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A group containing search and inspect should show those literal command names with explanations. The package documentation notes that subcommand names containing underscores are rejected; use dashes when appropriate. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Try the top-level help, child help and a deliberately wrong child. Confirm a reader can move from overview to executable route without guessing a translation. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
5. Longer readme help
How it works. The optional readme function supplies fuller help text for a command or group. It is an appropriate place to put task context and cautions that would be too long for a one-line summary. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Write a concise purpose first, then accepted values, one working example, an expected result and a useful recovery action. A long translated essay that hides syntax is less helpful than a short usable command guide. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. View help in both full-width and narrow terminals. Check that the readme does not overwhelm required flag information or make a placeholder look literal. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
6. Command.run and its argv contract
How it works. Command.run executes the registered command against process arguments or an explicitly supplied argv in supported versions. This makes program behavior testable without relying only on visual terminal inspection. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A multilingual regression test can supply the same syntax with different Unicode values and compare the invoked action. Language selection may affect messages but should not silently change parser semantics. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Use controlled argv tests and a packaged binary. Record version, locale, selected path and process result for both valid and invalid invocations. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
7. Param flag names
How it works. Command.Param.flag registers a named option with documentation and a typed flag specification. Names generally use a leading hyphen; the API can normalize a supplied name, but the user sees the effective command-line spelling. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Keep the printed flag token separate from its translated description. If an app accepts -limit, a guide should not casually rewrite it as –limit or a word in another language. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Generate help and test the exact sample syntax. Use a deliberate typo test to establish how the parser responds. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
8. Flags may allow unambiguous prefixes
How it works. Core.Command documentation describes matching unambiguous flag prefixes unless full_flag_required is selected. A shortened form that works today can become ambiguous after another option is introduced. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Teach full names as the stable public pattern. Prefix abbreviations may be convenient for an expert but are fragile in multilingual training materials and command evolution. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Add a second similar flag in a test build and observe the ambiguity. Explain the resulting error without suggesting a prefix as a universal alias. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
9. Full flag requirement
How it works. The full_flag_required option can enforce that users type the complete flag. It provides a useful stability rule where automated scripts and documentation need exact and predictable tokens. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A localized guide should use complete option names even if older versions accepted prefixes; this makes examples more robust against future additions. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Attempt a shortened spelling and record whether the actual release accepts or rejects it. Match the article’s claim to the tested configuration. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
10. Aliases are product features
How it works. Command.Param.flag accepts a list of aliases in supported versions. An alias can provide shorter or alternate registered spellings, but every alias is part of the command grammar and requires maintenance. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. If a team adds an alias for regional users, publish both the canonical spelling and verified alias, noting where they are supported. Do not equate a translated help label with an alias. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Test all aliases against every child command and confirm there is no collision with existing names, parser defaults or future planned options. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
11. Required flags
How it works. Command.Flag.required binds a value that must be present exactly once. A translator should make mandatory status explicit because omission produces a parsing failure, not a default. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. For a report search that requires -query, show a complete invocation. Do not describe query as optional merely because the user might wish to browse everything. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Run the command with missing, present and repeated required flags. Explain the difference between a missing value and a repeated value. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
12. Optional flags
How it works. Command.Flag.optional binds a value that may be omitted and is represented as an OCaml option. Omission and an explicitly empty input are different events. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. If -region is optional, say what happens when it is absent. Do not tell users to type None unless the application explicitly accepts that string as meaningful data. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Inspect the bound OCaml value for missing, empty and supplied input. Confirm that the localized default description matches the handler behavior. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
13. Optional flags with defaults
How it works. Command.Flag.optional_with_default supplies a value when a flag is absent. This is useful for limits or modes, but the translated summary must state the real default rather than a culturally familiar guess. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A row limit of 20 should be demonstrated once with -limit 20 and once with the option omitted. A change of default is a code and documentation change. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Verify the parsed result in both cases, then test a malformed value to show what the type conversion rejects. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
14. No-argument flags
How it works. A Boolean-like no-argument flag changes behavior by presence, not by asking for a translated word. The actual command specification decides whether it is a switch or a typed value. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. For verbose output, teach the exact flag and the absence case. Separate the prose explanation of yes or no from the literal token used by scripts. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Run present and absent forms; compare whether the body receives a Boolean and what the program prints. Do not invent negated aliases. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
15. Type-driven Arg_type parsing
How it works. Command.Arg_type specifies how text becomes an OCaml value. Core provides types including strings, integers, floats and dates in the documented API. These types have real grammars. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A translated instruction saying enter any number is insufficient for an integer option. Some regional punctuation conventions will not be accepted unless the application supplies a converter. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Test a normal value, a malformed value and a locale-looking alternative; describe observed conversion instead of overpromising cultural flexibility. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
16. Anonymous argument names
How it works. Command.Anons declarations describe unnamed positionals. The named placeholder is shown in usage, while parsing depends on position and type rather than on how the placeholder sounds in another language. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A required QUERY should be shown as replaceable data, not a literal token. Translating the placeholder in prose can help, but readers must understand they replace it with a search phrase. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Ask a new reader to construct an invocation from the usage line. Confirm they do not literally type QUERY or reorder positionals. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
17. The percent-colon specifier
How it works. Command.Anons uses the infix percent-colon constructor for an argument name and Arg_type. This defines one required argument of a particular type, not an arbitrary English phrase. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A small reference should show why QUERY is a named positional and why an integer count must be a valid integer when used as another positional. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Build a test with one missing positional and one wrong type. The error should lead users to the right input rather than to translate syntax symbols. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
18. Special characters in placeholder names
How it works. The library documents treatment of anonymous argument names, including uppercase conversion and special surrounding delimiter rules. Translated placeholders must respect syntax constraints in the spec. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A label that looks like an editorial note may become invalid when inserted directly into a parser declaration. Prefer short ASCII identifiers in the specification and rich localized explanation in readme text. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Compile translated metadata variations in isolation. Reject an invalid placeholder form before a release rather than allowing a help-rendering problem. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
19. Sequences of anonymous values
How it works. Core.Command supports Anons combinators for sequences and non-empty sequences. A repeated positional input needs a clear explanation of its minimum and ordering. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A command that accepts several catalogue IDs is different from one that takes a single comma-separated value. Provide two tested invocations that reveal the actual tokenization. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Test zero, one and several arguments and note which become a list. Make the reader’s interpretation match the function’s input type. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
20. Negative numeric positionals
How it works. Core.Command documentation warns that a negative anonymous integer can be mistaken for a flag. The built-in -anon mechanism can force a leading-dash string to be treated as anonymous input in relevant versions. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A guide that allows a negative offset should show the exact tested method rather than assume a bare -1 always works. Explain the conflict between flags and positional data. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Run -1 with and without the documented protective syntax. Capture the parsed number or error in a safe harness. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
21. Escape and end-of-options handling
How it works. Some Command.Param facilities collect remaining tokens without further parsing, such as escape_anon. This is useful for wrappers and pass-through tools where a subsequent token could start with a dash. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Show the dividing point between options for the current command and arguments delivered to a child application. Avoid inventing POSIX double-dash behavior without checking the exact interface. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Test one forwarded argument that looks like an option and one with spaces. Check the received string array at the target handler. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
22. Group body when no child is supplied
How it works. Command.group can supply a body for the case where no subcommand is given. Without that, a user may see help or an error depending on the program’s configuration. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A translated introduction should not claim that simply running catalog performs search when the group only lists commands. Show the zero-argument behavior explicitly. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Invoke the group without a child and compare with the specific search child. Document the difference and required next action. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
23. Order of subcommands in help
How it works. Command.group has configuration for preserving subcommand order. Help organization influences how easily a reader can find a task, especially with many verbs. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Put high-frequency safe commands first when the application supports that choice, and organize descriptions consistently across languages. Do not change routing merely to change visual order. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Generate help and inspect whether the selected order actually appears. Check that a missing or hidden command is not caused by the presentation layer. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
24. Subcommand name hyphen rule
How it works. The documented group API rejects underscores in subcommand names. A translator who replaces hyphens with underscores can create an invalid command declaration, not just a different spelling. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Keep syntax restrictions in developer-facing notes and show only valid, registered command names to general readers. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Build a small invalid-name test to demonstrate the restriction, then replace it with the accepted hyphenated spelling. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
25. Help and recursive help
How it works. Core.Command offers command help and supports recursive help for command hierarchies. The exact switches and output format should be read from the installed version rather than guessed from another CLI framework. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A user who wants a particular nested option should be shown how to request help for that child instead of scrolling through every unrelated command. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Capture root, child and recursive help. Check legibility, useful navigation and whether the output accurately describes the executable route. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
26. Completion is a separate interface
How it works. Core.Command supports shell completion in its command system. Completion candidates are not prose translations: they must correspond to genuine paths, flags and accepted values. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. If a shell suggests a child command, it must be invocable. Descriptions can be localized for comprehension, while actual candidates should remain consistent with parser registration. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Exercise completion for partial commands and ambiguous flag prefixes in the supported shell environment. Reject candidates that point to no registered route. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
27. Parsing versus running
How it works. The command system distinguishes input parsing from executing the unit-returning command body. In particular, validation that happens during parsing can lead to help context, while runtime failures may not. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Explain whether a complaint is caused by invalid syntax, invalid content or failure to read a record. The remedy differs, and a translation must preserve the distinction. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Trigger each failure type and compare stdout, stderr and exit status. Do not promise that changing a flag fixes a missing file. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
28. when_parsing_succeeds hook
How it works. Command.run includes a hook invoked after arguments have parsed but before the handler executes. It can support safe logging of accepted invocations without logging rejected input as completed work. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. A localized status message should not say that a search succeeded merely because parsing succeeded. Describe this stage as accepted parameters, not completed task. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Use a test handler that prints its execution marker after the hook. Verify the sequence for a success and for an application-level failure. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
29. Version and build information
How it works. Command.run supports explicit version and build information. A guide must avoid mistaking the translation catalog version for the executable release version. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. When documenting a parser feature, attach the relevant library and application version, because upstream APIs and default help formats evolve. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Compare the released binary’s version output to the build tested for localization. Do not publish universal claims based on one outdated snippet. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
30. Programmatic argv tests
How it works. Passing controlled argv to Command.run can make tests reproducible and separate parsing behavior from shell quoting behavior. This is valuable when multilingual failures seem inconsistent. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Write test cases for a Unicode query, required flag, bad number and missing argument. Only after core parsing passes should shell-specific entry-point tests be added. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Record expected parsed values, observed outputs and errors. Repeat against the package artifact to detect build-dependent differences. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
31. Nested executable dispatch
How it works. Core.Command provides exec integration for command trees that delegate to other executables. The source documentation warns about recursive help and completion with non-Command children. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Do not use a destructive helper executable as a demonstration of recursive help. A wrapped external program may execute unexpectedly when traversal is requested. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Test nested help only against harmless known commands. Document exact boundaries between the parent program and delegated child. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
32. Path and system argv differences
How it works. Executable paths and process argument handling vary across operating systems. A help string that assumes one shell or filesystem can break even though its translation is accurate. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Use a fixed read-only catalogue sample and platform-specific invocation instructions when necessary. Include paths with spaces and non-ASCII characters. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Observe argv at the OCaml boundary in every supported environment. Fix shell examples when values are split before the parser sees them. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
33. Unicode and terminal width
How it works. UTF-8 text can be valid while terminal rendering misaligns columns or displays bidi sequences unexpectedly. Correctness requires both visible help and accurately received argument bytes. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Test accented Latin strings, CJK queries and right-to-left explanatory text; isolate literal command tokens as code to protect copy and paste. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Compare real terminal renders at narrow widths, then paste the documented command. A screenshot alone cannot verify byte-for-byte executable syntax. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
34. Fallback language design
How it works. An application can select different summary or readme strings based on a resource table, but resource lookup and fallback behavior must be explicitly implemented by the program. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Choose a stable default language and keep technical tokens literal when a region-specific catalog is missing. Prefer complete fallback help over partially translated fragments. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Simulate an unavailable locale. The user should still identify valid commands, argument grammar and recovery instructions. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
35. Structured output stability
How it works. If a CLI emits JSON or tabular data, localized human headings should not alter machine-consumed keys unless a separately versioned output contract explicitly permits it. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Teach the difference between display labels and field names. A bilingual guide should not translate a JSON key that automation scripts still depend on. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Compare machine-readable output across languages and verify schema identity. Keep the human help translation as a separate presentation layer. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
36. Independent reader acceptance
How it works. A translation that reads naturally but cannot guide an unfamiliar person through a real invocation is incomplete. The final test must be a task, not a grammar discussion. That is the boundary between what the parser guarantees and what user-facing educational text must explain.
Worked reader decision. Ask readers to run search with a query, set a supported limit, interpret a failure and request child help without consulting source code. Give a command the user can copy and identify each token that cannot be freely translated.
What to test. Observe hesitation, repair the exact instruction and repeat. Preserve the reproducible command alongside its localized explanation. Record the actual input, locale, executable version, parsed result and any error. Where the behavior depends on configuration, describe that dependency explicitly rather than making a universal claim.
Repair cases for multilingual terminal users
A diagnostic is useful when it identifies which layer failed and what the reader can do next. These cases are intentionally different: some concern grammar, others documentation, completion, runtime execution, operating-system behavior or data contracts.
Case 1: A shortened flag stops working
What is happening. A newly introduced similarly named flag can make the old prefix ambiguous. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Teach full flag names and test the exact release rather than assuming earlier prefix behavior persists. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 2: A translated subcommand is rejected
What is happening. Descriptions and registered group names have been confused. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Show the actual child name or add a properly tested alias after collision review. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 3: A required value seems optional
What is happening. The prose does not match Command.Flag.required or positional declarations. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Run with the value omitted and rewrite the opening instruction to describe the real requirement. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 4: A negative integer looks like an option
What is happening. The parser sees a leading dash where a flag might begin. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Test the documented -anon mechanism and explain the exact supported invocation. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 5: A placeholder is copied literally
What is happening. The user has not been told that QUERY is replaceable. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Separate literal tokens from example data and show a filled-out command. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 6: Child help does not match root help
What is happening. A command’s readme or summary differs from the registered group. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Render both views from the same build and correct the localized source of truth. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 7: An underscore breaks a command name
What is happening. The Core.Command group API restricts child names. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Use a valid hyphenated registration and avoid translating the token into invalid syntax. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 8: A zero-argument group surprises users
What is happening. The group has no default body, or a body they did not expect. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Show the no-child behavior and point users to a safe explicit child command. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 9: A numeric string rejects a comma
What is happening. Arg_type grammar and locale display conventions differ. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Document the accepted invariant input form and distinguish it from formatted output. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 10: A runtime error displays no help
What is happening. The failure occurred after parsing and outside parser validation. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Explain the domain error and give a recovery action instead of treating it as a flag typo. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 11: Help traversal triggers a child executable
What is happening. The command tree delegates via exec to a non-Command program. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Limit recursive help tests to harmless known children and audit external dispatch. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 12: Completion offers ambiguous choices
What is happening. Abbreviations and candidate names are no longer unique. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Regenerate completion from the installed grammar and prefer full registered names. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 13: A quoted query is split
What is happening. The shell processes arguments before the OCaml parser. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Test shell-specific quoting and inspect the actual argv array. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 14: An unknown locale shows missing text
What is happening. The program did not supply a complete fallback resource. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Return stable default summaries and examples rather than blank descriptions. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 15: JSON fields change with language
What is happening. Display localization has leaked into serialized output. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Keep stable machine field names and translate labels in a separate human-readable mode. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Case 16: A reader cannot find search
What is happening. An accurate command is buried under long introductory content. The same visual symptom can conceal a different root cause in another build or shell, so avoid treating a translated screenshot as final proof.
Repair and evidence. Move a valid invocation and expected result to the beginning and retest independently. Repeat the original failure and the corrected invocation against the installed release. Capture the exit status and the received argument values; successful recovery is the standard.
Frequently asked questions
Is Core.Command a translation package?
No. It is a command-construction and parsing framework. Developers supply translated summaries, readme text, examples and any resource selection policy. Pair this answer with a runnable example tied to the current package version, so readers can act instead of inferring behavior from terminology alone.
Should new applications use Command.Spec?
Prefer the modern Command.Param approach described in current documentation; Command.Spec is identified as the old interface. Always follow the installed version. Pair this answer with a runnable example tied to the current package version, so readers can act instead of inferring behavior from terminology alone.
Why can a short flag become invalid?
Without full_flag_required, unambiguous prefixes may be accepted. A new similarly named flag can make a once-unique prefix ambiguous. Pair this answer with a runnable example tied to the current package version, so readers can act instead of inferring behavior from terminology alone.
Can anonymous argument placeholders be localized?
Explanations can be translated, but parser metadata must remain syntactically valid and users must distinguish literal tokens from replaceable values. Pair this answer with a runnable example tied to the current package version, so readers can act instead of inferring behavior from terminology alone.
What if a positional number is negative?
Test the framework’s documented handling of dash-prefixed anonymous values, including -anon where appropriate, rather than assuming plain -1 is accepted. Pair this answer with a runnable example tied to the current package version, so readers can act instead of inferring behavior from terminology alone.
Do summaries and readmes do the same job?
A summary gives quick identification. A readme supplies longer task explanation. Both should describe actual behavior and avoid contradicting parser metadata. Pair this answer with a runnable example tied to the current package version, so readers can act instead of inferring behavior from terminology alone.
Why test argv and shell commands separately?
Controlled argv tests isolate the parser; real terminal tests add quoting, encoding and shell expansion behavior that happens before the process starts. Pair this answer with a runnable example tied to the current package version, so readers can act instead of inferring behavior from terminology alone.
How do we test error translation?
Induce missing, malformed and runtime failures separately, record the message owner, and verify that a target-language reader knows the next valid action. Pair this answer with a runnable example tied to the current package version, so readers can act instead of inferring behavior from terminology alone.
Will changing language translate command names?
Not unless the application registers new names or aliases. Stable command identity is usually the safest cross-language documentation policy. Pair this answer with a runnable example tied to the current package version, so readers can act instead of inferring behavior from terminology alone.
What counts as release-ready?
An unfamiliar reader can discover help, choose a real subcommand, supply valid input and recover from a typo using the packaged application. Pair this answer with a runnable example tied to the current package version, so readers can act instead of inferring behavior from terminology alone.
Four-week learning and release plan
Week 1 — map the command grammar
Pin the OCaml and Core versions, create a harmless catalogue search, and record Command.basic, group, Param flags and anonymous arguments. Test missing and malformed inputs before any translation. Keep exact accepted route names visible in a reference sheet. At the end of the week, preserve one proof of a successful task and one proof of meaningful error recovery in each supported language.
Week 2 — create language-aware explanations
Translate summaries, longer readmes, examples and error-recovery guidance with a defined fallback. Preserve real tokens, type grammar and machine output keys. Review how query placeholders and numeric defaults will be understood by someone unfamiliar with OCaml. At the end of the week, preserve one proof of a successful task and one proof of meaningful error recovery in each supported language.
Week 3 — test boundaries and packaging
Exercise abbreviated flags, full_flag_required, negative anonymous values, Unicode inputs, missing values, nested help and completion. Capture process outputs and repeat in the binary built for release, rather than relying on editor-local execution. At the end of the week, preserve one proof of a successful task and one proof of meaningful error recovery in each supported language.
Week 4 — observe independent completion
Ask a target-language reader to choose the search subcommand, pass a query, vary a limit and recover from a malformed option. Revise the specific misunderstanding, rerun the test and establish a rule that any parser change reopens language review. At the end of the week, preserve one proof of a successful task and one proof of meaningful error recovery in each supported language.
Conclusion: what correct localization demonstrates
The reader’s final test is simple: without reading the OCaml implementation, can they identify the proper command, supply a valid query, understand the limit and repair an invalid invocation? Good translation keeps accepted input and human explanation connected while preserving the machine contracts that scripts and operators depend upon. A route, a translated description and a tested result must describe one consistent application.