chore(l10n): remove base Lokalise TS file, update README

- the l10n workflow using an external service is no longer used
- update the I18N.md readme file

Fixes #21334
This commit is contained in:
Lukáš Tinkl
2026-07-03 00:22:47 +02:00
committed by Lukáš Tinkl
parent 35211682b3
commit ef2cb090ae
4 changed files with 5 additions and 23247 deletions
+5 -8
View File
@@ -16,13 +16,10 @@ $ make update-translations
The resulting binary QM files are also produced by simply running `make` via `make compile-translations` subtarget
### Update translations
1. Create pull request with exported translations using lokalise.com, see [docs](https://docs.lokalise.com/en/articles/1684090-github)
1. Simply attach the changed TS files to your PR; we have CI checks in place that enforce this
2. If adding a brand new language, make sure to add the new TS file to `ui/i18n/CMakeLists.txt` as well
## Translator workflow
Lokalise is a continuous localization and translation management platform. It integrates into development workflow and automates localization process.
Lokalise workflow:
1. Upload base strings (`qml_base.ts` and `qml_en.ts` files) to Lokalise project. This is done automatically, Lokalise auto-pulls changes done to master's TS files.
2. Translate strings to target languages. Target languages are driven by Lokalise configuration. Translations are done by community
3. Export *.ts files with translations (e.g. qml_de.ts, qml_fr.ts)
4. Create pull request with exported translations
1. For editing TS files, we use the Qt's official [Linguist](https://doc.qt.io/qt-6/linguist-translators.html) tool
2. For AI guided translations, please refer to the respective Linguist's chapter: [AI translation](https://doc.qt.io/qt-6/linguist-ai-translation.html)
3. Recommended AI model: [translategemma:27b](https://ollama.com/library/translategemma:27b); offers large enough context window, and supports a wide array of 55 languages
-1
View File
@@ -670,7 +670,6 @@ log-update-translations:
update-translations: | log-update-translations
cmake -S $(TS_SOURCE_DIR) -B $(TS_BUILD_DIR) -Wno-dev $(TS_CMAKE_PARAMS) $(HANDLE_OUTPUT)
cmake --build $(TS_BUILD_DIR) --target update_application_translations $(HANDLE_OUTPUT)
+ cd scripts/translationScripts && go run fixup-base-ts-for-lokalise.go $(HANDLE_OUTPUT)
log-compile-translations:
echo -e "\033[92mCompiling:\033[39m translations"
@@ -1,138 +0,0 @@
package main
import (
"encoding/xml"
"fmt"
"os"
"strings"
)
// TS represents the root TS element
type TS struct {
XMLName xml.Name `xml:"TS"`
Language string `xml:"language,attr"`
SourceLanguage string `xml:"sourcelanguage,attr"`
Contexts []Context `xml:"context"`
}
// Context represents a context element
type Context struct {
Name string `xml:"name"`
Messages []Message `xml:"message"`
}
// Message represents a message element
type Message struct {
Numerus string `xml:"numerus,attr,omitempty"`
Source string `xml:"source"`
Comment string `xml:"comment,omitempty"`
Translation Translation `xml:"translation"`
Extra []xml.Token `xml:",any"` // For any extra elements like unfinished
}
// Translation represents a translation element, handling numerus forms
type Translation struct {
Type string `xml:"type,attr,omitempty"`
Text string `xml:",chardata"`
NumerusForms []NumerusForm `xml:"numerusform,omitempty"`
}
// NumerusForm represents a numerusform element
type NumerusForm struct {
Text string `xml:",chardata"`
}
func main() {
// Relative paths from project root
baseFile := "../../ui/i18n/qml_base_en.ts"
pluralFile := "../../ui/i18n/qml_en.ts"
outputFile := "../../ui/i18n/qml_base_lokalise_en.ts"
// Parse the base TS file
baseData, err := os.ReadFile(baseFile)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading %s: %v\n", baseFile, err)
os.Exit(1)
}
var baseTS TS
if err := xml.Unmarshal(baseData, &baseTS); err != nil {
fmt.Fprintf(os.Stderr, "Error parsing %s: %v\n", baseFile, err)
os.Exit(1)
}
// Parse the plural TS file
pluralData, err := os.ReadFile(pluralFile)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading %s: %v\n", pluralFile, err)
os.Exit(1)
}
var pluralTS TS
if err := xml.Unmarshal(pluralData, &pluralTS); err != nil {
fmt.Fprintf(os.Stderr, "Error parsing %s: %v\n", pluralFile, err)
os.Exit(1)
}
// Create a dictionary for quick lookup of plural translations by source
pluralLookup := make(map[string]Translation)
for _, context := range pluralTS.Contexts {
for _, message := range context.Messages {
if message.Source != "" {
pluralLookup[message.Source] = message.Translation
}
}
}
// Process each message in the base file
for i := range baseTS.Contexts {
context := &baseTS.Contexts[i]
contextName := context.Name
for j := range context.Messages {
message := &context.Messages[j]
// Add comment if missing
if message.Comment == "" {
message.Comment = contextName
}
if message.Numerus == "yes" && message.Source != "" {
if pluralTrans, exists := pluralLookup[message.Source]; exists {
message.Translation = pluralTrans
// Clean up whitespace in text and numerus forms
message.Translation.Text = strings.TrimSpace(message.Translation.Text)
for k := range message.Translation.NumerusForms {
message.Translation.NumerusForms[k].Text = strings.TrimSpace(message.Translation.NumerusForms[k].Text)
}
// Remove unfinished type
if message.Translation.Type == "unfinished" {
message.Translation.Type = ""
}
}
} else {
// Set translation to source, trimmed
message.Translation.Text = strings.TrimSpace(message.Source)
message.Translation.NumerusForms = nil // Clear numerus forms
// Remove unfinished type
if message.Translation.Type == "unfinished" {
message.Translation.Type = ""
}
}
}
}
// Set language attributes
baseTS.Language = "en"
baseTS.SourceLanguage = "en"
// Write the modified XML to output file
outputData, err := xml.MarshalIndent(baseTS, "", " ")
if err != nil {
fmt.Fprintf(os.Stderr, "Error marshaling XML: %v\n", err)
os.Exit(1)
}
// Add XML declaration
outputData = []byte(xml.Header + string(outputData))
if err := os.WriteFile(outputFile, outputData, 0644); err != nil {
fmt.Fprintf(os.Stderr, "Error writing to %s: %v\n", outputFile, err)
os.Exit(1)
}
fmt.Printf("Successfully transformed %s to %s\n", baseFile, outputFile)
}
File diff suppressed because it is too large Load Diff