gohugoio/hugo · error
failed to load translations: %w%s
Error message
failed to load translations: %w%s
What it means
Hugo's i18n TranslationProvider failed to parse a translation file with go-i18n's bundle.ParseMessageFileBytes. The wrapped error carries the underlying parse failure (invalid TOML/YAML/JSON, bad plural categories, or reserved keys mixed with unreserved keys), and Hugo appends extra guidance for the reserved-keys case. The error is wrapped with file context so the offending i18n file and position are shown.
Source
Thrown at langs/i18n/translationProvider.go:142
}
name = artificialLangTagPrefix + name
}
_, err = bundle.ParseMessageFileBytes(b, name)
if err != nil {
if strings.Contains(err.Error(), "no plural rule") {
// https://github.com/gohugoio/hugo/issues/7798
name = artificialLangTagPrefix + name
_, err = bundle.ParseMessageFileBytes(b, name)
if err == nil {
return nil
}
}
var guidance string
if strings.Contains(err.Error(), "mixed with unreserved keys") {
guidance = ": see the lang.Translate documentation for a list of reserved keys"
}
return errWithFileContext(fmt.Errorf("failed to load translations: %w%s", err, guidance), r)
}
return nil
}
// CloneResource sets the language func for the new language.
func (tp *TranslationProvider) CloneResource(dst, src *deps.Deps) error {
dst.Translate = tp.getTranslateFunc(dst)
return nil
}
func defaultLanguage(conf config.AllProvider) *langs.Language {
key := conf.DefaultContentLanguage()
for _, l := range conf.Languages().(langs.Languages) {
if l.Lang == key {
return l
}
}View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Open the i18n file named in the error and fix the reported syntax/key problem at the given position.
- If the message mentions 'mixed with unreserved keys', restructure the entry: reserved plural keys (one, other, etc.) cannot share a map with arbitrary custom keys — see the lang.Translate docs for the reserved-key list.
- Remove plural categories not supported by that language's CLDR rules, or rename the file to the correct language code.
- Validate the file's TOML/YAML/JSON with a linter to catch format errors.
Example fix
# i18n/en.toml — before (reserved plural keys mixed with custom keys) [readMore] other = "Read more" label = "link" # after [readMore] other = "Read more" [readMoreLabel] other = "link"
Defensive patterns
Strategy: validation
Validate before calling
// Validate translation files parse before running hugo
// ls i18n/ && for f in i18n/*.toml; do tomlv "$f"; done
if _, err := toml.DecodeFile("i18n/en.toml", &v); err != nil { log.Fatal(err) } Try / catch
if err := ss.Update(deps); err != nil {
if strings.Contains(err.Error(), "failed to load translations") {
// report offending i18n file/key to user
}
return err
} Prevention
- Lint i18n TOML/YAML/JSON files in CI before builds
- Keep translation keys flat and consistently typed across languages
- Avoid duplicate keys and reserved plural keys like 'other' misuse
- Validate new language files locally with hugo server before commit
When it happens
Trigger: Loading any file under i18n/ (or a theme's i18n/) during site build. Specifically: syntax errors in the translation file; using reserved go-i18n keys (id, description, one, other, few, many, zero) mixed with custom sub-keys under one message; plural categories not valid for the file's language tag (Hugo retries with an artificial 'art-x-' tag prefix for the 'no plural rule' case, so this fires only when that retry also fails).
Common situations: Nesting custom keys alongside 'one'/'other' under a translation id; copying plural forms (e.g. 'few', 'many') into a language whose CLDR plural rules don't define them; malformed TOML/YAML after hand-editing; theme-provided i18n files incompatible after a go-i18n or Hugo upgrade; naming the file with an unparseable language code.
Related errors
- failed to unmarshal config for path %q: %w
- failed to load config: %w
- language %q not found
- failed to decode languages config: %w
- invalid language configuration for %q
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/dda0985b928d345b.json.
Report an issue: GitHub ↗.