1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-12 05:20:26 +00:00
mycorrhiza/l18n/util.go

106 lines
3.2 KiB
Go
Raw Normal View History

2021-09-06 17:46:34 +00:00
package l18n
import (
"fmt"
"golang.org/x/text/feature/plural"
"golang.org/x/text/language"
"net/http"
"strings"
)
// matcher is a language.Matcher configured for all supported languages.
var locales = language.NewMatcher([]language.Tag{
language.Make("en"),
language.Make("ru"),
})
// FromRequest takes a HTTP request and picks the most appropriate localizer (with English fallback)
2021-09-06 17:46:34 +00:00
func FromRequest(r *http.Request) *Localizer {
t, _, _ := language.ParseAcceptLanguage(r.Header.Get("Accept-Language"))
tag, _, _ := locales.Match(t...)
// TODO: support subtags such as en-US, en-GB, zh-Hans
base, _ := tag.Base()
return New(base.String(), "en")
}
var formNames = map[plural.Form]string{
plural.Other: "other",
plural.Zero: "zero",
plural.One: "one",
plural.Two: "two",
plural.Few: "few",
plural.Many: "many",
}
func (t Localizer) rawPlural(lang, rawKey string, n int) (string, bool) {
key := t.getLocalizationKey(lang, rawKey)
str, ok := t.Localizations[key]
if !ok {
return key, false
}
var (
formIdx = plural.Cardinal.MatchPlural(language.Make(lang), n, 0, 0, 0, 0)
form = formNames[formIdx]
)
plural, plOk := t.Localizations[fmt.Sprintf("%v+%v", key, form)]
if !plOk {
return key, false
}
return fmt.Sprintf(str, plural), true
}
// GetPlural gets a translated string respecting locale-specific plural rules. Technically, it replaces %s token with +form subkey and proceed as usual.
func (t Localizer) GetPlural(key string, n int, replacements ...*Replacements) string {
str, ok := t.rawPlural(t.Locale, key, n)
if !ok {
str, ok = t.rawPlural(t.FallbackLocale, key, n)
if !ok {
return key
}
}
// As in the original, we skip templating if have nothing to replace (however, it's strange case for plurals)
if strings.Index(str, "}}") == -1 {
return str
}
return t.replace(str, append(replacements, &Replacements{"n": n})...)
}
// GetPlural64 is ditto for int64
func (t Localizer) GetPlural64(key string, n int64, replacements ...*Replacements) string {
str, ok := t.rawPlural(t.Locale, key, int(n%1000000))
if !ok {
str, ok = t.rawPlural(t.FallbackLocale, key, int(n%1000000))
if !ok {
return key
}
}
// As in the original, we skip templating if have nothing to replace (however, it's strange case for plurals)
if strings.Index(str, "}}") == -1 {
return str
}
return t.replace(str, append(replacements, &Replacements{"n": n})...)
}
func getLocalizationKey(locale string, key string) string {
return fmt.Sprintf("%v.%v", locale, key)
}
/* chekoopa: Missing translation features:
- history records (they use Git description, the possible solution is to parse and translate)
- history dates (history.WithRevisions doesn't consider locale, Monday package is bad idea)
2021-09-06 17:46:34 +00:00
- probably error messages (which are scattered across the code)
- default top bar (it is static from one-shot cfg.SetDefaultHeaderLinks, but it is possible to track default-ness in templates)
- alt solution is implementing "special" links
- dynamic UI (JS are static, though we may send some strings through templates)
- help switches, like,
- "Read in your language"
- "Try reading it in English", if no page found in a foreign locale
- feeds (it seems diffcult to pull locale here)
We do not translate:
- stdout traces (logging is English-only)
*/