diff --git a/.forgejo/workflows/renovate.yml b/.forgejo/workflows/renovate.yml index 1851833caf..c327691033 100644 --- a/.forgejo/workflows/renovate.yml +++ b/.forgejo/workflows/renovate.yml @@ -18,6 +18,9 @@ on: env: RENOVATE_DRY_RUN: ${{ (github.event_name != 'schedule' && github.ref_name != github.event.repository.default_branch) && 'full' || '' }} RENOVATE_REPOSITORIES: ${{ github.repository }} + # fix because 10.0.0-58-7e1df53+gitea-1.22.0 < 10.0.0 for semver + # and codeberg api returns such versions from `git describe --tags` + RENOVATE_X_PLATFORM_VERSION: 10.0.0+gitea-1.22.0 jobs: renovate: @@ -25,7 +28,7 @@ jobs: runs-on: docker container: - image: data.forgejo.org/renovate/renovate:39.156.1 + image: data.forgejo.org/renovate/renovate:39.158.2 steps: - name: Load renovate repo cache diff --git a/Dockerfile b/Dockerfile index 2df13c2326..4b2eca7a4c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/xx AS xx -FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.23-alpine3.21 as build-env +FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.23-alpine3.21 AS build-env ARG GOPROXY ENV GOPROXY=${GOPROXY:-direct} diff --git a/Dockerfile.rootless b/Dockerfile.rootless index 8aec4d828f..1d3f0e4538 100644 --- a/Dockerfile.rootless +++ b/Dockerfile.rootless @@ -1,6 +1,6 @@ FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/xx AS xx -FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.23-alpine3.21 as build-env +FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.23-alpine3.21 AS build-env ARG GOPROXY ENV GOPROXY=${GOPROXY:-direct} diff --git a/Makefile b/Makefile index b94c32f2e3..fd5f4f5352 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasour DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.29.0 # renovate: datasource=go GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.17.1 # renovate: datasource=go -RENOVATE_NPM_PACKAGE ?= renovate@39.156.1 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate +RENOVATE_NPM_PACKAGE ?= renovate@39.158.2 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate # https://github.com/disposable-email-domains/disposable-email-domains/commits/main/ DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ... diff --git a/build/lint-locale.go b/build/lint-locale.go index 44d320994c..0fb500222f 100644 --- a/build/lint-locale.go +++ b/build/lint-locale.go @@ -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() { @@ -59,9 +62,9 @@ func initRemoveTags() { oldnew := []string{} for _, el := range []string{ "email@example.com", "correu@example.com", "epasts@domens.lv", "email@exemplo.com", "eposta@ornek.com", "email@példa.hu", "email@esempio.it", - "user", "utente", "lietotājs", "gebruiker", "usuário", "Benutzer", "Bruker", "bruger", + "user", "utente", "lietotājs", "gebruiker", "usuário", "Benutzer", "Bruker", "bruger", "użytkownik", "server", "servidor", "kiszolgáló", "serveris", - "label", "etichetta", "etiķete", "rótulo", "Label", "utilizador", "etiket", "iezīme", + "label", "etichetta", "etiķete", "rótulo", "Label", "utilizador", "etiket", "iezīme", "etykieta", } { oldnew = append(oldnew, "<"+el+">", "REPLACED-TAG") } @@ -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) } diff --git a/build/lint-locale_test.go b/build/lint-locale_test.go index b33dc9af2b..408897d781 100644 --- a/build/lint-locale_test.go +++ b/build/lint-locale_test.go @@ -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 " added/removed