go-i18n

Go i18n library for translating apps into 200+ languages with full CLDR plural support and a companion CLI.

Library
Go
vv2.6.1
3,545stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
63/100Good
Development Activity60
Maintenance32
Community60
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture82
Code Quality88
Innovation68
Learning Curve65

go-i18n is a Go package and companion CLI for translating applications into multiple languages. The i18n package provides a Bundle for loading translation message files and a Localizer for looking up messages based on a set of language preferences, with plural-aware rendering for all 200+ languages defined in the Unicode CLDR plural rules.

Alongside the library, the goi18n command extracts translatable Message literals from Go source into message files and merges newly translated files back into the active set, giving teams a lightweight workflow for keeping translations synced with code changes without needing an external localization platform.

What You Get

  • A Bundle type for loading translation message files in JSON, TOML, or YAML (or any format via a registered UnmarshalFunc)
  • A Localizer that matches Accept-Language headers or explicit locale tags to the best available translation
  • Full CLDR plural-form support (zero/one/two/few/many/other) for 200+ languages, code-generated from Unicode’s plural rules data
  • The goi18n CLI for extracting Message literals from source and merging translations across active/translate file pairs
  • text/template-style variable interpolation inside translated strings via TemplateData

Common Use Cases

  • Localizing HTTP handlers by parsing the Accept-Language header into a Localizer per request
  • Extracting new translatable strings from a Go codebase before sending them to translators
  • Merging translator output back into active message files as part of a release workflow
  • Embedding locale files with go:embed and loading them via LoadMessageFileFS for a single static binary

Under The Hood

Architecture The module splits cleanly into a public i18n package (Bundle, Localizer, Message, MessageTemplate) and two supporting internals: internal/plural, which holds CLDR plural-rule tables and their form-selection logic, and i18n/template, a small pluggable template-execution abstraction consumed by Localizer.Localize. Bundle owns per-language-tag maps of parsed MessageTemplates and builds a golang.org/x/text/language.Matcher for locale negotiation, while Localizer wraps a Bundle plus a caller’s language preferences and resolves the best-matching tag before executing the message template with plural and interpolation data. The separate goi18n command reuses the same i18n parsing code to extract Message literals from Go source (extract_command.go) and to diff/merge active vs. translate message files (merge_command.go), so the CLI and library never duplicate message-file logic. If the core Bundle/Localizer split changed, both the library API and the CLI’s extract/merge commands would need to change together.

Tech Stack Written in Go 1.24+ with a deliberately small dependency set: github.com/BurntSushi/toml and go.yaml.in/yaml/v3 for message-file formats, and golang.org/x/text for language-tag parsing and matching (JSON support uses the standard library encoding/json). Releases are built and published with GoReleaser, CI runs on GitHub Actions across two Go version channels, and golangci-lint enforces linting on the latest channel. No runtime web framework or database dependency — the whole module is a self-contained library plus CLI binary.

Code Quality The repository carries 17 _test.go files exercising the bundle, localizer, parser, message, and plural-rule logic, and CI runs go test -race with coverage uploaded to Codecov, so both concurrency safety and coverage are actively tracked. Errors are modeled as explicit typed values (MessageNotFoundErr, invalidPluralCountErr, messageIDMismatchErr, mixedKeysError) with dedicated Error() implementations rather than ad hoc fmt.Errorf strings, and public API naming is consistent (New*, Must* panic-on-error variants, Load*/Parse* pairs). Combined with golangci-lint gating merges, this reflects a mature, actively maintained testing and error-handling discipline.

API Design The public surface favors a small number of composable types over configuration objects: construct one Bundle per process, register unmarshal functions once, then create a lightweight Localizer per request or per language preference. Must* variants (MustLoadMessageFile, MustLocalize) trade explicit error handling for terser call sites during startup, and LocalizeConfig centralizes the optional knobs (plural count, template data, custom template parser) behind a single struct so the common case (Localize with just a message ID) stays simple. Godoc comments are present on essentially every exported type and method, and the CLI mirrors the library’s extract/merge mental model, keeping the developer experience consistent between writing code and managing translation files.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search