@@ -15,17 +15,20 @@ import (
1515 "code.gitea.io/gitea/modules/translation/i18n"
1616
1717 "golang.org/x/text/language"
18+ "golang.org/x/text/message"
19+ "golang.org/x/text/number"
1820)
1921
2022type contextKey struct {}
2123
22- var ContextKey interface {} = & contextKey {}
24+ var ContextKey any = & contextKey {}
2325
2426// Locale represents an interface to translation
2527type Locale interface {
2628 Language () string
27- Tr (string , ... interface {}) string
28- TrN (cnt interface {}, key1 , keyN string , args ... interface {}) string
29+ Tr (string , ... any ) string
30+ TrN (cnt any , key1 , keyN string , args ... any ) string
31+ PrettyNumber (v any ) string
2932}
3033
3134// LangType represents a lang type
@@ -135,6 +138,7 @@ func Match(tags ...language.Tag) language.Tag {
135138type locale struct {
136139 i18n.Locale
137140 Lang , LangName string // these fields are used directly in templates: .i18n.Lang
141+ msgPrinter * message.Printer
138142}
139143
140144// NewLocale return a locale
@@ -147,13 +151,24 @@ func NewLocale(lang string) Locale {
147151 langName := "unknown"
148152 if l , ok := allLangMap [lang ]; ok {
149153 langName = l .Name
154+ } else if len (setting .Langs ) > 0 {
155+ lang = setting .Langs [0 ]
156+ langName = setting .Names [0 ]
150157 }
158+
151159 i18nLocale , _ := i18n .GetLocale (lang )
152- return & locale {
160+ l := & locale {
153161 Locale : i18nLocale ,
154162 Lang : lang ,
155163 LangName : langName ,
156164 }
165+ if langTag , err := language .Parse (lang ); err != nil {
166+ log .Error ("Failed to parse language tag from name %q: %v" , l .Lang , err )
167+ l .msgPrinter = message .NewPrinter (language .English )
168+ } else {
169+ l .msgPrinter = message .NewPrinter (langTag )
170+ }
171+ return l
157172}
158173
159174func (l * locale ) Language () string {
@@ -199,7 +214,7 @@ var trNLangRules = map[string]func(int64) int{
199214}
200215
201216// TrN returns translated message for plural text translation
202- func (l * locale ) TrN (cnt interface {} , key1 , keyN string , args ... interface {} ) string {
217+ func (l * locale ) TrN (cnt any , key1 , keyN string , args ... any ) string {
203218 var c int64
204219 if t , ok := cnt .(int ); ok {
205220 c = int64 (t )
@@ -223,3 +238,8 @@ func (l *locale) TrN(cnt interface{}, key1, keyN string, args ...interface{}) st
223238 }
224239 return l .Tr (keyN , args ... )
225240}
241+
242+ func (l * locale ) PrettyNumber (v any ) string {
243+ // TODO: this mechanism is not good enough, the complete solution is to switch the translation system to ICU message format
244+ return l .msgPrinter .Sprintf ("%v" , number .Decimal (v ))
245+ }
0 commit comments