diff options
author | wxiaoguang <wxiaoguang@gmail.com> | 2023-04-17 11:37:23 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-17 11:37:23 +0800 |
commit | 7681d582cdae42d9322309ddf732117e6d332776 (patch) | |
tree | 6cdfa61a2055f23153884404fe93d4b4792fd532 /modules/translation | |
parent | be7cd73439c2210bfd889915f74d66686e99dab6 (diff) | |
download | gitea-7681d582cdae42d9322309ddf732117e6d332776.tar.gz gitea-7681d582cdae42d9322309ddf732117e6d332776.zip |
Refactor locale number (#24134)
Before, the `GiteaLocaleNumber.js` was just written as a a drop-in
replacement for old `js-pretty-number`.
Actually, we can use Golang's `text` package to format.
This PR partially completes the TODOs in `GiteaLocaleNumber.js`:
> if we have complete backend locale support (eg: Golang "x/text"
package), we can drop this component.
> tooltip: only 2 usages of this, we can replace it with Golang's
"x/text/number" package in the future.
This PR also helps #24131
Screenshots:
<details>
![image](https://user-images.githubusercontent.com/2114189/232179420-b1b9974b-9d96-4408-b209-b80182c8b359.png)
![image](https://user-images.githubusercontent.com/2114189/232179416-14f36aa0-3f3e-4ac9-b366-7bd3a4464a11.png)
</details>
Diffstat (limited to 'modules/translation')
-rw-r--r-- | modules/translation/mock.go | 27 | ||||
-rw-r--r-- | modules/translation/translation.go | 30 | ||||
-rw-r--r-- | modules/translation/translation_test.go | 27 |
3 files changed, 79 insertions, 5 deletions
diff --git a/modules/translation/mock.go b/modules/translation/mock.go new file mode 100644 index 0000000000..6ce66166aa --- /dev/null +++ b/modules/translation/mock.go @@ -0,0 +1,27 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package translation + +import "fmt" + +// MockLocale provides a mocked locale without any translations +type MockLocale struct{} + +var _ Locale = (*MockLocale)(nil) + +func (l MockLocale) Language() string { + return "en" +} + +func (l MockLocale) Tr(s string, _ ...interface{}) string { + return s +} + +func (l MockLocale) TrN(_cnt interface{}, key1, _keyN string, _args ...interface{}) string { + return key1 +} + +func (l MockLocale) PrettyNumber(v any) string { + return fmt.Sprint(v) +} diff --git a/modules/translation/translation.go b/modules/translation/translation.go index 331da0f965..56cf1df2d4 100644 --- a/modules/translation/translation.go +++ b/modules/translation/translation.go @@ -15,17 +15,20 @@ import ( "code.gitea.io/gitea/modules/translation/i18n" "golang.org/x/text/language" + "golang.org/x/text/message" + "golang.org/x/text/number" ) type contextKey struct{} -var ContextKey interface{} = &contextKey{} +var ContextKey any = &contextKey{} // Locale represents an interface to translation type Locale interface { Language() string - Tr(string, ...interface{}) string - TrN(cnt interface{}, key1, keyN string, args ...interface{}) string + Tr(string, ...any) string + TrN(cnt any, key1, keyN string, args ...any) string + PrettyNumber(v any) string } // LangType represents a lang type @@ -135,6 +138,7 @@ func Match(tags ...language.Tag) language.Tag { type locale struct { i18n.Locale Lang, LangName string // these fields are used directly in templates: .i18n.Lang + msgPrinter *message.Printer } // NewLocale return a locale @@ -147,13 +151,24 @@ func NewLocale(lang string) Locale { langName := "unknown" if l, ok := allLangMap[lang]; ok { langName = l.Name + } else if len(setting.Langs) > 0 { + lang = setting.Langs[0] + langName = setting.Names[0] } + i18nLocale, _ := i18n.GetLocale(lang) - return &locale{ + l := &locale{ Locale: i18nLocale, Lang: lang, LangName: langName, } + if langTag, err := language.Parse(lang); err != nil { + log.Error("Failed to parse language tag from name %q: %v", l.Lang, err) + l.msgPrinter = message.NewPrinter(language.English) + } else { + l.msgPrinter = message.NewPrinter(langTag) + } + return l } func (l *locale) Language() string { @@ -199,7 +214,7 @@ var trNLangRules = map[string]func(int64) int{ } // TrN returns translated message for plural text translation -func (l *locale) TrN(cnt interface{}, key1, keyN string, args ...interface{}) string { +func (l *locale) TrN(cnt any, key1, keyN string, args ...any) string { var c int64 if t, ok := cnt.(int); ok { c = int64(t) @@ -223,3 +238,8 @@ func (l *locale) TrN(cnt interface{}, key1, keyN string, args ...interface{}) st } return l.Tr(keyN, args...) } + +func (l *locale) PrettyNumber(v any) string { + // TODO: this mechanism is not good enough, the complete solution is to switch the translation system to ICU message format + return l.msgPrinter.Sprintf("%v", number.Decimal(v)) +} diff --git a/modules/translation/translation_test.go b/modules/translation/translation_test.go new file mode 100644 index 0000000000..83a40f1458 --- /dev/null +++ b/modules/translation/translation_test.go @@ -0,0 +1,27 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package translation + +import ( + "testing" + + "code.gitea.io/gitea/modules/translation/i18n" + + "github.com/stretchr/testify/assert" +) + +func TestPrettyNumber(t *testing.T) { + // TODO: make this package friendly to testing + + i18n.ResetDefaultLocales() + + allLangMap = make(map[string]*LangType) + allLangMap["id-ID"] = &LangType{Lang: "id-ID", Name: "Bahasa Indonesia"} + + l := NewLocale("id-ID") + assert.EqualValues(t, "1.000.000", l.PrettyNumber(1000000)) + + l = NewLocale("nosuch") + assert.EqualValues(t, "1,000,000", l.PrettyNumber(1000000)) +} |