mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-02-13 17:48:33 -05:00
chore: teach lint-locale about locale_next (#6800)
- Ref: forgejo/forgejo#6203 & forgejo/forgejo#5703 - Moved code around to be reusable, otherwise an straightforward implementation. - Added unit test. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6800 Reviewed-by: 0ko <0ko@noreply.codeberg.org> Co-authored-by: Gusted <postmaster@gusted.xyz> Co-committed-by: Gusted <postmaster@gusted.xyz>
This commit is contained in:
parent
6cdc78ed4f
commit
742e0c6a72
2 changed files with 99 additions and 10 deletions
|
@ -5,6 +5,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json" //nolint:depguard
|
||||
"fmt"
|
||||
"html"
|
||||
"io/fs"
|
||||
|
@ -26,6 +27,8 @@ var (
|
|||
|
||||
// Matches href="", href="#", href="%s", href="#%s", href="%[1]s" and href="#%[1]s".
|
||||
placeHolderRegex = regexp.MustCompile(`href="#?(%s|%\[\d\]s)?"`)
|
||||
|
||||
dmp = diffmatchpatch.New()
|
||||
)
|
||||
|
||||
func initBlueMondayPolicy() {
|
||||
|
@ -79,6 +82,21 @@ func preprocessTranslationValue(value string) string {
|
|||
return value
|
||||
}
|
||||
|
||||
func checkValue(trKey, value string) []string {
|
||||
keyValue := preprocessTranslationValue(value)
|
||||
|
||||
if html.UnescapeString(policy.Sanitize(keyValue)) == keyValue {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a nice diff of the difference.
|
||||
diffs := dmp.DiffMain(keyValue, html.UnescapeString(policy.Sanitize(keyValue)), false)
|
||||
diffs = dmp.DiffCleanupSemantic(diffs)
|
||||
diffs = dmp.DiffCleanupEfficiency(diffs)
|
||||
|
||||
return []string{trKey + ": " + dmp.DiffPrettyText(diffs)}
|
||||
}
|
||||
|
||||
func checkLocaleContent(localeContent []byte) []string {
|
||||
// Same configuration as Forgejo uses.
|
||||
cfg := ini.Empty(ini.LoadOptions{
|
||||
|
@ -90,9 +108,7 @@ func checkLocaleContent(localeContent []byte) []string {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
dmp := diffmatchpatch.New()
|
||||
errors := []string{}
|
||||
|
||||
for _, section := range cfg.Sections() {
|
||||
for _, key := range section.Keys() {
|
||||
var trKey string
|
||||
|
@ -102,16 +118,27 @@ func checkLocaleContent(localeContent []byte) []string {
|
|||
trKey = section.Name() + "." + key.Name()
|
||||
}
|
||||
|
||||
keyValue := preprocessTranslationValue(key.Value())
|
||||
errors = append(errors, checkValue(trKey, key.Value())...)
|
||||
}
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
if html.UnescapeString(policy.Sanitize(keyValue)) != keyValue {
|
||||
// Create a nice diff of the difference.
|
||||
diffs := dmp.DiffMain(keyValue, html.UnescapeString(policy.Sanitize(keyValue)), false)
|
||||
diffs = dmp.DiffCleanupSemantic(diffs)
|
||||
diffs = dmp.DiffCleanupEfficiency(diffs)
|
||||
func checkLocaleNextContent(data map[string]any, trKey ...string) []string {
|
||||
errors := []string{}
|
||||
for key, value := range data {
|
||||
currentKey := key
|
||||
if len(trKey) == 1 {
|
||||
currentKey = trKey[0] + "." + key
|
||||
}
|
||||
|
||||
errors = append(errors, trKey+": "+dmp.DiffPrettyText(diffs))
|
||||
}
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
errors = append(errors, checkValue(currentKey, value)...)
|
||||
case map[string]any:
|
||||
errors = append(errors, checkLocaleNextContent(value, currentKey)...)
|
||||
default:
|
||||
panic(fmt.Sprintf("Unexpected type during linting locale next: %s - %T", currentKey, value))
|
||||
}
|
||||
}
|
||||
return errors
|
||||
|
@ -127,6 +154,7 @@ func main() {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
// Safety check that we are not reading the wrong directory.
|
||||
if !slices.ContainsFunc(localeFiles, func(e fs.DirEntry) bool { return strings.HasSuffix(e.Name(), ".ini") }) {
|
||||
fmt.Println("No locale files found")
|
||||
os.Exit(1)
|
||||
|
@ -151,5 +179,37 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
// Check the locale next.
|
||||
localeDir = filepath.Join("options", "locale_next")
|
||||
localeFiles, err = os.ReadDir(localeDir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Safety check that we are not reading the wrong directory.
|
||||
if !slices.ContainsFunc(localeFiles, func(e fs.DirEntry) bool { return strings.HasSuffix(e.Name(), ".json") }) {
|
||||
fmt.Println("No locale_next files found")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for _, localeFile := range localeFiles {
|
||||
localeContent, err := os.ReadFile(filepath.Join(localeDir, localeFile.Name()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var localeData map[string]any
|
||||
if err := json.Unmarshal(localeContent, &localeData); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := checkLocaleNextContent(localeData); len(err) > 0 {
|
||||
fmt.Println(localeFile.Name())
|
||||
fmt.Println(strings.Join(err, "\n"))
|
||||
fmt.Println()
|
||||
exitCode = 1
|
||||
}
|
||||
}
|
||||
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
|
|
@ -63,3 +63,32 @@ func TestLocalizationPolicy(t *testing.T) {
|
|||
assert.EqualValues(t, []string{"key: و\x1b[31m \x1b[0m\x1b[32m\u00a0\x1b[0m"}, checkLocaleContent([]byte(`key = و `)))
|
||||
})
|
||||
}
|
||||
|
||||
func TestNextLocalizationPolicy(t *testing.T) {
|
||||
initBlueMondayPolicy()
|
||||
initRemoveTags()
|
||||
|
||||
t.Run("Nested locales", func(t *testing.T) {
|
||||
assert.Empty(t, checkLocaleNextContent(map[string]any{
|
||||
"settings": map[string]any{
|
||||
"hidden_comment_types_description": `Comment types checked here will not be shown inside issue pages. Checking "Label" for example removes all "<user> added/removed <label>" comments.`,
|
||||
},
|
||||
}))
|
||||
|
||||
assert.EqualValues(t, []string{"settings.hidden_comment_types_description: \"\x1b[31m<not-an-allowed-key>\x1b[0m REPLACED-TAG\""}, checkLocaleNextContent(map[string]any{
|
||||
"settings": map[string]any{
|
||||
"hidden_comment_types_description": `"<not-an-allowed-key> <label>"`,
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
t.Run("Flat locales", func(t *testing.T) {
|
||||
assert.Empty(t, checkLocaleNextContent(map[string]any{
|
||||
"settings.hidden_comment_types_description": `Comment types checked here will not be shown inside issue pages. Checking "Label" for example removes all "<user> added/removed <label>" comments.`,
|
||||
}))
|
||||
|
||||
assert.EqualValues(t, []string{"settings.hidden_comment_types_description: \"\x1b[31m<not-an-allowed-key>\x1b[0m REPLACED-TAG\""}, checkLocaleNextContent(map[string]any{
|
||||
"settings.hidden_comment_types_description": `"<not-an-allowed-key> <label>"`,
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue