Skip to content

Commit 9afa7ef

Browse files
committed
chore(Makefile): create targets to update and build translations
- create dedicated Makefile targets: `update-translations` and `compile-translations` that extract/update/merge and compile the TS files respectively - these targets can then later be invoked externally by CI automation - provide a small manual Python script that transforms the empty `qml_base_en.ts` into a pre-filled `qml_base_lokalise_en.ts` for the purpose of AI enabled translations on Lokalise - add a sample Czech translation to test the changes (to be finished later separately) - update the i18n README Fixes #18820
1 parent ac2ac73 commit 9afa7ef

File tree

10 files changed

+38936
-1023
lines changed

10 files changed

+38936
-1023
lines changed

I18N.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ There are excellent manuals detailing the translation process for [developers](h
88
### Update base translations file
99
1. Update the base TS files (`qml_base.ts` and `qml_en.ts`, the latter serving only for the purpose of providing plural forms for English):
1010
```bash
11-
$ cd scripts/translationScripts
12-
$ python update-en-ts.py
11+
$ make update-translations
1312
```
1413
2. The updated TS files are created in the `ui/i18n/` directory
1514
3. Ensure the updated base files land in master
1615

16+
The resulting binary QM files are also produced by simply running `make` via `make compile-translations` subtarget
17+
1718
### Update translations
1819
1. Create pull request with exported translations using lokalise.com, see [docs](https://docs.lokalise.com/en/articles/1684090-github)
1920

Makefile

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ BUILD_SYSTEM_DIR := vendor/nimbus-build-system
2222
check-pkg-target-macos \
2323
check-pkg-target-windows \
2424
clean \
25+
update-translations \
2526
compile-translations \
2627
deps \
2728
nim_status_client \
@@ -39,11 +40,11 @@ BUILD_SYSTEM_DIR := vendor/nimbus-build-system
3940
status-keycard-go \
4041
statusq-sanity-checker \
4142
run-statusq-sanity-checker \
42-
statusq-tests \
43-
run-statusq-tests \
44-
storybook-build \
45-
run-storybook \
46-
run-storybook-tests \
43+
statusq-tests \
44+
run-statusq-tests \
45+
storybook-build \
46+
run-storybook \
47+
run-storybook-tests \
4748
update
4849

4950
ifeq ($(NIM_PARAMS),)
@@ -532,18 +533,26 @@ $(UI_RESOURCES): $(UI_SOURCES) | check-qt-dir
532533

533534
rcc: $(UI_RESOURCES)
534535

535-
TS_SOURCES := $(shell find ui/i18n -iname '*.ts') # ui/i18n/qml_*.ts
536-
QM_BINARIES := $(shell find ui/i18n -iname "*.ts" | sed 's/\.ts/\.qm/' | sed 's/ui/bin/') # bin/i18n/qml_*.qm
536+
TS_SOURCE_DIR := ui/i18n
537+
TS_BUILD_DIR := $(TS_SOURCE_DIR)/build
537538

538-
$(QM_BINARIES): TS_FILE = $(shell echo $@ | sed 's/\.qm/\.ts/' | sed 's/bin/ui/')
539-
$(QM_BINARIES): $(TS_SOURCES) | check-qt-dir
540-
mkdir -p bin/i18n
541-
lrelease -removeidentical $(TS_FILE) -qm $@ $(HANDLE_OUTPUT)
539+
log-update-translations:
540+
echo -e "\033[92mUpdating:\033[39m translations"
541+
542+
update-translations: | log-update-translations
543+
cmake -S $(TS_SOURCE_DIR) -B $(TS_BUILD_DIR) -Wno-dev $(HANDLE_OUTPUT)
544+
cmake --build $(TS_BUILD_DIR) --target update_application_translations $(HANDLE_OUTPUT)
545+
# + cd scripts/translationScripts && ./fixup-base-ts-for-lokalise.py $(HANDLE_OUTPUT)
542546

543547
log-compile-translations:
544548
echo -e "\033[92mCompiling:\033[39m translations"
545549

546-
compile-translations: | log-compile-translations $(QM_BINARIES)
550+
compile-translations: | update-translations log-compile-translations
551+
cmake -S $(TS_SOURCE_DIR) -B $(TS_BUILD_DIR) -Wno-dev $(HANDLE_OUTPUT)
552+
cmake --build $(TS_BUILD_DIR) --target compile_application_translations $(HANDLE_OUTPUT)
553+
554+
clean-translations:
555+
rm -rf $(TS_BUILD_DIR)
547556

548557
# used to override the default number of kdf iterations for sqlcipher
549558
KDF_ITERATIONS ?= 0
@@ -839,7 +848,7 @@ zip-windows: check-pkg-target-windows $(STATUS_CLIENT_7Z)
839848
clean-destdir:
840849
rm -rf bin/*
841850

842-
clean: | clean-common clean-destdir statusq-clean status-go-clean dotherside-clean storybook-clean
851+
clean: | clean-common clean-destdir statusq-clean status-go-clean dotherside-clean storybook-clean clean-translations
843852
rm -rf node_modules bottles/* pkg/* tmp/* $(STATUSKEYCARDGO)
844853
+ $(MAKE) -C vendor/QR-Code-generator/c/ --no-print-directory clean
845854

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/python
2+
3+
import xml.etree.ElementTree as ET
4+
import sys
5+
6+
def main():
7+
# Relative paths from project root
8+
base_file = "../../ui/i18n/qml_base_en.ts"
9+
plural_file = "../../ui/i18n/qml_en.ts" # Assumed pluralTsFile
10+
output_file = "../../ui/i18n/qml_base_lokalise_en.ts"
11+
12+
# Parse the base TS file
13+
try:
14+
base_tree = ET.parse(base_file)
15+
base_root = base_tree.getroot()
16+
except ET.ParseError as e:
17+
print(f"Error parsing {base_file}: {e}", file=sys.stderr)
18+
sys.exit(1)
19+
20+
# Parse the plural TS file
21+
try:
22+
plural_tree = ET.parse(plural_file)
23+
plural_root = plural_tree.getroot()
24+
except ET.ParseError as e:
25+
print(f"Error parsing {plural_file}: {e}", file=sys.stderr)
26+
sys.exit(1)
27+
28+
# Create a dictionary for quick lookup of plural translations by source
29+
plural_lookup = {}
30+
for context in plural_root.findall('context'):
31+
for message in context.findall('message'):
32+
source = message.find('source')
33+
if source is not None and source.text:
34+
plural_lookup[source.text] = message.find('translation')
35+
36+
# Process each message in the base file
37+
for context in base_root.findall('context'):
38+
for message in context.findall('message'):
39+
numerus = message.get('numerus')
40+
source = message.find('source')
41+
translation = message.find('translation')
42+
43+
if numerus == 'yes' and source is not None and source.text in plural_lookup:
44+
# Copy translation from plural file
45+
plural_translation = plural_lookup[source.text]
46+
if plural_translation is not None:
47+
# Clear existing translation content
48+
translation.clear()
49+
# Copy attributes and subelements
50+
for attr, value in plural_translation.attrib.items():
51+
translation.set(attr, value)
52+
for child in plural_translation:
53+
translation.append(child)
54+
# Remove unfinished if present
55+
if 'type' in translation.attrib and translation.attrib['type'] == 'unfinished':
56+
del translation.attrib['type']
57+
else:
58+
# For non-numerus or unmatched, set translation to source
59+
if translation is not None and source is not None:
60+
translation.text = source.text
61+
# Remove unfinished
62+
if 'type' in translation.attrib and translation.attrib['type'] == 'unfinished':
63+
del translation.attrib['type']
64+
65+
# Write the modified XML to output file
66+
try:
67+
base_tree.write(output_file, encoding='utf-8', xml_declaration=True)
68+
print(f"Successfully transformed {base_file} to {output_file}")
69+
except Exception as e:
70+
print(f"Error writing to {output_file}: {e}", file=sys.stderr)
71+
sys.exit(1)
72+
73+
if __name__ == "__main__":
74+
main()

scripts/translationScripts/update-en-ts.py

Lines changed: 0 additions & 39 deletions
This file was deleted.

src/app/modules/main/profile_section/language/locale_table.nim

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ type
1414

1515
let localeDescriptionTable* = {
1616
"ar": Description(name: "Arabic", native: "العربية", flag: "", state: State.Alpha),
17-
"bn": Description(name: "Bengali", native: "বাংলা", flag: "X", state: State.Alpha),
17+
"bn": Description(name: "Bengali", native: "বাংলা", flag: "X", state: State.Alpha),
18+
"cs": Description(name: "Czech", native: "čeština", flag: "🇨🇿", state: State.Alpha),
1819
"de": Description(name: "German", native: "Deutsch", flag: "🇩🇪", state: State.Alpha),
1920
"el": Description(name: "Greek", native: "Ελληνικά", flag: "🇬🇷", state: State.Alpha),
20-
"en": Description(name: "English", native: "English", flag: "🏴󠁧󠁢󠁥󠁮󠁧󠁿", state: State.Stable),
21+
"en": Description(name: "English", native: "English", flag: "🇬🇧", state: State.Stable),
2122
"en_US": Description(name: "English (United States)", native: "English (United States)", flag: "🇺🇸", state: State.Alpha),
2223
"es": Description(name: "Spanish", native: "Español", flag: "🇪🇸", state: State.Alpha),
2324
"es_419": Description(name: "Spanish (Latin America)", native: "Español (Latinoamerica)", flag: "", state: State.Alpha),

ui/i18n/CMakeLists.txt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
cmake_minimum_required(VERSION 3.19)
2+
3+
project(status-app-i18n) # dummy project to silence warnings, TBD at the toplevel
4+
5+
find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core)
6+
find_package(Qt6 REQUIRED COMPONENTS LinguistTools)
7+
8+
#qt6_standard_project_setup(I18N_TRANSLATED_LANGUAGES cs)
9+
10+
set(QT_NO_MISSING_CATALOG_LANGUAGE_WARNING ON)
11+
12+
file(GLOB_RECURSE
13+
COLLECTED_SOURCE_FILES
14+
${CMAKE_SOURCE_DIR}/../*.qml
15+
)
16+
17+
qt6_add_lupdate(
18+
LUPDATE_TARGET update_application_translations # name of the cmake target
19+
OPTIONS -locations none -no-obsolete -source-language en # options passed to 'lupdate'
20+
TS_FILES
21+
${CMAKE_SOURCE_DIR}/qml_base_en.ts #empty base file, for manual translations
22+
${CMAKE_SOURCE_DIR}/qml_cs.ts
23+
PLURALS_TS_FILE
24+
${CMAKE_SOURCE_DIR}/qml_en.ts
25+
SOURCES ${COLLECTED_SOURCE_FILES}
26+
)
27+
28+
qt6_add_lrelease(
29+
LRELEASE_TARGET compile_application_translations # name of the cmake target
30+
OPTIONS -removeidentical -compress -nounfinished # options passed to 'lrelease'
31+
TS_FILES
32+
${CMAKE_SOURCE_DIR}/qml_en.ts
33+
${CMAKE_SOURCE_DIR}/qml_cs.ts
34+
QM_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/../../bin/i18n
35+
MERGE_QT_TRANSLATIONS
36+
QT_TRANSLATION_CATALOGS qtbase qtmultimedia qtwebengine
37+
)
38+
39+
# Ideally at the toplevel it could be done sth like this in one pass/target:
40+
#qt6_add_translations(
41+
# TS_FILE_BASE qml_
42+
# SOURCES ${COLLECTED_SOURCE_FILES}
43+
# LUPDATE_TARGET update_application_translations
44+
# LUPDATE_OPTIONS "-locations none -no-obsolete"
45+
# LRELEASE_TARGET compile_application_translations
46+
# LRELEASE_OPTIONS "-removeidentical -compress -nounfinished"
47+
# QM_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/../../bin/i18n
48+
# MERGE_QT_TRANSLATIONS
49+
#)

0 commit comments

Comments
 (0)