aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2023-03-31 12:16:41 +0800
committerGitHub <noreply@github.com>2023-03-31 12:16:41 +0800
commit288c2e8c48991e5e425fd5ffe1959f4b3d0b675a (patch)
tree831ad0b2bd2da5435a8a53f6cee0f03540bcd242
parentd5feb10aca0b309dce17a13255b4030f0a0cfe1b (diff)
downloadgitea-288c2e8c48991e5e425fd5ffe1959f4b3d0b675a.tar.gz
gitea-288c2e8c48991e5e425fd5ffe1959f4b3d0b675a.zip
Clarify Gitea/Crowdin locale behaviors, add tests for LocaleStore, fix some strings with semicolons (#23819)
Follow #23633 and #23240 Close #23814 Now we almost have a complete test set for Gitea's LocalStore. This PR is still a quick fix for the legacy locale system (see the TODOs), to resolve the problems fundamentally, it needs more work in the future.
-rwxr-xr-xbuild/update-locales.sh15
-rw-r--r--modules/translation/i18n/i18n_test.go54
-rw-r--r--options/locale/locale_en-US.ini8
3 files changed, 62 insertions, 15 deletions
diff --git a/build/update-locales.sh b/build/update-locales.sh
index 596ddfec03..6f9ee334be 100755
--- a/build/update-locales.sh
+++ b/build/update-locales.sh
@@ -17,17 +17,10 @@ fi
mv ./options/locale/locale_en-US.ini ./options/
-# the "ini" library for locale has many quirks
-# * `a="xx"` gets `xx` (no quote)
-# * `a=x\"y` gets `x\"y` (no unescaping)
-# * `a="x\"y"` gets `"x\"y"` (no unescaping, the quotes are still there)
-# * `a='x\"y'` gets `x\"y` (no unescaping, no quote)
-# * `a="foo` gets `"foo` (although the quote is not closed)
-# * 'a=`foo`' works like single-quote
-# crowdin needs the strings to be quoted correctly and doesn't like incomplete quotes
-# crowdin always outputs quoted strings if there are quotes in the strings.
-
-# this script helps to unquote the crowdin outputs for the quirky ini library
+# the "ini" library for locale has many quirks, its behavior is different from Crowdin.
+# see i18n_test.go for more details
+
+# this script helps to unquote the Crowdin outputs for the quirky ini library
# * find all `key="...\"..."` lines
# * remove the leading quote
# * remove the trailing quote
diff --git a/modules/translation/i18n/i18n_test.go b/modules/translation/i18n/i18n_test.go
index 76a91522ba..085d03811f 100644
--- a/modules/translation/i18n/i18n_test.go
+++ b/modules/translation/i18n/i18n_test.go
@@ -4,6 +4,7 @@
package i18n
import (
+ "strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -75,3 +76,56 @@ c=22
assert.Equal(t, "21", ls.Tr("lang1", "b"))
assert.Equal(t, "22", ls.Tr("lang1", "c"))
}
+
+func TestLocaleStoreQuirks(t *testing.T) {
+ const nl = "\n"
+ q := func(q1, s string, q2 ...string) string {
+ return q1 + s + strings.Join(q2, "")
+ }
+ testDataList := []struct {
+ in string
+ out string
+ hint string
+ }{
+ {` xx`, `xx`, "simple, no quote"},
+ {`" xx"`, ` xx`, "simple, double-quote"},
+ {`' xx'`, ` xx`, "simple, single-quote"},
+ {"` xx`", ` xx`, "simple, back-quote"},
+
+ {`x\"y`, `x\"y`, "no unescape, simple"},
+ {q(`"`, `x\"y`, `"`), `"x\"y"`, "unescape, double-quote"},
+ {q(`'`, `x\"y`, `'`), `x\"y`, "no unescape, single-quote"},
+ {q("`", `x\"y`, "`"), `x\"y`, "no unescape, back-quote"},
+
+ {q(`"`, `x\"y`) + nl + "b=", `"x\"y`, "half open, double-quote"},
+ {q(`'`, `x\"y`) + nl + "b=", `'x\"y`, "half open, single-quote"},
+ {q("`", `x\"y`) + nl + "b=`", `x\"y` + nl + "b=", "half open, back-quote, multi-line"},
+
+ {`x ; y`, `x ; y`, "inline comment (;)"},
+ {`x # y`, `x # y`, "inline comment (#)"},
+ {`x \; y`, `x ; y`, `inline comment (\;)`},
+ {`x \# y`, `x # y`, `inline comment (\#)`},
+ }
+
+ for _, testData := range testDataList {
+ ls := NewLocaleStore()
+ err := ls.AddLocaleByIni("lang1", "Lang1", []byte("a="+testData.in), nil)
+ assert.NoError(t, err, testData.hint)
+ assert.Equal(t, testData.out, ls.Tr("lang1", "a"), testData.hint)
+ assert.NoError(t, ls.Close())
+ }
+
+ // TODO: Crowdin needs the strings to be quoted correctly and doesn't like incomplete quotes
+ // and Crowdin always outputs quoted strings if there are quotes in the strings.
+ // So, Gitea's `key="quoted" unquoted` content shouldn't be used on Crowdin directly,
+ // it should be converted to `key="\"quoted\" unquoted"` first.
+ // TODO: We can not use UnescapeValueDoubleQuotes=true, because there are a lot of back-quotes in en-US.ini,
+ // then Crowdin will output:
+ // > key = "`x \" y`"
+ // Then Gitea will read a string with back-quotes, which is incorrect.
+ // TODO: Crowdin might generate multi-line strings, quoted by double-quote, it's not supported by LocaleStore
+ // LocaleStore uses back-quote for multi-line strings, it's not supported by Crowdin.
+ // TODO: Crowdin doesn't support back-quote as string quoter, it mainly uses double-quote
+ // so, the following line will be parsed as: value="`first", comment="second`" on Crowdin
+ // > a = `first; second`
+}
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 0d5b2c9a44..347f5e4312 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -2140,10 +2140,10 @@ settings.dismiss_stale_approvals_desc = When new commits that change the content
settings.require_signed_commits = Require Signed Commits
settings.require_signed_commits_desc = Reject pushes to this branch if they are unsigned or unverifiable.
settings.protect_branch_name_pattern = Protected Branch Name Pattern
-settings.protect_protected_file_patterns = `Protected file patterns (separated using semicolon ';'):`
-settings.protect_protected_file_patterns_desc = `Protected files are not allowed to be changed directly even if user has rights to add, edit, or delete files in this branch. Multiple patterns can be separated using semicolon (';'). See <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.`
-settings.protect_unprotected_file_patterns = `Unprotected file patterns (separated using semicolon ';'):`
-settings.protect_unprotected_file_patterns_desc = `Unprotected files that are allowed to be changed directly if user has write access, bypassing push restriction. Multiple patterns can be separated using semicolon (';'). See <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.`
+settings.protect_protected_file_patterns = "Protected file patterns (separated using semicolon ';'):"
+settings.protect_protected_file_patterns_desc = "Protected files are not allowed to be changed directly even if user has rights to add, edit, or delete files in this branch. Multiple patterns can be separated using semicolon (';'). See <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>."
+settings.protect_unprotected_file_patterns = "Unprotected file patterns (separated using semicolon ';'):"
+settings.protect_unprotected_file_patterns_desc = "Unprotected files that are allowed to be changed directly if user has write access, bypassing push restriction. Multiple patterns can be separated using semicolon (';'). See <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>."
settings.add_protected_branch = Enable protection
settings.delete_protected_branch = Disable protection
settings.update_protect_branch_success = Branch protection for rule '%s' has been updated.