From 1b7495bc4902d9a00416e653c538466c668dec08 Mon Sep 17 00:00:00 2001 From: Joe Mooring Date: Wed, 22 Apr 2026 10:34:43 -0700 Subject: [PATCH] langs: Use Language.Locale as primary localization key Localization now uses Language.Locale as the golocales lookup key, falling back to Language.Lang, then defaultContentLanguage, then "en". Closes #9109 --- langs/language.go | 12 +++-- langs/languages_integration_test.go | 81 +++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/langs/language.go b/langs/language.go index 1ff15b266..fc33518b1 100644 --- a/langs/language.go +++ b/langs/language.go @@ -79,11 +79,13 @@ func (l *Language) IsDefault() bool { // NewLanguage creates a new language. func NewLanguage(lang, defaultContentLanguage, timeZone string, languageConfig LanguageConfig, logger loggers.Logger) (*Language, error) { - translator := golocales.New(lang) - if translator == nil { - translator = golocales.New(defaultContentLanguage) - if translator == nil { - translator = golocales.New("en") + var translator golocales.Translator + for _, key := range []string{languageConfig.Locale, lang, defaultContentLanguage, "en"} { + if key == "" { + continue + } + if translator = golocales.New(key); translator != nil { + break } } diff --git a/langs/languages_integration_test.go b/langs/languages_integration_test.go index 20b93e0f9..5e58cdc8c 100644 --- a/langs/languages_integration_test.go +++ b/langs/languages_integration_test.go @@ -215,3 +215,84 @@ TITLE: {{ .Title }} RELPERMALINK: {{ .RelPermalink }}| "b (en)|TITLE: P1 (en) RELPERMALINK: /en/p1/|", ) } + +func TestLocaleAsLocalizationKeyIssue9109(t *testing.T) { + t.Parallel() + + files := ` +-- hugo.toml -- +disableKinds = ['page','rss','section','sitemap','taxonomy','term'] +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = true + +[languages.de] +weight = 1 + +[languages.en] +locale = 'en-US' +weight = 2 + +[languages.fr] +locale = 'bogus' +weight = 3 + +[languages.nn] +weight = 4 + +[languages.xx] +locale = 'bogus' +weight = 5 + +[languages.zh-cn] +locale = 'zh-Hans' +weight = 6 +-- layouts/home.html -- +Time: {{ "2026-04-01T20:11:31+08:00" | time.Format ":date_long" }}| +FormatAccounting: {{ 512.5032 | lang.FormatAccounting 2 "USD" }}| +FormatCurrency: {{ 512.5032 | lang.FormatCurrency 2 "USD" }}| +` + + b := hugolib.Test(t, files) + + // de: no locale => localize with lang. + b.AssertFileContent("public/de/index.html", + `Time: 1. April 2026|`, + "FormatAccounting: 512,50\u00a0$|", + "FormatCurrency: 512,50\u00a0$|", + ) + + // en: valid locale => localize with locale. + b.AssertFileContent("public/en/index.html", + `Time: April 1, 2026|`, + `FormatAccounting: $512.50|`, + `FormatCurrency: $512.50|`, + ) + + // fr: invalid locale => localize with lang. + b.AssertFileContent("public/fr/index.html", + `Time: 1 avril 2026|`, + "FormatAccounting: 512,50\u00a0$US|", + "FormatCurrency: 512,50\u00a0$US|", + ) + + // nn: no locale => localize with lang. + b.AssertFileContent("public/nn/index.html", + `Time: 1. april 2026|`, + "FormatAccounting: 512,50\u00a0USD|", + "FormatCurrency: 512,50\u00a0USD|", + ) + + // xx: invalid locale + invalid lang => localize with defaultContentLanguage. + b.AssertFileContent("public/xx/index.html", + `Time: 1. April 2026|`, + "FormatAccounting: 512,50\u00a0$|", + "FormatCurrency: 512,50\u00a0$|", + ) + + // zh-cn: invalid lang, but valid locale => localize with locale. + b.AssertFileContent("public/zh-cn/index.html", + `Time: 2026年4月1日|`, + `FormatAccounting: US$512.50|`, + `FormatCurrency: US$512.50|`, + ) +} -- 2.39.5