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 | 8780 — Go ffcli Localization, Command Trees, FlagSet, UsageFunc, Help and Error QA

Go ffcli localization is the discipline of translating command descriptions, usage screens, argument guidance and recoverable errors without changing the flag.FlagSet names and ffcli.Command structure that the executable actually understands. Readers searching for Go ffcli help translation, ShortUsage, ShortHelp, LongHelp, UsageFunc, subcommands, ParseAndRun and Unicode CLI QA need to know how these pieces connect and where application-specific validation begins.

Consider a small logistics utility called routebook that reads local demonstration records. A team uses the same binary in English, Spanish and Japanese while automated jobs still invoke routebook inspect -format json report.txt. The public command name and machine-output keys must remain predictable. A user-facing explanation of the inspect command can be translated; the syntax shown in the actual sample must still work on the version shipped to readers. A translated help screen that breaks scripts is not a successful adaptation.

The practical method is to describe the command tree, keep the flag grammar stable, supply language-appropriate ShortHelp and LongHelp content where the application supports it, distinguish parsing errors from execution errors and test the entire task in clean environments. This guide develops those steps through a small Go example, framework-specific investigations, multilingual terminal quality checks, FAQs and a release plan.

  • ffcli.Command organizes names, help text, flags, subcommands and execution behavior.
  • flag.FlagSet supplies parsed flags; the application still owns many validation and translation choices.
  • UsageFunc permits custom usage generation, but must reflect the actual command structure.
  • Test help, NoExecError, parsing, output compatibility, Unicode and exit behavior across supported environments.

Chapter 1 — From framework behavior to a useful multilingual interface

The ffcli package is deliberately small. It builds declarative command trees over Go’s standard flag.FlagSet and integrates options from the related ff library. Its documented command fields include Name, ShortUsage, ShortHelp, LongHelp, UsageFunc, FlagSet, Options, Subcommands and Exec. This design gives authors visible places to supply reader-facing descriptions without requiring a large external translation framework. It also makes the boundary between executable options and presentation text easy to inspect.

ShortUsage is a compact command signature; the documentation recommends a form containing flags, a command and positional placeholders. ShortHelp appears near subcommand names in parent help; LongHelp provides expanded context; UsageFunc can produce complete usage text. These are different audiences and spaces, not three interchangeable copies of one marketing sentence. An efficient translation gives the short version enough meaning for discovery and the long version enough detail for making a correct choice.

Every command may have its own flag.FlagSet. The flag set holds names, defaults and type-aware parsing behavior, while ffcli selects the terminal command and invokes its Exec function. Developers should decide whether to use flag.ContinueOnError, how to route usage output and how to handle flag.ErrHelp. A language reviewer should not guess these runtime choices from a screenshot. An apparent mistranslation may actually be a mismatch between a parent command and its child’s flag set.

The package documents ParseAndRun as a convenient combined operation; applications can also call Parse and then Run separately. Splitting the phases can be useful when configuration determines which dependencies must be initialized, but it does not automatically improve localization. What matters is that errors from parsing, missing subcommands and command execution reach a consistent, safe, understandable presentation layer. If a root command has subcommands but no executable action of its own, a missing Exec may lead to a documented NoExecError that the application needs to handle.

User-facing translation is not the same as changing the program’s stable interface. JSON keys, subcommand names, environment-variable names, configuration file fields and flags may be relied upon by scripts. Translate explanatory text and supported application messages; make any command alias or schema change a deliberate compatibility decision. Test both an interactive help request and a machine-oriented invocation under each locale so that accessibility gains do not silently break automation.

Chapter 2 — One harmless example, examined carefully

The following Go example shows a single read-only demonstration command with a typed flag set and human-readable help fields. It prints selected arguments and does not perform file operations. The fields are deliberately small so developers can separate the flag name from the description and see where validation and localization would be added.

package main

import (
    "context"
    "flag"
    "fmt"
    "os"
    "github.com/peterbourgon/ff/v3/ffcli"
)

func main() {
    fs := flag.NewFlagSet("routebook inspect", flag.ContinueOnError)
    format := fs.String("format", "text", "Output format: text or json")
    inspect := &ffcli.Command{
        Name:       "inspect",
        ShortUsage: "routebook inspect [-format text|json] <path>",
        ShortHelp:  "Inspect a local demonstration record.",
        LongHelp:   "Reads a local filename supplied by the user.",
        FlagSet:    fs,
        Exec: func(_ context.Context, args []string) error {
            if len(args) != 1 { return fmt.Errorf("one input path required") }
            fmt.Println("format:", *format, "path:", args[0])
            return nil
        },
    }
    root := &ffcli.Command{
        ShortUsage: "routebook <subcommand>",
        Subcommands: []*ffcli.Command{inspect},
    }
    if err := root.ParseAndRun(context.Background(), os.Args[1:]); err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(2)
    }
}

This is a teaching example, not a complete multilingual program. In particular, it validates the positional count but does not yet reject arbitrary values of -format, and its error text is still English. Add a controlled message catalogue and a well-defined exit policy at the application layer. If you customize help with UsageFunc, compare its output with the actual FlagSet and subcommand tree instead of hard-coding obsolete flags.

Chapter 3 — Practical investigations with observable acceptance tests

The following 30 cases are organized around problems a real reader or maintainer can encounter. Each one separates the visible symptom from the framework mechanism, a bounded repair and a test. The aim is to learn how the command actually behaves. A good translation becomes reliable when the user can predict and verify that behavior, rather than when a phrase merely sounds like an English original.

1. Flag name translated accidentally

A translator changes -format in a Spanish example to a Spanish word, but the program registers only the original flag. flag.FlagSet matches executable names and does not automatically accept localized synonyms.

The lesson for multilingual documentation is to keep command grammar and reader-facing explanation in separate places. Keep the key literal and translate its short explanatory text instead of inventing an alias. Explain the accepted form with a small ordinary task, not with a slogan about localization. If the correction implies a software change, it belongs in an engineering review rather than a translator’s untracked edit.

Verify the result with evidence: Invoke the same flag under every locale and compare parsed values. Preserve the invocation and its observed output so the check can be repeated after an upgrade. A passing outcome in one locale is not proof of behavior in every operating system.

2. ShortUsage no longer matches command

A common reader journey starts here: The ShortUsage sample displays a positional path that the command’s Exec no longer accepts. The underlying mechanism matters because Usage strings can be written manually and must track actual validation and command design.

Generate a test from the published signature and update documentation alongside code changes. Describe the difference between what is typed and what is explained. Show a valid example and one intentional failure that the reader can safely reproduce without modifying valuable files.

A useful acceptance check is this: Paste the usage example into the built binary and confirm the expected outcome. If the translated guide does not enable the reader to interpret the result, improve its recovery explanation before treating the passage as complete.

3. LongHelp repeats the wrong default

An expanded help paragraph says json is the default while FlagSet registers text. The visible words are only part of the problem. A human-readable description can become stale without affecting the typed default.

A maintainable correction begins with the actual contract. Read the registered default from code and correct every locale resource together. Keep the test small so that a failure can be traced to a command token, a value conversion, an application rule or display formatting. These are different defects and often require different owners.

Reproduce and review: Run the command without a format flag and check the selected output type. Save both positive and negative outcomes. Ask a language reviewer to explain which input is accepted and why; an accurate answer is more valuable than a superficially fluent screenshot.

4. ShortHelp translated too literally

Consider the boundary between the executable and its explanation. A subcommand label remains grammatical but tells readers nothing about what the command actually does. ShortHelp is discovery text placed near command names in parent help.

Use a concise action-and-object description that fits the parent listing. Write the example using literal accepted tokens, then translate the prose about their purpose. Avoid claiming that the framework provides a feature merely because the surrounding application could implement it.

The release gate should include this check: Ask a first-time reader to choose the correct child command from help alone. Document any dependence on versions, shells or terminal settings rather than generalizing a local result to every reader.

5. Custom UsageFunc omits a child

A localized usage generator returns a fixed old list of commands after a new subcommand is added. UsageFunc is an application-owned function and can diverge from the live command tree.

The lesson for multilingual documentation is to keep command grammar and reader-facing explanation in separate places. Build its output from the current command structure or test the list against it. Explain the accepted form with a small ordinary task, not with a slogan about localization. If the correction implies a software change, it belongs in an engineering review rather than a translator’s untracked edit.

Verify the result with evidence: Add a fixture enumerating every public child name and verify it appears. Preserve the invocation and its observed output so the check can be repeated after an upgrade. A passing outcome in one locale is not proof of behavior in every operating system.

6. Unexpected flag library assumption

A common reader journey starts here: A developer copies syntax from Cobra or Kingpin into a tool actually using Go’s standard flag.FlagSet. The underlying mechanism matters because ffcli deliberately works with the standard flag abstraction rather than the API of every CLI framework.

Use only documented flag syntax and explicitly test bundled or GNU-looking forms. Describe the difference between what is typed and what is explained. Show a valid example and one intentional failure that the reader can safely reproduce without modifying valuable files.

A useful acceptance check is this: Run the sample through the real binary instead of assuming another library’s semantics. If the translated guide does not enable the reader to interpret the result, improve its recovery explanation before treating the passage as complete.

7. Wrong FlagSet output stream

Help is captured from standard output in a test, but the flag set writes usage through a different configured writer. The visible words are only part of the problem. The Go flag package has its own output writer and an application’s help path may choose streams differently.

A maintainable correction begins with the actual contract. Document where help and errors are written, and test both pipes and redirection. Keep the test small so that a failure can be traced to a command token, a value conversion, an application rule or display formatting. These are different defects and often require different owners.

Reproduce and review: Capture stdout and stderr independently for a -h invocation. Save both positive and negative outcomes. Ask a language reviewer to explain which input is accepted and why; an accurate answer is more valuable than a superficially fluent screenshot.

8. Parse error exits prematurely

Consider the boundary between the executable and its explanation. A flag set configured with flag.ExitOnError terminates the process before the application’s translation layer can handle a mistake. Go flag error-handling modes change control flow, not just the wording of an error.

Choose an error policy intentionally, such as ContinueOnError when centralized recovery is required. Write the example using literal accepted tokens, then translate the prose about their purpose. Avoid claiming that the framework provides a feature merely because the surrounding application could implement it.

The release gate should include this check: Run an unknown flag and assert the chosen handler controls the message and status. Document any dependence on versions, shells or terminal settings rather than generalizing a local result to every reader.

9. ErrHelp misclassified

A reader asks for -h and receives a failure alarm even though they requested usage. flag.ErrHelp has a distinct documented role in help control flow.

The lesson for multilingual documentation is to keep command grammar and reader-facing explanation in separate places. Treat an intentional help request differently from an actual rejected input. Explain the accepted form with a small ordinary task, not with a slogan about localization. If the correction implies a software change, it belongs in an engineering review rather than a translator’s untracked edit.

Verify the result with evidence: Compare the response to -h with the response to an invalid flag. Preserve the invocation and its observed output so the check can be repeated after an upgrade. A passing outcome in one locale is not proof of behavior in every operating system.

10. Missing Exec on terminal command

A common reader journey starts here: A parent command is selected without an Exec function and the user receives an unfamiliar error. The underlying mechanism matters because ffcli documents NoExecError for a terminal command that lacks an execution function.

Present the relevant help or a supported subcommand choice instead of a generic failure. Describe the difference between what is typed and what is explained. Show a valid example and one intentional failure that the reader can safely reproduce without modifying valuable files.

A useful acceptance check is this: Run the parent without a child and verify the expected guidance. If the translated guide does not enable the reader to interpret the result, improve its recovery explanation before treating the passage as complete.

11. Root flags consumed in wrong place

A user puts a root flag after a child command because a translated example assumes flags may be placed anywhere. The visible words are only part of the problem. Each command can have its own flag set and argument parsing stage.

A maintainable correction begins with the actual contract. Show canonical tested placement for parent and child flags. Keep the test small so that a failure can be traced to a command token, a value conversion, an application rule or display formatting. These are different defects and often require different owners.

Reproduce and review: Permute positions of the same flag and document which invocations actually work. Save both positive and negative outcomes. Ask a language reviewer to explain which input is accepted and why; an accurate answer is more valuable than a superficially fluent screenshot.

12. Child name localized invisibly

Consider the boundary between the executable and its explanation. A new locale translates the displayed child command name but the dispatcher still expects the original Name. Subcommand dispatch uses executable names, while ShortHelp is presentation.

Keep the recognized child token stable and translate its purpose separately. Write the example using literal accepted tokens, then translate the prose about their purpose. Avoid claiming that the framework provides a feature merely because the surrounding application could implement it.

The release gate should include this check: Execute a child under two locales and compare command selection. Document any dependence on versions, shells or terminal settings rather than generalizing a local result to every reader.

13. ParseAndRun hides phase boundary

The guide implies that option values are validated and external clients created before parsing, even though setup belongs elsewhere. ParseAndRun combines command selection and execution, while separate Parse and Run allow staged setup.

The lesson for multilingual documentation is to keep command grammar and reader-facing explanation in separate places. Describe the implementation’s actual sequence, avoiding guarantees about dependencies not present in ffcli. Explain the accepted form with a small ordinary task, not with a slogan about localization. If the correction implies a software change, it belongs in an engineering review rather than a translator’s untracked edit.

Verify the result with evidence: Trace a good command and a bad command through both paths in tests. Preserve the invocation and its observed output so the check can be repeated after an upgrade. A passing outcome in one locale is not proof of behavior in every operating system.

14. Incorrect errors from Exec

A common reader journey starts here: Exec rejects missing positional input, but the application prints an English error after otherwise translated help. The underlying mechanism matters because Execution errors are owned by application code and are not automatically localized by the command tree.

Centralize errors and provide a path-specific recovery instruction. Describe the difference between what is typed and what is explained. Show a valid example and one intentional failure that the reader can safely reproduce without modifying valuable files.

A useful acceptance check is this: Run the command with no path in every locale and inspect the whole message. If the translated guide does not enable the reader to interpret the result, improve its recovery explanation before treating the passage as complete.

15. Unknown flag feedback is cryptic

The user types -formt and sees a low-level flag parsing complaint without a valid alternative. The visible words are only part of the problem. A technical parser error may not be the best reader-facing explanation.

A maintainable correction begins with the actual contract. Offer the actual registered spelling and a harmless working invocation. Keep the test small so that a failure can be traced to a command token, a value conversion, an application rule or display formatting. These are different defects and often require different owners.

Reproduce and review: Test the typo and ask a reader to repair it without opening English docs. Save both positive and negative outcomes. Ask a language reviewer to explain which input is accepted and why; an accurate answer is more valuable than a superficially fluent screenshot.

16. String flag accepts invalid enum

Consider the boundary between the executable and its explanation. The flag set accepts -format banana because its type is string, though the application supports only text and json. Type-aware parsing does not enforce a domain-specific enumeration automatically.

Validate values in the application and give the exact accepted tokens. Write the example using literal accepted tokens, then translate the prose about their purpose. Avoid claiming that the framework provides a feature merely because the surrounding application could implement it.

The release gate should include this check: Test the two valid choices and a deliberately unsupported one. Document any dependence on versions, shells or terminal settings rather than generalizing a local result to every reader.

17. Bool flag followed by value

A sample shows -verbose true while the registered flag is Boolean and the next token becomes positional. Go flag parsing has defined Boolean handling that differs from arbitrary string-value flags.

The lesson for multilingual documentation is to keep command grammar and reader-facing explanation in separate places. Show the tested Boolean form rather than adapting a template from another language. Explain the accepted form with a small ordinary task, not with a slogan about localization. If the correction implies a software change, it belongs in an engineering review rather than a translator’s untracked edit.

Verify the result with evidence: Compare flag omitted, present, and an explicitly assigned Boolean value. Preserve the invocation and its observed output so the check can be repeated after an upgrade. A passing outcome in one locale is not proof of behavior in every operating system.

18. Negative integer ambiguity

A common reader journey starts here: A user provides a negative number to an integer flag but the published example relies on untested spacing and separators. The underlying mechanism matters because Flag parsing and value conversion need an exact command grammar.

Show a verified form such as an equals assignment where the actual parser accepts it. Describe the difference between what is typed and what is explained. Show a valid example and one intentional failure that the reader can safely reproduce without modifying valuable files.

A useful acceptance check is this: Use a harmless negative value and assert the parsed integer. If the translated guide does not enable the reader to interpret the result, improve its recovery explanation before treating the passage as complete.

19. Environment variable name translated

A local-language guide changes a configuration key used by the related ff integration. The visible words are only part of the problem. Environment and config names may be stable machine interfaces, not display labels.

A maintainable correction begins with the actual contract. Keep the literal key and translate the explanation of what it controls. Keep the test small so that a failure can be traced to a command token, a value conversion, an application rule or display formatting. These are different defects and often require different owners.

Reproduce and review: Run the same config fixture under each locale and compare flags populated. Save both positive and negative outcomes. Ask a language reviewer to explain which input is accepted and why; an accurate answer is more valuable than a superficially fluent screenshot.

20. Configuration priority misdescribed

Consider the boundary between the executable and its explanation. The help claims that a file value always wins over a flag when the selected ff options use another order. Configuration precedence is a policy that depends on parser options and application wiring.

Describe only tested precedence, with a short example of conflicting sources. Write the example using literal accepted tokens, then translate the prose about their purpose. Avoid claiming that the framework provides a feature merely because the surrounding application could implement it.

The release gate should include this check: Supply two conflicting harmless values and inspect the selected value. Document any dependence on versions, shells or terminal settings rather than generalizing a local result to every reader.

21. Credential echoed in logs

An error includes all parsed command arguments, revealing a dummy secret in a test and potentially a real one in production. Flag parsing and diagnostics can expose sensitive values if the application prints whole inputs.

The lesson for multilingual documentation is to keep command grammar and reader-facing explanation in separate places. Redact credentials and keep examples free of live tokens. Explain the accepted form with a small ordinary task, not with a slogan about localization. If the correction implies a software change, it belongs in an engineering review rather than a translator’s untracked edit.

Verify the result with evidence: Run a dummy secret fixture and assert that its full value never appears. Preserve the invocation and its observed output so the check can be repeated after an upgrade. A passing outcome in one locale is not proof of behavior in every operating system.

22. Unicode path displayed but not opened

A common reader journey starts here: A Japanese filename prints correctly in the demo but fails during real file access. The underlying mechanism matters because UTF-8 strings, process arguments and OS path operations are distinct layers.

Test real harmless file I/O through the distributed binary. Describe the difference between what is typed and what is explained. Show a valid example and one intentional failure that the reader can safely reproduce without modifying valuable files.

A useful acceptance check is this: Create a non-Latin temporary path, open it, and inspect its contents. If the translated guide does not enable the reader to interpret the result, improve its recovery explanation before treating the passage as complete.

23. RTL help with mixed syntax

An Arabic sentence embeds -format=json and readers copy an incorrect visual order. The visible words are only part of the problem. Bidirectional layout affects reading order and can obscure ASCII tokens.

A maintainable correction begins with the actual contract. Put command syntax on standalone code lines with unambiguous punctuation. Keep the test small so that a failure can be traced to a command token, a value conversion, an application rule or display formatting. These are different defects and often require different owners.

Reproduce and review: Have a fluent reviewer paste-test every mixed-direction sample. Save both positive and negative outcomes. Ask a language reviewer to explain which input is accepted and why; an accurate answer is more valuable than a superficially fluent screenshot.

24. Narrow terminal hides options

Consider the boundary between the executable and its explanation. Long translated LongHelp text wraps across a subcommand table and separates option names from explanations. Terminal width and glyph width matter to layout even when content is semantically correct.

Use readable paragraphs and review custom usage formatting at narrow widths. Write the example using literal accepted tokens, then translate the prose about their purpose. Avoid claiming that the framework provides a feature merely because the surrounding application could implement it.

The release gate should include this check: Capture 40-column and 80-column usage and inspect all flags. Document any dependence on versions, shells or terminal settings rather than generalizing a local result to every reader.

25. JSON keys changed by locale

A script consuming structured output fails after its human description language changes. Machine-readable field names require stable contracts independent of help translation.

The lesson for multilingual documentation is to keep command grammar and reader-facing explanation in separate places. Localize interactive text and leave specified schema fields unchanged. Explain the accepted form with a small ordinary task, not with a slogan about localization. If the correction implies a software change, it belongs in an engineering review rather than a translator’s untracked edit.

Verify the result with evidence: Parse two locale outputs using the same schema and compare values. Preserve the invocation and its observed output so the check can be repeated after an upgrade. A passing outcome in one locale is not proof of behavior in every operating system.

26. Help success status differs

A common reader journey starts here: An intentional usage request returns the same failure status as invalid input, confusing automation. The underlying mechanism matters because Exit behavior is an application-level decision that interacts with flag error handling.

Define and test a consistent help and failure policy. Describe the difference between what is typed and what is explained. Show a valid example and one intentional failure that the reader can safely reproduce without modifying valuable files.

A useful acceptance check is this: Invoke help, one bad flag and one valid command and compare statuses. If the translated guide does not enable the reader to interpret the result, improve its recovery explanation before treating the passage as complete.

27. Stale parent listing

A new command is registered but the translated root ShortHelp list remains out of date. The visible words are only part of the problem. Command hierarchies and usage generation can drift when documentation is maintained separately.

A maintainable correction begins with the actual contract. Test that every registered public child appears in help and in task navigation. Keep the test small so that a failure can be traced to a command token, a value conversion, an application rule or display formatting. These are different defects and often require different owners.

Reproduce and review: Enumerate child names from the command tree and compare with rendered usage. Save both positive and negative outcomes. Ask a language reviewer to explain which input is accepted and why; an accurate answer is more valuable than a superficially fluent screenshot.

28. Test shares mutable FlagSet

Consider the boundary between the executable and its explanation. A test suite reuses a flag set between scenarios and one case influences the next, hiding locale-specific bugs. Flags can maintain parsed state and should be initialized carefully in isolated tests.

Construct fresh command trees or reset test fixtures as needed. Write the example using literal accepted tokens, then translate the prose about their purpose. Avoid claiming that the framework provides a feature merely because the surrounding application could implement it.

The release gate should include this check: Run tests in different orders and compare identical outcomes. Document any dependence on versions, shells or terminal settings rather than generalizing a local result to every reader.

29. ffcli version changed

A guide copies a method from a newer module version while the distributed application uses an older major path. Go module versions and import paths affect available APIs and behavior.

The lesson for multilingual documentation is to keep command grammar and reader-facing explanation in separate places. Pin the exact tested version and verify the imports against that release. Explain the accepted form with a small ordinary task, not with a slogan about localization. If the correction implies a software change, it belongs in an engineering review rather than a translator’s untracked edit.

Verify the result with evidence: Build from a clean module file and run the published example. Preserve the invocation and its observed output so the check can be repeated after an upgrade. A passing outcome in one locale is not proof of behavior in every operating system.

30. Claims universal locale support

A common reader journey starts here: One English and one Japanese terminal produce good help, and the article announces full support for all languages. The underlying mechanism matters because Terminal, font, shell and filesystem differences remain outside ffcli’s small API.

Record specific tested configurations and keep untested environments explicit. Describe the difference between what is typed and what is explained. Show a valid example and one intentional failure that the reader can safely reproduce without modifying valuable files.

A useful acceptance check is this: Replay representative Unicode, width and error fixtures on each supported deployment. If the translated guide does not enable the reader to interpret the result, improve its recovery explanation before treating the passage as complete.

Chapter 4 — Quality gates that make localization dependable

1. Choose a measurable reader task

An international command-line guide should begin with an outcome that makes sense outside the development team. A reader may want to inspect a file, request a summary or list available commands. Identify that task, give the smallest safe invocation, and explain the result. A translation that merely reproduces an API reference without helping the reader act is not sufficient. Record what a successful run looks like before choosing terminology, because the expected result determines which details deserve the clearest wording.

Start with routebook inspect -format text report.txt and the reader’s purpose: inspect a local record. Explain the output before presenting the Go struct definition. This gives newcomers an immediate reason to care about ShortUsage and Exec, while still serving technical readers who need the concrete field names.

2. Classify the text before translating it

Make a three-way distinction between literal syntax, user data and translatable content. Literal syntax includes established command names, flags, placeholders when interpreted by a parser and configuration keys promised as stable. User data includes filenames, project identifiers and values supplied by the reader. Human-facing explanations, headings and recovery instructions are the main translation surface. This classification prevents a well-meaning language edit from creating an incompatible executable command.

A Go flag.FlagSet is the executable source for flag names and typed defaults. Put those in a grammar table separate from ShortHelp and LongHelp. Translate human descriptions without changing the flag name format or an accepted machine value unless the code and versioned contract deliberately change too.

3. Keep a single source of truth for examples

A code sample should be tested in the same shell and software version named by the documentation. Store the command beside a known expected result and rerun it after releases. If the example is displayed through a publishing system, paste-test the rendered version as well; quotation marks, dashes, code fences and whitespace are easily corrupted. Use imaginary local paths and harmless operations rather than live credentials, production services or private information.

Use fictional filenames and read-only examples. Some Go CLI examples use remote tokens or production endpoints, but those introduce unnecessary risk into a translation tutorial. A copied command should be harmless under the documented shell, and its expected output should not depend on private infrastructure.

4. Explain accepted values, not just option labels

A label such as ‘format’ is useful only when the reader knows which values it accepts. Distinguish machine tokens such as text and json from translated descriptions of those tokens. State defaults, whether case matters, whether the value may be omitted and how invalid values are handled. If a number is expected, document the actually accepted numeric syntax rather than silently replacing a decimal point with a culturally familiar separator.

Differentiate the compact ShortUsage line from the explanatory paragraphs in LongHelp. The first shows how to form a command; the second explains why a user might choose it. A fluent translation of ShortHelp still needs a separately tested invocation and an accessible path from the parent command to its child.

5. Connect discovery, execution and recovery

Help has more than one job. It must allow a user to discover what exists, understand enough to choose the right option, execute a reasonable command, and correct mistakes without escalating to an expert. Test all four stages. If the first three work but the error remains a cryptic source-language exception, the reader still lacks an independent path to completion. A concise, concrete repair instruction can have more value than many translated lines of reference material.

The ff ecosystem can bring configuration files and environment variables into a command’s inputs. Those key names are potentially relied upon by automation and should have a documented stable contract. Translate their explanations and validation failures while testing that programmatic configuration still means the same thing under every supported locale.

6. Protect automation when localizing output

The same executable may serve a person and a scheduled job. Human-readable help, progress and errors can vary with locale; machine-readable keys, numeric fields and exit statuses should follow their documented stable contracts. If users pipe output into another program, changing a JSON key or adding decorative banners may break workflows. Separate interactive presentation from data output explicitly and test each as a different interface.

A typed FlagSet can parse an integer or Boolean flag, but application rules such as permitted output formats, resource bounds and missing positional arguments still need clear enforcement. Show exact accepted values rather than replacing them with translated labels that the program does not understand.

7. Check Unicode input and output separately

A visually correct non-Latin command in a web article does not prove that a terminal receives the same bytes or that a file can be opened. Test shell argument construction, runtime string handling, path operations, error formatting and terminal or redirected output as separate stages. Include decomposed accents and mixed-direction text where relevant. Report what was actually tested and avoid claiming uniform behavior across all systems from one machine.

Go strings are UTF-8 text, yet filenames, shell quoting, terminal output and OS interfaces still need an end-to-end test. A Japanese path that prints in fmt.Println should also be opened successfully by the real application before making broad portability claims.

8. Design for narrow terminals and plain text

Not every reader uses an eighty-column desktop terminal with color support. Test long descriptions at narrow widths, copy them into plain text and verify that each flag remains associated with its explanation. When color is stripped, errors should still be identifiable by wording and stable codes. Avoid using whitespace alignment as a substitute for good sentences. A readable fallback is more inclusive than a beautiful table that collapses under translation.

ShortHelp often appears in a short parent listing and may have less space than LongHelp. Review translated length at narrow terminal widths and test output captured to a file. Do not use color or indentation alone to distinguish commands in a way that disappears for screen readers.

9. Use error messages to teach valid recovery

An error should identify the offending choice where safe, state the actual accepted form and show a harmless corrective example. Do not dump secret values or raw environment configurations. Keep error categories stable even when prose is localized, so support teams can diagnose the same problem in different languages. A practical acceptance test is to give a user an incorrect command and see whether they can repair it using the displayed message alone.

An application may see flag.ErrHelp, NoExecError, ordinary parsing errors and failures from Exec. Those paths need different recovery instructions. Keep stable categories for support, give one valid command and redact values that could contain credentials or private data.

10. Store release evidence with the translation

Translate documentation against a tested version, not against a remembered version. Keep the source text, locale resources, executable examples, observed results and responsible reviewer linked to the release. Parser or framework upgrades should trigger renewed testing of help, errors, Unicode and compatibility. When something remains unverified, say so. Accurate limitations increase trust and make it easier to decide what to test next.

Save the tested Go module version, flag set layout and expected usage output. A change to UsageFunc or a new nested command can alter the public interface even when the translation files remain untouched. Rebuild and run the distributed binary before publishing new documentation.

Chapter 5 — Common implementation questions

Does ffcli include a complete translation engine?

Its documented focus is command trees, standard Go flags, usage and execution. It exposes human-facing help fields and a custom usage function; choosing languages, storing messages and validating translations remain application responsibilities.

Which fields belong in localized help?

ShortHelp and LongHelp are naturally reader-facing. ShortUsage contains both grammar and explanatory placeholders, so it needs careful editing. UsageFunc can generate an appropriate presentation if its output remains synchronized with the real command tree.

Should I rename FlagSet keys for each locale?

Normally not. Existing scripts may depend on those names. Keep stable keys, explain them in the user’s language and handle aliases only through a deliberate compatible API design.

What happens if a command has no Exec?

The package documents NoExecError when a selected terminal command has no executable function. Applications can use that condition to show relevant guidance or parent help instead of a mysterious raw failure.

Why choose Parse and Run separately?

It can help when configuration must be parsed before dependencies are initialized. ParseAndRun is convenient for simpler flows. Neither form automatically solves localization; what matters is where and how errors reach the user.

How can I keep JSON output compatible?

Treat machine-readable output as a stable schema. Translate human explanations and interactive messages separately, then parse the outputs of different locales against the same schema in tests.

What Unicode testing is necessary?

Check arguments with accented and non-Latin text, file operations on disposable paths, readable diagnostics, redirected output and terminal display. Record which operating systems and shells were actually exercised.

What is the minimum maintenance routine?

Pin the module version, run a clean build, compare generated help with the command tree, test one valid and several invalid commands, and repeat core multilingual fixtures after any flag or usage change.

Chapter 6 — Four weeks from first example to maintainable documentation

Week one — audit the executable contract

List the literal flags, command names, aliases, value types, defaults and errors for Go ffcli. Build one harmless test command and one deliberately incorrect command. Use the official reference for the installed framework version and note where the application supplies custom behavior. By the end of this week, a reviewer should distinguish syntax from translatable explanation, and the team should have an observable baseline against which future documentation can be checked.

Week two — translate a complete task

Select one user goal and translate its help entry, example, expected result and error recovery together. Ask a technical reviewer and a proficient target-language reader to attempt that task independently. The technical reviewer verifies Go ffcli behavior; the language reviewer verifies that instructions are understandable without referring to the source-language article. Disagreements about command spelling are resolved against the accepted grammar, not by preference for a familiar word.

Week three — test international edge cases

Expand the matrix to include a missing value, a wrong value, one unknown option, Unicode paths, a filename with spaces, redirected output and narrow terminal display. Add any framework-specific cases in the preceding investigations that match the actual product. Test the supported versions and operating systems; do not advertise untested behavior. Keep the fixtures small, fictional and free from credentials. Preserve both the test invocation and the observed result.

Week four — publish and establish a revision trigger

Give a new reader the finished localized page and a clean environment. They should be able to discover help, run the simplest valid command, interpret the output and recover from a predictable failure. Paste-test the rendered code samples in the target shell. Archive the result and record a trigger for changes to Go ffcli, command signatures, help generation, recognized options or expected output. Every such change deserves a new documentation check, not an assumption that the old translation remains correct.

Chapter 7 — What proficiency looks like

Go ffcli succeeds by keeping the command-tree machinery small. That also gives authors a clear opportunity to improve the experience of international users. A command’s Name and flag keys define the executable path; ShortHelp, LongHelp and application diagnostics explain that path to a person. Carefully translated guidance, honest version-specific evidence and repeatable tests can preserve both interfaces. The result is a CLI that helps people act independently without asking their scripts to understand translated prose.

The long-term measure is not the number of translated sentences. It is whether a reader using another language can perform the intended task, understand the consequences of their choices and recover safely when something goes wrong. Keep executable syntax stable unless deliberately versioned, keep ordinary explanations clear, preserve machine contracts and test the published examples. That is the practical work of translating command-line software like a professional.

Primary documentation and connected learning