-
Notifications
You must be signed in to change notification settings - Fork 28
Complete language support to all GUI tabs #873
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
2180c36
aff35f2
b1c5733
bce5a70
cdf9504
d239658
7eb3da0
f03e2ee
4808ad1
59cad72
b2a2d08
7e3be47
518b74f
d74d92b
05a157e
8d3ebce
dce7d74
37c8d6b
95999ac
f498e3d
69ba3d8
4865c9e
0585d1f
3bce8c5
4c22eb1
31f9508
b70dc87
3e1c01c
d3b7090
f6642ba
5ac6599
ac13885
2578068
60af71b
eea0cab
9804a2f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| name: Translation Check | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ master, develop ] | ||
| pull_request: | ||
| branches: [ master, develop ] | ||
|
|
||
| jobs: | ||
| check: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Install Qt6 lupdate | ||
| run: | | ||
| sudo apt-get update -q | ||
| sudo apt-get install -y qt6-l10n-tools | ||
|
|
||
| - name: Run lupdate against all .ts files | ||
| run: | | ||
| # -locations none: suppress line-number comments so only genuine | ||
| # string additions/removals cause a git diff change. | ||
| lupdate6 src/ \ | ||
| -ts translations/OpenStudioApp_*.ts \ | ||
| -extensions cpp,hpp \ | ||
| -locations none \ | ||
| 2>&1 | tee lupdate_output.txt | ||
|
|
||
| - name: Detect vanished or new unfinished strings | ||
| run: | | ||
| # If lupdate changed any .ts file, strings were either added to source | ||
| # (new type="unfinished" stubs) or removed from source (type="obsolete"). | ||
| # Either way the commit that introduced the drift should not merge until | ||
| # the .ts files are updated and translations are provided. | ||
| python3 ci/check_translations.py | ||
|
|
||
| - name: Upload artifacts on failure | ||
| if: failure() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: translation-check-${{ github.sha }} | ||
| path: | | ||
| lupdate_output.txt | ||
| translation_check.patch |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| #!/usr/bin/env python3 | ||
| """ | ||
| Called by translation_check.yml after lupdate has run. | ||
|
|
||
| Checks whether lupdate changed any OpenStudioApp_*.ts file by running | ||
| `git diff translations/`. If there are changes it means: | ||
|
|
||
| - type="unfinished" stubs were ADDED → new tr() calls in source with no | ||
| translation yet. Fix: run translate_skeleton.py / translate_all_languages.py. | ||
|
|
||
| - type="obsolete" entries were ADDED → tr() calls removed from source but | ||
| still present as dead entries in the .ts files. Fix: run | ||
| `lupdate -no-obsolete` and commit the cleaned-up .ts files. | ||
|
|
||
| If the diff is empty, all .ts files are in sync with the C++ source. | ||
| Exits with code 1 if drift is detected so CI fails. | ||
| """ | ||
|
|
||
| import re | ||
| import subprocess | ||
| import sys | ||
|
|
||
|
|
||
| def run(cmd: list[str]) -> str: | ||
| return subprocess.check_output(cmd, text=True) | ||
|
|
||
|
|
||
| def main() -> int: | ||
| # Produce a diff of everything lupdate may have touched. | ||
| diff = run(["git", "diff", "translations/"]) | ||
|
|
||
| if not diff: | ||
| print("All .ts files are in sync with the C++ source. ✓") | ||
| return 0 | ||
|
|
||
| # Save patch as artifact for inspection. | ||
| with open("translation_check.patch", "w") as f: | ||
| f.write(diff) | ||
|
|
||
| # Classify what changed so the error message is actionable. | ||
| added_unfinished = len(re.findall(r'^\+.*type="unfinished"', diff, re.MULTILINE)) | ||
| added_obsolete = len(re.findall(r'^\+.*type="obsolete"', diff, re.MULTILINE)) | ||
|
|
||
| # Summarise changed files. | ||
| stat = run(["git", "diff", "--stat", "translations/"]) | ||
| print("lupdate changed the following .ts files:") | ||
| print(stat) | ||
|
|
||
| if added_unfinished: | ||
| print(f" {added_unfinished} new empty unfinished string(s) detected.") | ||
| print(" These are new tr() calls in C++ source that have no translation yet.") | ||
| print(" Fix: run translate_skeleton.py (Spanish) or translate_all_languages.py") | ||
| print(" to batch-translate the new strings, then commit the updated .ts files.") | ||
| print() | ||
|
|
||
| if added_obsolete: | ||
| print(f" {added_obsolete} new obsolete string(s) detected.") | ||
| print(" These are tr() calls that were removed from C++ source.") | ||
| print(" Fix: run `lupdate src/ -no-obsolete -ts translations/OpenStudioApp_*.ts`") | ||
| print(" then commit the cleaned-up .ts files.") | ||
| print() | ||
|
|
||
| if not added_unfinished and not added_obsolete: | ||
| # Location comments or other minor changes — still fail so the dev is aware. | ||
| print(" .ts files changed in an unexpected way (not unfinished/obsolete).") | ||
| print(" Review translation_check.patch for details.") | ||
|
|
||
| print("Translation check FAILED. Commit the updated .ts files to fix CI.") | ||
| return 1 | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| sys.exit(main()) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,8 @@ | |
| #include <QIntValidator> | ||
| #include <QLabel> | ||
| #include <QLineEdit> | ||
| #include <QCoreApplication> | ||
| #include <QLocale> | ||
| #include <QPainter> | ||
| #include <QPushButton> | ||
| #include <QRadioButton> | ||
|
|
@@ -53,6 +55,28 @@ | |
| #include <QVBoxLayout> | ||
|
|
||
| using namespace openstudio; | ||
|
|
||
| // Returns "Traducción (Field Name)" when the app locale is non-English and | ||
| // a translation exists in the "IDD" context of the loaded .qm file; | ||
| // otherwise returns the plain English field name. | ||
| // | ||
| // When translated, returns an HTML-formatted string with the translated name | ||
| // on the first line and the original English name in smaller gray italics on | ||
| // the second line — so a non-English speaker can cross-reference EnergyPlus | ||
| // documentation or .idf/.osm files without switching the application language. | ||
| // | ||
| // To add or refine translations: add entries to the IDD context in | ||
| // OpenStudioApp_<lang>.ts and recompile with lrelease — no C++ changes needed. | ||
| static QString iddFieldDisplayName(const std::string& englishName) { | ||
| const QString qname = QString::fromStdString(englishName); | ||
| if (QLocale().language() != QLocale::English) { | ||
| const QString translated = QCoreApplication::translate("IDD", englishName.c_str()); | ||
| if (translated != qname) { | ||
| return translated.toHtmlEscaped() + "<br><i style='color:gray'>" + qname.toHtmlEscaped() + "</i>"; | ||
| } | ||
| } | ||
| return qname; | ||
|
Comment on lines
+71
to
+78
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point — went with HTML formatting instead: the translated name on the first line, English original in small gray italics on the second line (31f9508). Tooltip was considered but rejected: a non-English speaker cross-referencing EnergyPlus documentation while looking at the inspector would find it frustrating to have the English name appear and vanish with cursor movement. The persistent second line keeps both names visible at all times. |
||
| } | ||
| using namespace openstudio::model; | ||
|
|
||
| const char* InspectorGadget::s_indexSlotName = "indexSlot"; | ||
|
|
@@ -507,7 +531,7 @@ void InspectorGadget::layoutText(QVBoxLayout* layout, QWidget* parent, openstudi | |
| auto* vbox = new QVBoxLayout(); | ||
| frame->setLayout(vbox); | ||
|
|
||
| auto* label = new QLabel(QString(name.c_str()), parent); | ||
| auto* label = new QLabel(iddFieldDisplayName(name), parent); | ||
| label->setWordWrap(true); | ||
| vbox->addWidget(label); | ||
|
|
||
|
|
@@ -751,7 +775,7 @@ void InspectorGadget::layoutComboBox(QVBoxLayout* layout, QWidget* parent, opens | |
| auto* frame = new QFrame(parent); | ||
| auto* vbox = new QVBoxLayout(); | ||
| frame->setLayout(vbox); | ||
| auto* label = new QLabel(QString(name.c_str()), parent); | ||
| auto* label = new QLabel(iddFieldDisplayName(name), parent); | ||
| label->setWordWrap(true); | ||
|
|
||
| QComboBox* combo = new IGComboBox(parent); | ||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.