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 | 8640 — Ruby dry-cli Localization, Command Registry, Arguments, Options, Help and Error QA

Ruby dry-cli localization means making a Ruby command-line application’s commands, option help, required arguments, examples and error recovery understandable in multiple languages while keeping the executable interface reliable. This dry-cli tutorial explains the registry, Dry::CLI::Command, argument and option declarations, command callbacks and the difference between language for humans and tokens for the shell. It is intended for teams releasing Ruby gems and internal tools to international users.

Imagine ArchiveLedger, a small Ruby utility used by archivists to validate inventory CSV files. A colleague in Spain searches for how to translate dry-cli help, another in Japan needs to understand a missing required argument, and an automated job still calls archiveledger inspect inventory.csv –dry-run. If translators replace the literal inspect command in the copyable example, the job and the documentation disagree; if the dry-run explanation overpromises, a user may unintentionally write a report.

The quick rule is to keep the command registry and option names stable, translate human-facing desc and example text where the implementation can select it, and compare actual command behavior under each locale. dry-cli’s documented API separates registered commands from arguments, options and their descriptive fields, but translating those descriptions does not automatically translate every error created by the library or the shell. We begin with that boundary and move to step-by-step testing.

Quick answer — how to localize Ruby dry-cli safely

  • Keep registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior exact in runnable examples and program behavior.
  • Translate command descriptions, argument :desc and option :desc metadata, examples, user-facing messages, help guidance and app-controlled error wording in a controlled language layer.
  • Distinguish library-generated text from messages owned by the application.
  • Pin and inspect the installed Ruby dependencies before relying on a public example.
  • Test valid commands, missing values, invalid options and unsafe side-effect claims.
  • Capture real stdout, stderr and exit status; compare typed outputs instead of translated strings.
  • Test Unicode filenames, narrow terminals, right-to-left explanations and copied commands.
  • Record a supported-language fallback and ask native speakers to complete a real task.

Chapter 1 — What the command-line interface actually does

A command-line interface is a compact language. It combines a program name, selected action, options and data supplied by the reader. In Ruby dry-cli, Dry::CLI::Registry registers commands; Dry::CLI::Command declares desc, argument, option and example metadata; command classes implement call; Dry::CLI.new(registry).call dispatches the executable. This arrangement is valuable because the program can recognize the intended operation without interpreting an entire natural-language sentence. It is also why careless translation is risky: replacing a recognized command with a fluent but unimplemented synonym is equivalent to changing the program, not improving its documentation.

Begin with a task the reader already understands: ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report. The example task is archiveledger inspect inventory.csv –dry-run. Before translating anything, identify the input file, the executable tokens, the expected result and possible side effects. A professional guide is useful when it answers what will change, what will not change, how to confirm success, and what happens if a step fails. Those four questions are more important than showing every optional switch on the first screen.

Chapter 2 — Separate executable identity from language

The simplest reliable distinction is between a machine token and a human description. registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior belong to the interface contract. command descriptions, argument :desc and option :desc metadata, examples, user-facing messages, help guidance and app-controlled error wording are candidates for localization, provided the chosen software architecture can display the translated text. A filename or number is usually data, which needs its own validation and formatting policy. The fact that all three may appear in one help line does not make them interchangeable.

Create a small inventory with columns for the visible string, where it originates, who owns it, whether users must type it and what tests protect it. For example, a translated phrase can sit beside –help, while –help itself remains literal. Reconfirm where the string is actually rendered: command help, validation error, progress output, a manual page, a generated completion script or a copied example. A change to a help paragraph should not need to rewire parsing.

Chapter 3 — A small version-aware technical example

The following Ruby excerpt is a compact illustration of the code boundary. It is not an invitation to run unreviewed operations against real records. Put equivalent code in a disposable project, pin the library version and test with sample inputs. If your installed package differs from the cited documentation, inspect its public API first. Some applications wrap libraries with their own helper layers, so a team’s production command may accept different options from this educational example.

Read the example in two directions. First, follow the value typed by a user through the parser and into the program’s action. Second, find which strings describe that process to the reader. Translation belongs primarily in the second path, while validation and successful execution belong in the first. If the input path or option set changes when only the description language changes, that is evidence of a behavioral regression.

require "dry/cli"
module ArchiveCommands
  extend Dry::CLI::Registry
  class Inspect < Dry::CLI::Command
    desc "Inspect a local archive inventory"
    argument :path, required: true, desc: "CSV inventory path"
    option :dry_run, type: :boolean, default: false, desc: "Do not write a report"
    def call(path:, dry_run: false, **)
      puts "Inspecting #{path} (dry run: #{dry_run})"
    end
  end
  register "inspect", Inspect
end
Dry::CLI.new(ArchiveCommands).call

Chapter 4 — Help must form a useful path, not a dictionary

A good help page begins with purpose, then a minimum safe invocation, then common arguments, then the next action after success or failure. It should not force a novice to decode a complete reference table before trying a single harmless example. Show a real path format, state whether it refers to a file or folder, identify default behavior, and explain what the command will write. Use short option descriptions for scanning, followed by detailed discussion for ambiguous or risky actions.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, start with a local fixture and a clear observation such as a row count, a checked schema, or a summarized warning. Present a command in code formatting and keep its spelling stable. The surrounding explanation can adapt to local grammar, but the command cannot change unless the program really supports another syntax. Think of translated help as a trustworthy user journey rather than a list of words that happen to be equivalent.

Chapter 5 — Choose a locale without changing the task

A multilingual application needs to determine the language before it constructs human-facing output. Depending on the application’s design, a documented flag, environment variable or configuration setting may be appropriate. Use predictable fallbacks and support an explicit list of locale tags. A user who requests Japanese help should not accidentally run a different operation, write to a different directory or grant broader permissions. Locale selection is a presentation decision until the application explicitly documents a different contract.

Avoid assuming that a low-level parser library supplies a ready-made translation catalog. The technical reference may document description strings without providing message extraction, fallback or plural handling. A practical architecture keeps a catalog keyed by stable identifiers and lets application code choose complete sentences. The key is never itself a command flag. Record which messages still come from Ruby dry-cli so readers and maintainers do not confuse a partial translation with total support.

Chapter 6 — Make errors actionable, accurate and safe

An error message should answer what failed, where the user can look and which next action is safe. Missing arguments, unknown switches, unsupported values, unreadable files and malformed contents are different failures. Some are rejected by the parser before the application starts; others occur later. Translating them into one generic ‘operation failed’ sentence removes critical information. Where messages are controlled by a dependency and lack a documented translation hook, a localized application explanation can be safer than brittle rewriting of raw dependency output.

Never print a successful-completion message after a command that failed. Compare exit status and side effects as well as displayed wording. When errors mention sensitive paths, identifiers or internal details, avoid exposing secrets in the guise of helpful localization. Show enough context for recovery without turning a CLI diagnostic into a data leak. The correct reader-facing wording often includes a valid minimal invocation and a pointer to a local log reference.

Chapter 7 — Treat Unicode and typography as engineering issues

Translation changes the shape of text. French descriptions may be longer, Japanese glyphs may occupy multiple terminal display columns, Arabic paragraphs may mix right-to-left text with left-to-right options, and filenames can contain combining marks or spaces. A string that looks fine in a browser may be unreadable or uncopyable in a shell. The program’s data representation, stdout encoding, terminal font and renderer are separate boundaries worth checking.

Keep executable tokens in code formatting, preserve ASCII punctuation where it has syntax meaning, and test copied commands as bytes. Check a narrow terminal and a normal terminal, stdout piped into a file and errors written to stderr. A correct translation should help a reader act, not merely look attractive in the translator’s editor. Confirm the supported environments rather than claiming universal Unicode behavior from the language runtime alone.

Chapter 8 — Check real outcomes, not just translated snapshots

A screenshot proves that text appeared. It does not prove that an operator selected the correct input, that the parser produced the intended value or that a command avoided an unpromised write. Build fixtures for a valid invocation, missing required input, malformed value, unknown option, Unicode path and a permissions failure. Compare parsed outputs, exit code and file effects across languages. The content of the sentence may change, but the operational result should stay consistent.

Native-language testing adds a different kind of evidence. Ask a reader to explain what the command will do before executing it, which part of the example is a placeholder, and what the next step is after a failure. A reviewer who can translate every word but selects the wrong operation has found a usability defect. Use that observation to fix help ordering, not just vocabulary.

Chapter 9 — Ruby dry-cli design decisions that change translation quality

1. A command registry is a navigation map

The registry creates a relationship between a literal command path and a Ruby command class. A registered name such as inspect is not merely a phrase for display; it is a token interpreted by the CLI. You can explain it in several languages without redefining it. When there are nested commands, document the full chain instead of treating every leaf as a root command.

To make this decision useful for a real reader, first identify which part of archiveledger inspect inventory.csv –dry-run is a typed token, which part is an input value, and which part is merely explanatory. Record the behavior before revising the wording. When a localized page makes a promise, turn that promise into a fixture: invoke a valid sample command, inspect the structured result and check that side effects match the guide.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

2. Descriptions should answer user questions

The desc class method describes what a command does; an argument’s desc explains a value; an option’s desc explains a switch. Treat these as three editorial jobs rather than copying the same sentence into all three fields. The command description tells readers what outcome to expect, the argument description explains the input’s shape, and the option description explains the changed behavior.

This issue usually appears when source code, an English help screen and a translator’s draft are reviewed separately. Put them side by side. Ask the maintainer to show what Ruby dry-cli actually accepts, ask the language reviewer to describe the intended operation without consulting English, and let the test suite arbitrate differences. A good edit survives both kinds of review.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

3. Required arguments and keyword calls

A required argument is not just a warning for the help screen; it shapes how the command is called. For a command with argument :path, required: true, def call(path:, …) must receive a valid value. A translation must not imply that the argument can be omitted or that an example placeholder is the literal path. Test the missing-argument branch against a disposable command invocation.

A small example is better than a sweeping claim. Build a disposable input, run it once successfully and then change only the display language. If the parsed values or selected files differ, the localization boundary has moved too far. If behavior matches but the reader cannot explain what happened, the prose is still not adequate. Both outcomes deserve independent fixes.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

4. Options have both identity and affordance

An option declaration has a symbol name and may have aliases, defaults and type information. A translated description should explain the value of using it rather than invent a new spelling. A short alias such as -p and a long form such as –port are accepted only if declared. When a change would improve discoverability, propose it to the developer as an API change, not a copy edit.

Keep a note of ownership and version. If the wording comes from library help generation, check the installed public API. If the wording comes from the application, change it with a catalog key and a semantic test. Never translate an internal identifier simply because it looks English, and never leave a user without an explanation because a technical token must remain stable.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

5. A class method is not a translation catalog

The methods desc, argument and option accept strings in command definitions. That does not automatically mean the library ships an application-wide locale resolver. A multilingual product may construct command classes or provide app-controlled text before rendering help; design that layer deliberately and test it against the exact library version. Do not claim a built-in method that the documentation does not show.

To make this decision useful for a real reader, first identify which part of archiveledger inspect inventory.csv –dry-run is a typed token, which part is an input value, and which part is merely explanatory. Record the behavior before revising the wording. When a localized page makes a promise, turn that promise into a fixture: invoke a valid sample command, inspect the structured result and check that side effects match the guide.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

6. Subcommands change context

A command may contain other commands, and a token can have a different meaning depending on its parent. For example, archiveledger collection inspect is different from a root inspect. Print the whole path in examples and explain which flags belong at which depth. Capture both root and leaf help screens, because nested navigation can hide an otherwise accurate translation.

This issue usually appears when source code, an English help screen and a translator’s draft are reviewed separately. Put them side by side. Ask the maintainer to show what Ruby dry-cli actually accepts, ask the language reviewer to describe the intended operation without consulting English, and let the test suite arbitrate differences. A good edit survives both kinds of review.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

7. Examples should be runnable and harmless

dry-cli supports examples associated with commands. A useful example includes a real-looking local filename and a safe operation, then labels it illustrative and explains how to replace the placeholder. Use only switches implemented by the example command. A copyable example must not contain typography substitutions that turn ASCII hyphens or quotation marks into visually similar but invalid characters.

A small example is better than a sweeping claim. Build a disposable input, run it once successfully and then change only the display language. If the parsed values or selected files differ, the localization boundary has moved too far. If behavior matches but the reader cannot explain what happened, the prose is still not adequate. Both outcomes deserve independent fixes.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

8. Boolean options are not permissions

A dry_run Boolean may tell the application to avoid a write, but the option declaration alone does not enforce that property. Application code does. Localizing the promise ‘does not modify files’ therefore requires side-effect tests, not a translation review. For ArchiveLedger, consider reports, temporary files, caches and audit records separately.

Keep a note of ownership and version. If the wording comes from library help generation, check the installed public API. If the wording comes from the application, change it with a catalog key and a semantic test. Never translate an internal identifier simply because it looks English, and never leave a user without an explanation because a technical token must remain stable.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

9. Callbacks and side effects

A command’s call implementation is where business effects occur. Translate messages from this level with full awareness of whether the command has begun, finished or failed. An optimistic ‘Complete’ printed before a file operation can be misleading. A localization layer should separate a progress message from a success message and from a recoverable problem.

To make this decision useful for a real reader, first identify which part of archiveledger inspect inventory.csv –dry-run is a typed token, which part is an input value, and which part is merely explanatory. Record the behavior before revising the wording. When a localized page makes a promise, turn that promise into a fixture: invoke a valid sample command, inspect the structured result and check that side effects match the guide.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

10. Ruby encodings and shell arguments

Ruby strings and filenames can contain non-ASCII characters, but not every user’s terminal or file system presents them identically. Check encoding in the executable environment instead of making broad claims about every platform. A path typed in Japanese may reach Ruby correctly but be hard to copy back from a badly wrapped translated error.

This issue usually appears when source code, an English help screen and a translator’s draft are reviewed separately. Put them side by side. Ask the maintainer to show what Ruby dry-cli actually accepts, ask the language reviewer to describe the intended operation without consulting English, and let the test suite arbitrate differences. A good edit survives both kinds of review.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

11. Release gem versions responsibly

The dry-cli guide and generated API references may describe different maintained versions. Pin the exact gem in the Gemfile.lock, run behavior tests against it and cite the version used for a public example. If an option signature is added or changed later, update the test fixture rather than silently assuming that older installations behave the same way.

A small example is better than a sweeping claim. Build a disposable input, run it once successfully and then change only the display language. If the parsed values or selected files differ, the localization boundary has moved too far. If behavior matches but the reader cannot explain what happened, the prose is still not adequate. Both outcomes deserve independent fixes.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

12. Use a modest locale selector

An application can choose display language from a documented configuration setting or environment variable, with explicit fallback. The locale must not secretly change the meaning of –dry-run, choose a different inventory, or add permissions. Store the resolved language in request-level context where feasible rather than a mutable global that leaks into another command execution.

Keep a note of ownership and version. If the wording comes from library help generation, check the installed public API. If the wording comes from the application, change it with a catalog key and a semantic test. Never translate an internal identifier simply because it looks English, and never leave a user without an explanation because a technical token must remain stable.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

13. Structured failures beat decorative prose

A ‘missing path’ failure, an invalid CSV schema and a file permission error need distinct recovery instructions. A single translated message that says ‘something went wrong’ may be grammatical but useless. Keep technical failures identifiable in tests and logs while translating the action a person should take next.

To make this decision useful for a real reader, first identify which part of archiveledger inspect inventory.csv –dry-run is a typed token, which part is an input value, and which part is merely explanatory. Record the behavior before revising the wording. When a localized page makes a promise, turn that promise into a fixture: invoke a valid sample command, inspect the structured result and check that side effects match the guide.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

14. Make reader training task-based

Most readers want to do something: validate a file, inspect a warning or learn how a report is written. Organize documentation by completed tasks and common repairs, followed by a reference table. A person who does not know the Ruby code should still be able to distinguish a required file path from an optional flag and verify the result.

This issue usually appears when source code, an English help screen and a translator’s draft are reviewed separately. Put them side by side. Ask the maintainer to show what Ruby dry-cli actually accepts, ask the language reviewer to describe the intended operation without consulting English, and let the test suite arbitrate differences. A good edit survives both kinds of review.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the acceptance test is concrete: the operator must be able to follow archiveledger inspect inventory.csv –dry-run, tell which output is a preview or final result, and recover from an invalid invocation. The reviewer should record the exact Ruby runtime and dependency versions used. This turns the topic from an abstract translation preference into a verifiable instruction that can be maintained through future releases.

Chapter 10 — Eighteen realistic troubleshooting investigations

The cases below describe different ways a Ruby dry-cli translation can be polished but wrong. Each has a symptom, a repair and a verification step. They are examples for training and testing, not claims about defects in the library itself. Use fictitious data, preserve any real system’s access controls and rerun relevant checks when the underlying package is upgraded.

Investigation 1: Command name rewritten

What the operator encounters: A translator replaces inspect in the invocation with the natural-language word for inspection. dry-cli’s registry continues to recognize only inspect. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Restore the registered command token in the code block and add a translated parenthetical explanation. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Run the published command with the correct spelling in every locale. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 2: Argument translated as a literal

What the operator encounters: The help says PATH and a reader enters PATH instead of a real file; the error looks like a file system problem. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Give a concrete sample inventory.csv, identify PATH as a placeholder and show safe shell quoting for spaces. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Test an existing local CSV and a missing filename separately. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 3: Boolean flag misrepresented

What the operator encounters: A description calls –dry-run a universal preview, but the implementation still writes a temporary report. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Enumerate application side effects and narrow the promise or repair the command. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Compare a directory snapshot before and after an invocation. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 4: Alias not declared

What the operator encounters: A French help page promotes -n as an abbreviation for –dry-run even though the Ruby option declaration has no such alias. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Either remove -n from copyable examples or implement and test an explicit alias. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Capture help and invoke both supported and unsupported spellings. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 5: Unknown option error

What the operator encounters: A German user supplies –dryrun instead of –dry-run and sees a generic message with no useful recovery. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Preserve the unknown token verbatim and explain the valid spelling as a next step. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Assert the command fails with no report output. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 6: Nested command mismatch

What the operator encounters: A localizer describes collection inspect as root inspect, omitting the parent segment of the registered route. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Print the complete command path and place each option beneath its actual command. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Test root help, collection help and the leaf invocation. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 7: Unicode filename interpolation

What the operator encounters: A file named 台帳.csv is displayed as escaped characters or broken bytes in a Ruby warning. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Inspect terminal encoding, Ruby string handling and log formatting; keep path data untouched. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Copy the exact filename from the failure message and retry. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 8: Wrong error ownership

What the operator encounters: A raw exception from a CSV parser is translated as if it were dry-cli’s missing argument error. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Catch app-owned failures at the proper layer and describe the corrective action without faking a parser feature. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Use separate fixtures for absent args and malformed CSV. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 9: Dangerous example

What the operator encounters: An example shows a write command against a production-looking directory without explaining side effects. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Replace with a disposable fixture and a tested read-only command; label any write as explicit. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Check example against a sandbox directory with no real customer data. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 10: Help width overflow

What the operator encounters: A longer Polish option description wraps under the wrong option and users associate it with another flag. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Test terminal widths and formatting, retaining a clear semantic label before long supporting prose. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Capture 80-column and 40-column output with Unicode characters. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 11: Trailing arguments

What the operator encounters: The guide tells users to append extra filenames, but the defined command accepts only one required path. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Document the actual accepted argument shape or extend the command after a deliberate compatibility review. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Pass one, two and zero positional values to the released command. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 12: Default shown incorrectly

What the operator encounters: A translator writes that a flag defaults to true, while the Ruby declaration uses false. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Generate descriptions from a reviewed options table; check declared defaults before translation. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Assert the no-flag invocation and the explicit flag invocation. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 13: Exit code hidden

What the operator encounters: An application wrapper prints success after a command raised an expected validation failure. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Put localized banners after successful return, and let failure branches retain non-zero status. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Compare process exit status, output text and filesystem state. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 14: Shell quotes altered

What the operator encounters: A Japanese typographic edit changes straight quotes into smart quotes in a copyable command line. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Use code formatting for literal shell fragments and translate only the surrounding explanation. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Paste the exact example into supported shells under a test directory. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 15: Stale registry

What the operator encounters: The documentation still lists a removed subcommand that was present in an earlier gem release. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Derive the public command list from the built application used by the release, not memory. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Diff root help between pinned releases and update the published instructions. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 16: Localization leaks across commands

What the operator encounters: One command changes a global locale value and a second command unexpectedly prints the first language. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Use explicit locale selection and clean isolation, particularly in test runners or long-running Ruby processes. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Execute commands sequentially with different locales and verify output separation. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 17: Inaccurate completion claim

What the operator encounters: A translated page says dry-cli has automatic shell completion, but the particular packaged application does not supply it. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Document completion only if the project actually builds and ships tested scripts; distinguish library capabilities from app behavior. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Install the released gem in a clean environment and test the claimed setup. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Investigation 18: Ambiguous report terminology

What the operator encounters: A translated message calls a validation list a finalized audit, although no authorized reviewer signed it. This matters because help text and a working parser can disagree even when each looks coherent in isolation. A human may follow instructions correctly and still make the wrong call, which is a documentation defect as much as an implementation problem.

A safe correction is specific: Use distinct terms for draft findings, computed results and approved records; preserve the approval boundary. Keep the change limited to the right layer. Do not alter registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior in response to a purely linguistic problem, and do not hide actual application defects beneath nicer wording.

Proof before release: Ask a target-language reviewer to explain the difference without reading English. Then repeat the attempt under the default language and at least one translated locale. Compare the result class, stderr and exit status, and inspect whether any output file, report or cache was changed. Mark a test as passing only when the technical result and the reader’s understanding agree.

Chapter 11 — A multilingual acceptance matrix

  • English baseline: Use it to establish actual flags, commands, defaults, success behavior, and known error variants. Record this as a reference trace, not as the one correct grammatical form for every locale.
  • French: Look for long descriptions, distinction between a command and a suggestion, correct treatment of filenames and quantities, and errors that say whether a file is absent or invalid.
  • German: Check compound nouns, table widths, longer help lines and precise distinction between validation and execution. Confirm that examples still contain exact option names.
  • Japanese: Check CJK terminal cell widths, natural task explanations, non-Latin filenames, copied quotes and an unambiguous explanation of values versus placeholders.
  • Arabic: Check right-to-left prose beside left-to-right program tokens, numerals and paths. Verify that copied commands preserve byte order and the underlying command has not been visually rearranged.
  • Hindi and Tamil: Test complex-script rendering, longer instructional sentences, font availability and clear presentation of syntax fragments. Do not use romanization as a substitute for genuine localized guidance without product justification.
  • Spanish and Portuguese: Check regional variations, units, number formatting and whether translated verbs imply a read-only check or a write. Numeric argument syntax must remain what the program actually parses.

The matrix is a set of test questions, not evidence that these locales already ship with Ruby dry-cli. The application owner must say which languages are supported, how they are selected, who reviews them and which environments are in scope. It is better to support a few languages accurately than to advertise many through untranslated dependency errors and untested scripts.

Chapter 12 — Twelve reader-focused practical exercises

Exercise 1: A command registry is a navigation map

The purpose of this exercise is to make a command registry is a navigation map understandable to someone who has not studied the library source. First, have a learner predict the effect of a safe invocation before executing it; write down the predicted input, output and any possible side effects. Then change the display language, not the command, and have a second learner repeat the prediction without reading the first answer. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: The registry creates a relationship between a literal command path and a Ruby command class. A registered name such as inspect is not merely a phrase for display; it is a token interpreted by the CLI. You can explain it in several languages without redefining it. When there are nested commands, document the full chain instead of treating every leaf as a root command. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 2: Descriptions should answer user questions

The purpose of this exercise is to make descriptions should answer user questions understandable to someone who has not studied the library source. Use an intentionally invalid command to examine recovery guidance. Preserve the typed tokens in the report, identify the exact rejection stage, and ask the learner to choose the next permitted action rather than merely translate the displayed error. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: The desc class method describes what a command does; an argument’s desc explains a value; an option’s desc explains a switch. Treat these as three editorial jobs rather than copying the same sentence into all three fields. The command description tells readers what outcome to expect, the argument description explains the input’s shape, and the option description explains the changed behavior. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 3: Required arguments and keyword calls

The purpose of this exercise is to make required arguments and keyword calls understandable to someone who has not studied the library source. Create two local fixtures: one valid and one that violates the condition under discussion. Test each in the base language and a translated language, comparing the parser result and real files, not just the text on screen. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: A required argument is not just a warning for the help screen; it shapes how the command is called. For a command with argument :path, required: true, def call(path:, …) must receive a valid value. A translation must not imply that the argument can be omitted or that an example placeholder is the literal path. Test the missing-argument branch against a disposable command invocation. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 4: Options have both identity and affordance

The purpose of this exercise is to make options have both identity and affordance understandable to someone who has not studied the library source. Review a narrow-terminal rendering and a copied command. Ask the learner to identify which components are executable grammar, which are placeholders and which describe behavior. Then paste the command into a disposable environment and verify the claim. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: An option declaration has a symbol name and may have aliases, defaults and type information. A translated description should explain the value of using it rather than invent a new spelling. A short alias such as -p and a long form such as –port are accepted only if declared. When a change would improve discoverability, propose it to the developer as an API change, not a copy edit. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 5: A class method is not a translation catalog

The purpose of this exercise is to make a class method is not a translation catalog understandable to someone who has not studied the library source. First, have a learner predict the effect of a safe invocation before executing it; write down the predicted input, output and any possible side effects. Then change the display language, not the command, and have a second learner repeat the prediction without reading the first answer. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: The methods desc, argument and option accept strings in command definitions. That does not automatically mean the library ships an application-wide locale resolver. A multilingual product may construct command classes or provide app-controlled text before rendering help; design that layer deliberately and test it against the exact library version. Do not claim a built-in method that the documentation does not show. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 6: Subcommands change context

The purpose of this exercise is to make subcommands change context understandable to someone who has not studied the library source. Use an intentionally invalid command to examine recovery guidance. Preserve the typed tokens in the report, identify the exact rejection stage, and ask the learner to choose the next permitted action rather than merely translate the displayed error. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: A command may contain other commands, and a token can have a different meaning depending on its parent. For example, archiveledger collection inspect is different from a root inspect. Print the whole path in examples and explain which flags belong at which depth. Capture both root and leaf help screens, because nested navigation can hide an otherwise accurate translation. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 7: Examples should be runnable and harmless

The purpose of this exercise is to make examples should be runnable and harmless understandable to someone who has not studied the library source. Create two local fixtures: one valid and one that violates the condition under discussion. Test each in the base language and a translated language, comparing the parser result and real files, not just the text on screen. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: dry-cli supports examples associated with commands. A useful example includes a real-looking local filename and a safe operation, then labels it illustrative and explains how to replace the placeholder. Use only switches implemented by the example command. A copyable example must not contain typography substitutions that turn ASCII hyphens or quotation marks into visually similar but invalid characters. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 8: Boolean options are not permissions

The purpose of this exercise is to make boolean options are not permissions understandable to someone who has not studied the library source. Review a narrow-terminal rendering and a copied command. Ask the learner to identify which components are executable grammar, which are placeholders and which describe behavior. Then paste the command into a disposable environment and verify the claim. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: A dry_run Boolean may tell the application to avoid a write, but the option declaration alone does not enforce that property. Application code does. Localizing the promise ‘does not modify files’ therefore requires side-effect tests, not a translation review. For ArchiveLedger, consider reports, temporary files, caches and audit records separately. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 9: Callbacks and side effects

The purpose of this exercise is to make callbacks and side effects understandable to someone who has not studied the library source. First, have a learner predict the effect of a safe invocation before executing it; write down the predicted input, output and any possible side effects. Then change the display language, not the command, and have a second learner repeat the prediction without reading the first answer. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: A command’s call implementation is where business effects occur. Translate messages from this level with full awareness of whether the command has begun, finished or failed. An optimistic ‘Complete’ printed before a file operation can be misleading. A localization layer should separate a progress message from a success message and from a recoverable problem. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 10: Ruby encodings and shell arguments

The purpose of this exercise is to make ruby encodings and shell arguments understandable to someone who has not studied the library source. Use an intentionally invalid command to examine recovery guidance. Preserve the typed tokens in the report, identify the exact rejection stage, and ask the learner to choose the next permitted action rather than merely translate the displayed error. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: Ruby strings and filenames can contain non-ASCII characters, but not every user’s terminal or file system presents them identically. Check encoding in the executable environment instead of making broad claims about every platform. A path typed in Japanese may reach Ruby correctly but be hard to copy back from a badly wrapped translated error. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 11: Release gem versions responsibly

The purpose of this exercise is to make release gem versions responsibly understandable to someone who has not studied the library source. Create two local fixtures: one valid and one that violates the condition under discussion. Test each in the base language and a translated language, comparing the parser result and real files, not just the text on screen. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: The dry-cli guide and generated API references may describe different maintained versions. Pin the exact gem in the Gemfile.lock, run behavior tests against it and cite the version used for a public example. If an option signature is added or changed later, update the test fixture rather than silently assuming that older installations behave the same way. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Exercise 12: Use a modest locale selector

The purpose of this exercise is to make use a modest locale selector understandable to someone who has not studied the library source. Review a narrow-terminal rendering and a copied command. Ask the learner to identify which components are executable grammar, which are placeholders and which describe behavior. Then paste the command into a disposable environment and verify the claim. In ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, the worked example is archiveledger inspect inventory.csv –dry-run. Use sample inputs only, and keep a record of the version, locale, expected result, actual result and the exact sentence that caused confusion.

The decision at stake is this: An application can choose display language from a documented configuration setting or environment variable, with explicit fallback. The locale must not secretly change the meaning of –dry-run, choose a different inventory, or add permissions. Store the resolved language in request-level context where feasible rather than a mutable global that leaks into another command execution. A reviewer should be able to explain why a misleading translation changes the operator’s decision, not merely say that two sentences sound different. If testing reveals an implementation bug, fix that separately and rerun the language review. A completed exercise leaves a small reproducible proof that the documentation matches the product.

Chapter 13 — Frequently asked questions

Can dry-cli automatically translate every message?

Its documented surface supports human-readable command, option and argument descriptions; that is not a guarantee of end-to-end message catalogs. Build and test your application’s locale strategy instead of assuming an undocumented global switch.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, settle this with a real command and a controlled fixture rather than intuition. A helpful answer names the stable part of registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior, identifies the reader-facing explanation, and shows how to verify the outcome without production data. Where support depends on package version, test the installed release rather than assuming universal behavior.

Should I translate the symbol passed to argument?

No, not casually. The symbol helps define command parameters and Ruby method calls. Translate its visible explanation, and change the symbol only as a deliberate, tested program refactor.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, settle this with a real command and a controlled fixture rather than intuition. A helpful answer names the stable part of registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior, identifies the reader-facing explanation, and shows how to verify the outcome without production data. Where support depends on package version, test the installed release rather than assuming universal behavior.

How do I preserve a stable public CLI?

Keep registered command names and aliases constant, test the same argv tokens under every display language, and treat any new alias as a versioned interface change.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, settle this with a real command and a controlled fixture rather than intuition. A helpful answer names the stable part of registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior, identifies the reader-facing explanation, and shows how to verify the outcome without production data. Where support depends on package version, test the installed release rather than assuming universal behavior.

What belongs in a correct help example?

The full command path, valid flags, real sample input, whether output is created, and an expected observation. Avoid promoting undocumented short options or speculative defaults.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, settle this with a real command and a controlled fixture rather than intuition. A helpful answer names the stable part of registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior, identifies the reader-facing explanation, and shows how to verify the outcome without production data. Where support depends on package version, test the installed release rather than assuming universal behavior.

How do I test missing arguments?

Invoke the command without its required input, assert failure, then inspect the displayed recovery guidance and verify that no report was written.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, settle this with a real command and a controlled fixture rather than intuition. A helpful answer names the stable part of registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior, identifies the reader-facing explanation, and shows how to verify the outcome without production data. Where support depends on package version, test the installed release rather than assuming universal behavior.

What about Japanese and Arabic paths?

Test non-Latin filenames and terminal behavior with the actual Ruby runtime and operating systems you ship, preserving the underlying filename bytes and a copyable display.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, settle this with a real command and a controlled fixture rather than intuition. A helpful answer names the stable part of registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior, identifies the reader-facing explanation, and shows how to verify the outcome without production data. Where support depends on package version, test the installed release rather than assuming universal behavior.

How do I translate app-specific errors?

Distinguish causes first, then write a recoverable action for each. Keep machine-readable identifiers or structured error types stable while translating the surrounding text.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, settle this with a real command and a controlled fixture rather than intuition. A helpful answer names the stable part of registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior, identifies the reader-facing explanation, and shows how to verify the outcome without production data. Where support depends on package version, test the installed release rather than assuming universal behavior.

When should I postpone release?

When a translated example does not run, a failed operation reports success, a ‘no write’ claim is false, or a non-English path cannot be handled in a supported environment.

For ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, settle this with a real command and a controlled fixture rather than intuition. A helpful answer names the stable part of registered command names, Ruby keyword argument identities, accepted option aliases, required argument count and application exit behavior, identifies the reader-facing explanation, and shows how to verify the outcome without production data. Where support depends on package version, test the installed release rather than assuming universal behavior.

Chapter 14 — A four-week implementation and review plan

Week 1: inventory the interface

Capture root help, nested help, sample invocations and errors from the released application. Map every visible message to its owner, list supported commands, record exact dependency and runtime versions, and classify input values separately from strings meant for translation. Choose two real reader tasks. A good result for this week is a short baseline document with no uncertainty about what the program actually accepts.

Applied to Ruby dry-cli, this week’s exit condition must be checked in both code and language. Use archiveledger inspect inventory.csv –dry-run with a disposable fixture, retain the original command spellings and compare the intended operation with the observed result. Do not advance merely because the text sounds polished; advance when a learner can predict and verify what the tool will do.

Week 2: draft and integrate language support

Choose supported locales and a fallback policy. Translate complete tasks, warnings and recovery instructions instead of isolated words, preserving fixed tokens. Connect application-owned strings to catalog keys or another version-appropriate system, and leave library-owned text identified where override support is unavailable. Ask developers to review every promise about writes, permissions, defaults, file formats and errors.

Applied to Ruby dry-cli, this week’s exit condition must be checked in both code and language. Use archiveledger inspect inventory.csv –dry-run with a disposable fixture, retain the original command spellings and compare the intended operation with the observed result. Do not advance merely because the text sounds polished; advance when a learner can predict and verify what the tool will do.

Week 3: behavior and comprehension testing

Run successful and invalid input fixtures under each chosen locale. Compare parsed values, stdout/stderr channels, exit statuses and output effects; also test non-ASCII paths, terminal width and copied code snippets. Ask native-language reviewers to complete the two original tasks without English guidance and record where decisions fail. Correct both functional and wording faults; re-run the baseline tests.

Applied to Ruby dry-cli, this week’s exit condition must be checked in both code and language. Use archiveledger inspect inventory.csv –dry-run with a disposable fixture, retain the original command spellings and compare the intended operation with the observed result. Do not advance merely because the text sounds polished; advance when a learner can predict and verify what the tool will do.

Week 4: publish, monitor and maintain

Finalize a short quick-start, supported-version note, option reference, troubleshooting guide and fallback disclosure. Publish only tested examples, with a release checklist signed by engineering and language reviewers. Keep the command contract versioned, record known limitations and add regression fixtures for defects found during real support requests. A translation is complete when a reader can finish the task safely, not when the catalog has no empty cells.

Applied to Ruby dry-cli, this week’s exit condition must be checked in both code and language. Use archiveledger inspect inventory.csv –dry-run with a disposable fixture, retain the original command spellings and compare the intended operation with the observed result. Do not advance merely because the text sounds polished; advance when a learner can predict and verify what the tool will do.

Chapter 15 — Professional standard and next step

The best multilingual command-line documentation is boring in the most useful sense: the examples execute as written, the parser behaves consistently, the outputs say what happened and the reader knows how to repair a failure. With Ruby dry-cli, translation quality depends on respecting how the framework defines commands and values while giving humans accurate descriptions of those same structures.

Start from one small task in ArchiveLedger, an illustrative utility that checks local archive inventory files and writes an optional verification report, verify it in the default language, translate its complete explanation and test the same action again. Expand to errors, more commands and additional locales only when earlier behavior stays stable. That sequence makes multilingual support maintainable for new contributors, reviewers and users who cannot ask the original developer what a sentence was supposed to mean.

Primary technical references and related translation guides