summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2022-01-02 11:33:57 +0800
committerGitHub <noreply@github.com>2022-01-02 04:33:57 +0100
commite61b390d545919244141b699b28e3fbc42adc66f (patch)
treede17418a260234e1043a6d3a130c2b4a8c27640a /modules
parent88da7a7174f9c1568cc2d8d084d6b05a8d268690 (diff)
downloadgitea-e61b390d545919244141b699b28e3fbc42adc66f.tar.gz
gitea-e61b390d545919244141b699b28e3fbc42adc66f.zip
Unify and simplify TrN for i18n (#18141)
Refer: https://github.com/go-gitea/gitea/pull/18135#issuecomment-1003246099 Now we have a unique and simple `TrN`, and make the fix of PR #18135 also use the better `TrN` logic.
Diffstat (limited to 'modules')
-rw-r--r--modules/csv/csv_test.go36
-rw-r--r--modules/templates/helper.go64
-rw-r--r--modules/test/context_tests.go4
-rw-r--r--modules/translation/translation.go65
4 files changed, 93 insertions, 76 deletions
diff --git a/modules/csv/csv_test.go b/modules/csv/csv_test.go
index d72c3e3a73..1612a66953 100644
--- a/modules/csv/csv_test.go
+++ b/modules/csv/csv_test.go
@@ -8,6 +8,7 @@ import (
"bytes"
"encoding/csv"
"io"
+ "strconv"
"strings"
"testing"
@@ -21,14 +22,21 @@ func TestCreateReader(t *testing.T) {
assert.Equal(t, ',', rd.Comma)
}
-//nolint
+func decodeSlashes(t *testing.T, s string) string {
+ s = strings.ReplaceAll(s, "\n", "\\n")
+ s = strings.ReplaceAll(s, "\"", "\\\"")
+ decoded, err := strconv.Unquote(`"` + s + `"`)
+ assert.NoError(t, err, "unable to decode string")
+ return decoded
+}
+
func TestCreateReaderAndDetermineDelimiter(t *testing.T) {
var cases = []struct {
csv string
expectedRows [][]string
expectedDelimiter rune
}{
- // case 0 - semicolon delmited
+ // case 0 - semicolon delimited
{
csv: `a;b;c
1;2;3
@@ -47,11 +55,11 @@ a, b c
e f
g h i
j l
-m n,
+m n,\t
p q r
u
v w x
-y
+y\t\t
`,
expectedRows: [][]string{
{"col1", "col2", "col3"},
@@ -74,7 +82,7 @@ y
a, b, c
d,e,f
,h, i
-j, ,
+j, ,\x20
, , `,
expectedRows: [][]string{
{"col1", "col2", "col3"},
@@ -89,7 +97,7 @@ j, ,
}
for n, c := range cases {
- rd, err := CreateReaderAndDetermineDelimiter(nil, strings.NewReader(c.csv))
+ rd, err := CreateReaderAndDetermineDelimiter(nil, strings.NewReader(decodeSlashes(t, c.csv)))
assert.NoError(t, err, "case %d: should not throw error: %v\n", n, err)
assert.EqualValues(t, c.expectedDelimiter, rd.Comma, "case %d: delimiter should be '%c', got '%c'", n, c.expectedDelimiter, rd.Comma)
rows, err := rd.ReadAll()
@@ -222,7 +230,7 @@ John Doe john@doe.com This,note,had,a,lot,of,commas,to,test,delimters`,
}
for n, c := range cases {
- delimiter := determineDelimiter(&markup.RenderContext{Filename: c.filename}, []byte(c.csv))
+ delimiter := determineDelimiter(&markup.RenderContext{Filename: c.filename}, []byte(decodeSlashes(t, c.csv)))
assert.EqualValues(t, c.expectedDelimiter, delimiter, "case %d: delimiter should be equal, expected '%c' got '%c'", n, c.expectedDelimiter, delimiter)
}
}
@@ -287,7 +295,7 @@ abc | |123
}
for n, c := range cases {
- modifiedText := removeQuotedString(c.text)
+ modifiedText := removeQuotedString(decodeSlashes(t, c.text))
assert.EqualValues(t, c.expectedText, modifiedText, "case %d: modified text should be equal", n)
}
}
@@ -353,7 +361,7 @@ John Doe john@doe.com This,note,had,a,lot,of,commas,to,test,delimters`,
quoted,
text," a
2 "some,
-quoted,
+quoted,\t
text," b
3 "some,
quoted,
@@ -442,7 +450,7 @@ jkl`,
}
for n, c := range cases {
- delimiter := guessDelimiter([]byte(c.csv))
+ delimiter := guessDelimiter([]byte(decodeSlashes(t, c.csv)))
assert.EqualValues(t, c.expectedDelimiter, delimiter, "case %d: delimiter should be equal, expected '%c' got '%c'", n, c.expectedDelimiter, delimiter)
}
}
@@ -459,7 +467,7 @@ func TestGuessFromBeforeAfterQuotes(t *testing.T) {
quoted,
text," a
2 "some,
-quoted,
+quoted,\t
text," b
3 "some,
quoted,
@@ -534,7 +542,7 @@ a|"he said, ""here I am"""`,
}
for n, c := range cases {
- delimiter := guessFromBeforeAfterQuotes([]byte(c.csv))
+ delimiter := guessFromBeforeAfterQuotes([]byte(decodeSlashes(t, c.csv)))
assert.EqualValues(t, c.expectedDelimiter, delimiter, "case %d: delimiter should be equal, expected '%c' got '%c'", n, c.expectedDelimiter, delimiter)
}
}
@@ -549,6 +557,10 @@ 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 TestFormatError(t *testing.T) {
var cases = []struct {
err error
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index a05c0c1a95..fc07b49c71 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -239,7 +239,6 @@ func NewFuncMap() []template.FuncMap {
"DisableImportLocal": func() bool {
return !setting.ImportLocalPaths
},
- "TrN": TrN,
"Dict": func(values ...interface{}) (map[string]interface{}, error) {
if len(values)%2 != 0 {
return nil, errors.New("invalid dict call")
@@ -857,69 +856,6 @@ func DiffLineTypeToStr(diffType int) string {
return "same"
}
-// Language specific rules for translating plural texts
-var trNLangRules = map[string]func(int64) int{
- "en-US": func(cnt int64) int {
- if cnt == 1 {
- return 0
- }
- return 1
- },
- "lv-LV": func(cnt int64) int {
- if cnt%10 == 1 && cnt%100 != 11 {
- return 0
- }
- return 1
- },
- "ru-RU": func(cnt int64) int {
- if cnt%10 == 1 && cnt%100 != 11 {
- return 0
- }
- return 1
- },
- "zh-CN": func(cnt int64) int {
- return 0
- },
- "zh-HK": func(cnt int64) int {
- return 0
- },
- "zh-TW": func(cnt int64) int {
- return 0
- },
- "fr-FR": func(cnt int64) int {
- if cnt > -2 && cnt < 2 {
- return 0
- }
- return 1
- },
-}
-
-// TrN returns key to be used for plural text translation
-func TrN(lang string, cnt interface{}, key1, keyN string) string {
- var c int64
- if t, ok := cnt.(int); ok {
- c = int64(t)
- } else if t, ok := cnt.(int16); ok {
- c = int64(t)
- } else if t, ok := cnt.(int32); ok {
- c = int64(t)
- } else if t, ok := cnt.(int64); ok {
- c = t
- } else {
- return keyN
- }
-
- ruleFunc, ok := trNLangRules[lang]
- if !ok {
- ruleFunc = trNLangRules["en-US"]
- }
-
- if ruleFunc(c) == 0 {
- return key1
- }
- return keyN
-}
-
// MigrationIcon returns a SVG name matching the service an issue/comment was migrated from
func MigrationIcon(hostname string) string {
switch hostname {
diff --git a/modules/test/context_tests.go b/modules/test/context_tests.go
index 1f893122f3..62ec21f6fe 100644
--- a/modules/test/context_tests.go
+++ b/modules/test/context_tests.go
@@ -103,6 +103,10 @@ func (l mockLocale) Tr(s string, _ ...interface{}) string {
return s
}
+func (l mockLocale) TrN(_cnt interface{}, key1, _keyN string, _args ...interface{}) string {
+ return key1
+}
+
type mockResponseWriter struct {
httptest.ResponseRecorder
size int
diff --git a/modules/translation/translation.go b/modules/translation/translation.go
index 77cc9ac7f5..af1e5d25df 100644
--- a/modules/translation/translation.go
+++ b/modules/translation/translation.go
@@ -17,6 +17,7 @@ import (
type Locale interface {
Language() string
Tr(string, ...interface{}) string
+ TrN(cnt interface{}, key1, keyN string, args ...interface{}) string
}
// LangType represents a lang type
@@ -99,3 +100,67 @@ func (l *locale) Language() string {
func (l *locale) Tr(format string, args ...interface{}) string {
return i18n.Tr(l.Lang, format, args...)
}
+
+// Language specific rules for translating plural texts
+var trNLangRules = map[string]func(int64) int{
+ // the default rule is "en-US" if a language isn't listed here
+ "en-US": func(cnt int64) int {
+ if cnt == 1 {
+ return 0
+ }
+ return 1
+ },
+ "lv-LV": func(cnt int64) int {
+ if cnt%10 == 1 && cnt%100 != 11 {
+ return 0
+ }
+ return 1
+ },
+ "ru-RU": func(cnt int64) int {
+ if cnt%10 == 1 && cnt%100 != 11 {
+ return 0
+ }
+ return 1
+ },
+ "zh-CN": func(cnt int64) int {
+ return 0
+ },
+ "zh-HK": func(cnt int64) int {
+ return 0
+ },
+ "zh-TW": func(cnt int64) int {
+ return 0
+ },
+ "fr-FR": func(cnt int64) int {
+ if cnt > -2 && cnt < 2 {
+ return 0
+ }
+ return 1
+ },
+}
+
+// TrN returns translated message for plural text translation
+func (l *locale) TrN(cnt interface{}, key1, keyN string, args ...interface{}) string {
+ var c int64
+ if t, ok := cnt.(int); ok {
+ c = int64(t)
+ } else if t, ok := cnt.(int16); ok {
+ c = int64(t)
+ } else if t, ok := cnt.(int32); ok {
+ c = int64(t)
+ } else if t, ok := cnt.(int64); ok {
+ c = t
+ } else {
+ return l.Tr(keyN, args...)
+ }
+
+ ruleFunc, ok := trNLangRules[l.Lang]
+ if !ok {
+ ruleFunc = trNLangRules["en-US"]
+ }
+
+ if ruleFunc(c) == 0 {
+ return l.Tr(key1, args...)
+ }
+ return l.Tr(keyN, args...)
+}