From 9b5b7140480a75edb070d4151f585c20d3a08f64 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Sun, 21 Jan 2024 17:38:14 +0000 Subject: [PATCH] [I18n] tooling and process Before: * Translations were imported from Crowdin via Gitea * New strings were added by Forgejo in feature branches but never translated * The build/merge-forgejo-locales.go script in the forgejo-i18n branch added/replaced Forgejo specific strings in the translated files at build time * Conflicts arising from Gitea changes in locale_en-US.ini were resolved by moving around Forgejo strings Transition: * The build/merge-forgejo-locales.go is run once on the source * The result is commited to the forgejo-development branch After: * Translation are exported and imported from translate.codeberg.org * build/crowdin-to-weblate.sh run is run when rebasing (soft-fork) or cherry-picking (hard-fork) to collect new translations from Crowdin via Gitea * In case of a conflict Forgejo translations are authoritative * In the absence of a conflict Crowdin translations are uploaded to Weblate --- build/crowdin-to-weblate.sh | 27 ++++++++ build/merge-forgejo-locales.go | 109 +++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100755 build/crowdin-to-weblate.sh create mode 100644 build/merge-forgejo-locales.go diff --git a/build/crowdin-to-weblate.sh b/build/crowdin-to-weblate.sh new file mode 100755 index 0000000000..877b5d9e07 --- /dev/null +++ b/build/crowdin-to-weblate.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright 2024 The Forgejo Authors +# SPDX-License-Identifier: MIT + +D=/tmp/crowdin-to-weblate +mkdir -p $D + +function checkout() { + if test -d $D/gitea ; then + git -C $D/gitea reset --hard + return + fi + + git clone --depth 1 https://github.com/go-gitea/gitea $D/gitea +} + +function replace() { + go run build/merge-forgejo-locales.go $D/gitea/options/locale + cp -a $D/gitea/options/locale/* options/locale +} + +function run() { + checkout + replace +} + +"$@" diff --git a/build/merge-forgejo-locales.go b/build/merge-forgejo-locales.go new file mode 100644 index 0000000000..eebe12578b --- /dev/null +++ b/build/merge-forgejo-locales.go @@ -0,0 +1,109 @@ +// Copyright 2022 The Forgejo Authors c/o Codeberg e.V.. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +//go:build ignore + +package main + +import ( + "bufio" + "log" + "os" + "regexp" + "strings" +) + +const ( + trimPrefix = "gitea_" + sourceFolder = "options/locales/" +) + +// returns list of locales, still containing the file extension! +func generate_locale_list() []string { + localeFiles, _ := os.ReadDir(sourceFolder) + locales := []string{} + for _, localeFile := range localeFiles { + if !localeFile.IsDir() && strings.HasPrefix(localeFile.Name(), trimPrefix) { + locales = append(locales, strings.TrimPrefix(localeFile.Name(), trimPrefix)) + } + } + return locales +} + +// replace all occurrences of Gitea with Forgejo +func renameGiteaForgejo(filename string) []byte { + file, err := os.Open(filename) + if err != nil { + panic(err) + } + + replacements := []string{ + "Gitea", "Forgejo", + "https://docs.gitea.com/installation/install-from-binary", "https://forgejo.org/download/#installation-from-binary", + "https://github.com/go-gitea/gitea/tree/master/docker", "https://forgejo.org/download/#container-image", + "https://docs.gitea.com/installation/install-from-package", "https://forgejo.org/download", + "https://code.gitea.io/gitea", "https://forgejo.org/download", + "code.gitea.io/gitea", "Forgejo", + `GitHub`, `Codeberg`, + "https://github.com/go-gitea/gitea", "https://codeberg.org/forgejo/forgejo", + "https://blog.gitea.io", "https://forgejo.org/news", + "https://docs.gitea.com/usage/protected-tags", "https://forgejo.org/docs/latest/user/protection/#protected-tags", + "https://docs.gitea.com/usage/webhooks", "https://forgejo.org/docs/latest/user/webhooks/", + } + replacer := strings.NewReplacer(replacements...) + replaced := make(map[string]bool, len(replacements)/2) + count_replaced := func(original string) { + for i := 0; i < len(replacements); i += 2 { + if strings.Contains(original, replacements[i]) { + replaced[replacements[i]] = true + } + } + } + + out := make([]byte, 0, 1024) + scanner := bufio.NewScanner(file) + scanner.Split(bufio.ScanLines) + for scanner.Scan() { + line := scanner.Text() + + if strings.HasPrefix(line, "license_desc=") { + line = strings.Replace(line, "GitHub", "Forgejo", 1) + } + + if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { + out = append(out, []byte(line+"\n")...) + } else if strings.HasPrefix(line, "settings.web_hook_name_gitea") { + out = append(out, []byte(line+"\n")...) + out = append(out, []byte("settings.web_hook_name_forgejo = Forgejo\n")...) + } else if strings.HasPrefix(line, "migrate.gitea.description") { + re := regexp.MustCompile(`(.*Gitea)`) + out = append(out, []byte(re.ReplaceAllString(line, "${1}/Forgejo")+"\n")...) + } else { + count_replaced(line) + out = append(out, []byte(replacer.Replace(line)+"\n")...) + } + } + file.Close() + if strings.HasSuffix(filename, "gitea_en-US.ini") { + for i := 0; i < len(replacements); i += 2 { + if replaced[replacements[i]] == false { + log.Fatalf("%s was never used to replace something in %s, it is obsolete and must be updated", replacements[i], filename) + } + } + } + return out +} + +func main() { + d := os.Args[1] + files, err := os.ReadDir(d) + if err != nil { + log.Fatal(err) + } + + for _, f := range files { + p := d + "/" + f.Name() + os.WriteFile(p, renameGiteaForgejo(p), 0o644) + } +}