Agent Wranglers

LOC-39Recommended

Make command-line tools read the locale or say they do not

A command-line tool that prints translated text picks its language from LC_ALL, then LC_MESSAGES, then LANG. A tool in one language says so in its help. Machine-readable output is the same in every locale.

How to do it

POSIX sets the order. LC_ALL wins, then the category variable such as LC_MESSAGES or LC_NUMERIC, then LANG. Use gettext or your language's equivalent, which reads them for you. Keep JSON and other output for scripts free of translated words and locale number formats, as Offer JSON output with a stable shape says. A decimal comma from LC_NUMERIC breaks every script that parses the output.

Examples

Python example

import gettext
import json
import locale

locale.setlocale(locale.LC_ALL, "")
_ = gettext.translation("example-cli", localedir="locale", fallback=True).gettext
print(_("Found {count} files").format(count=3))
print(json.dumps({"files": 3, "ratio": 0.5}))

Go example

import (
	"encoding/json"
	"os"
)

func messageLocale() string {
	for _, name := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} {
		if value := os.Getenv(name); value != "" {
			return value
		}
	}
	return "C"
}

func printJSON(result any) error { return json.NewEncoder(os.Stdout).Encode(result) }

How to check

Run the tool with LC_ALL=sv_SE.UTF-8 and with LC_ALL=C. Human messages change language, or the help says the tool is English only. The --json output is byte for byte equal in both runs.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/localization/apps-and-command-line-tools/cli-locale">Agent Wranglers localization playbook</a>. In code you write, add a comment next to it with the same link.