From 453cc2258191d391ee8a1584fe2b6e78e7e09eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sat, 24 Apr 2021 17:23:32 +0200 Subject: [PATCH] Fix handling of artificial languages This works around what seems to be an upstream by implementing a simplified tag matcher for artificual languages. Fixes #252 --- v2/go.mod | 2 -- v2/i18n/bundle.go | 52 ++++++++++++++++++++++++++++++++++++++++-- v2/i18n/bundle_test.go | 2 +- v2/i18n/localizer.go | 1 - 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/v2/go.mod b/v2/go.mod index ce404c69..447a6857 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -7,5 +7,3 @@ require ( golang.org/x/text v0.3.3 gopkg.in/yaml.v2 v2.3.0 ) - -replace golang.org/x/text => /Users/bep/dev/go/dump/text diff --git a/v2/i18n/bundle.go b/v2/i18n/bundle.go index 513c127d..077f29fc 100644 --- a/v2/i18n/bundle.go +++ b/v2/i18n/bundle.go @@ -26,9 +26,57 @@ type Bundle struct { matcher language.Matcher } +// The matcher in x/text/language does not handle artificial languages, +// see https://github.com/golang/go/issues/45749 +// This is a simplified matcher thatdelegates to the x/text/language matcher for +// the harder cases. +type matcher struct { + tags []language.Tag + defaultMatcher language.Matcher +} + +func newMatcher(tags []language.Tag) language.Matcher { + var hasArt bool + for _, tag := range tags { + base, _ := tag.Base() + hasArt = base == artTagBase + if hasArt { + break + } + } + + if !hasArt { + return language.NewMatcher(tags) + } + + return matcher{ + tags: tags, + defaultMatcher: language.NewMatcher(tags), + } +} + +func (m matcher) Match(t ...language.Tag) (language.Tag, int, language.Confidence) { + if len(t) == 1 { + candidate := t[0] + base, _ := candidate.Base() + if base == artTagBase { + for i, tag := range m.tags { + if tag == candidate { + return candidate, i, language.Exact + } + } + } + } + + return m.defaultMatcher.Match(t...) +} + // artTag is the language tag used for artificial languages // https://en.wikipedia.org/wiki/Codes_for_constructed_languages -var artTag = language.MustParse("art") +var ( + artTag = language.MustParse("art") + artTagBase, _ = artTag.Base() +) // NewBundle returns a bundle with a default language and a default set of plural rules. func NewBundle(defaultLanguage language.Tag) *Bundle { @@ -126,7 +174,7 @@ func (b *Bundle) addTag(tag language.Tag) { } } b.tags = append(b.tags, tag) - b.matcher = language.NewMatcher(b.tags) + b.matcher = newMatcher(b.tags) } // LanguageTags returns the list of language tags diff --git a/v2/i18n/bundle_test.go b/v2/i18n/bundle_test.go index af5dded7..9afb8514 100644 --- a/v2/i18n/bundle_test.go +++ b/v2/i18n/bundle_test.go @@ -101,7 +101,7 @@ hello = "`+expected+`" func TestPseudoLanguages(t *testing.T) { bundle := NewBundle(language.English) bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) - expected := "a3" + expected := "a2" bundle.MustParseMessageFileBytes([]byte(` hello = "a1" `), "art-x-a1.toml") diff --git a/v2/i18n/localizer.go b/v2/i18n/localizer.go index 9ff65163..17261e2e 100644 --- a/v2/i18n/localizer.go +++ b/v2/i18n/localizer.go @@ -171,7 +171,6 @@ func (l *Localizer) LocalizeWithTag(lc *LocalizeConfig) (string, language.Tag, e func (l *Localizer) getMessageTemplate(id string, defaultMessage *Message) (language.Tag, *MessageTemplate, error) { _, i, _ := l.bundle.matcher.Match(l.tags...) - fmt.Println("I", l.tags, l.bundle.tags, i) tag := l.bundle.tags[i] mt := l.bundle.getMessageTemplate(tag, id) if mt != nil {