This guide covers migration to the current production profile (v1.x) of msgcat.
No change if you already use:
import "github.com/loopcontext/msgcat"Old:
msgcat.Config{
ResourcePath: "./resources/messages",
}New recommended:
msgcat.Config{
ResourcePath: "./resources/messages",
CtxLanguageKey: "language",
DefaultLanguage: "en",
FallbackLanguages: []string{"es"},
StrictTemplates: true,
ObserverBuffer: 1024,
StatsMaxKeys: 512,
ReloadRetries: 2,
ReloadRetryDelay: 50 * time.Millisecond,
}Previous mental model: observer callbacks ran inline.
Current behavior:
- callbacks are dispatched asynchronously,
- callback panic is recovered,
- queue overflow increments
stats.DroppedEvents.
Action: if you depended on synchronous ordering, move that logic outside observer callbacks.
Current behavior includes capping:
- per-map key count is limited by
StatsMaxKeys; - overflow events are grouped as
__overflow__.
Action: dashboards should include both explicit keys and __overflow__.
Reload now retries transient failures.
Action:
- prefer atomic deploy of YAML files (
write temp+rename), - configure retries for your rollout pattern.
If you configured an observer, call msgcat.Close(catalog) on shutdown to flush/stop worker goroutine cleanly.
- Context key lookup remains compatible with both typed key and plain string key.
- (If you are on a release with string message keys and named parameters, see section 9 below.)
Module requires Go 1.26 or later. If you are on an older toolchain, upgrade before updating to msgcat v1.0.8.
If you are moving from numeric message codes and positional template parameters to the new API:
- Message keys — Use string keys everywhere (e.g.
"greeting.hello","error.not_found"). ReplaceGetMessageWithCtx(ctx, 1, a, b)withGetMessageWithCtx(ctx, "greeting.hello", msgcat.Params{"name": a, "detail": b}). - Templates — Replace
{{0}},{{1}}with named placeholders:{{name}},{{plural:count|item|items}},{{num:amount}},{{date:when}}. Pass a singlemsgcat.Paramsmap. - Code field — Code is now optional and string. In YAML use
code: 404orcode: "ERR_NOT_FOUND". In Go usemsgcat.CodeInt(503)ormsgcat.CodeString("ERR_MAINT"). Codes are not required to be unique. When code is empty, useMessage.KeyorErrorKey()as the API identifier. - LoadMessages — Each message must have
Keywith prefixsys.(e.g.sys.alert). No numeric code range; useCode: msgcat.CodeInt(9001)orCode: msgcat.CodeString("SYS_LOADED")if you need a code. - Observer —
OnMessageMissing(lang, msgKey string)andOnTemplateIssue(lang, msgKey string, issue string)now take stringmsgKeyinstead ofmsgCode int. - YAML — Remove
group. Use string keys underset:and optionalcodeper entry. See README anddocs/CONVERSION_PLAN.md.
The following are additive and optional. Existing YAML and code keep working as-is.
- Optional group — You can add top-level
group: 0orgroup: "api"to message files. The catalog does not interpret it; it is for organization and tooling. Omit if you do not use it. - CLDR plural forms — You can add
short_forms/long_forms(maps: zero, one, two, few, many, other) and optionalplural_paramper entry for languages that need more than two plural forms. If you only useshort/longand{{plural:count|singular|plural}}, no change needed. - MessageDef and CLI — You can define messages in Go with
msgcat.MessageDefand runmsgcat extract -source en.yaml -out en.yaml .to merge them into YAML. Optional; at runtime the catalog still loads from YAML.