Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Set up Qt Linguist workflow with .ts files, lupdate/lrelease integration, and translation management
.claude/skills/a5c-ai-qt-translation-workflow/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 72% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 76% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 10% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 49% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 18% | 0% |
Set up Qt Linguist translation workflow with .ts files and lrelease integration. This skill configures the complete internationalization pipeline for Qt applications.
json{ "type": "object", "properties": { "projectPath": { "type": "string", "description": "Path to the Qt project" }, "languages": { "type": "array", "items": { "type": "string" }, "description": "Target language codes (e.g., ['de', 'fr', 'ja'])" }, "sourceLanguage": { "type": "string", "default": "en", "description": "Source language code" }, "translationDir": { "type": "string", "default": "translations" }, "includeQml": { "type": "boolean", "default": true }, "pluralForms": { "type": "boolean", "default": true }, "generateCMake": { "type": "boolean", "default": true } }, "required": ["projectPath", "languages"] }
json{ "type": "object", "properties": { "success": { "type": "boolean" }, "files": { "type": "array", "items": { "type": "object", "properties": { "path": { "type": "string" }, "language": { "type": "string" }, "type": { "enum": ["ts", "qm", "cmake"] } } } }, "commands": { "type": "object", "properties": { "extract": { "type": "string" }, "compile": { "type": "string" } } } }, "required": ["success"] }
cmake# CMakeLists.txt find_package(Qt6 REQUIRED COMPONENTS LinguistTools) set(TS_FILES translations/myapp_de.ts translations/myapp_fr.ts translations/myapp_ja.ts ) # Create translation targets qt_add_translations(myapp TS_FILES ${TS_FILES} QM_FILES_OUTPUT_VARIABLE QM_FILES LUPDATE_OPTIONS -no-obsolete -locations relative LRELEASE_OPTIONS -compress ) # Add to resources qt_add_resources(myapp "translations" PREFIX "/translations" FILES ${QM_FILES} )
project/
├── translations/
│ ├── myapp_de.ts
│ ├── myapp_fr.ts
│ ├── myapp_ja.ts
│ └── myapp_en.ts # Reference
├── src/
│ ├── main.cpp
│ └── mainwindow.cpp
└── qml/
└── main.qmlcpp// mainwindow.cpp #include <QCoreApplication> MainWindow::MainWindow() { // Simple translation setWindowTitle(tr("My Application")); // With context label->setText(QCoreApplication::translate("MainWindow", "Welcome")); // Plural forms QString message = tr("%n file(s) selected", "", count); // With disambiguation QString open1 = tr("Open", "menu item"); QString open2 = tr("Open", "window title"); // Dynamic translation QString format = tr("Hello, %1!"); label->setText(format.arg(userName)); } // Enable retranslation void MainWindow::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { retranslateUi(); } QMainWindow::changeEvent(event); }
qml// main.qml import QtQuick 2.15 Window { title: qsTr("My Application") Text { // Simple translation text: qsTr("Welcome to the app") } Text { // Plural forms text: qsTr("%n item(s)", "", itemCount) } Text { // With context text: qsTranslate("SettingsPage", "Language") } }
cpp// main.cpp #include <QTranslator> #include <QLocale> int main(int argc, char *argv[]) { QApplication app(argc, argv); // Load system locale QTranslator translator; const QStringList uiLanguages = QLocale::system().uiLanguages(); for (const QString &locale : uiLanguages) { const QString baseName = "myapp_" + QLocale(locale).name(); if (translator.load(":/translations/" + baseName)) { app.installTranslator(&translator); break; } } // Or load specific language QTranslator germanTranslator; if (germanTranslator.load(":/translations/myapp_de")) { app.installTranslator(&germanTranslator); } return app.exec(); }
cppclass LanguageManager : public QObject { Q_OBJECT public: void setLanguage(const QString& languageCode) { // Remove old translator if (m_translator) { qApp->removeTranslator(m_translator); } // Load new translator m_translator = new QTranslator(this); QString path = QString(":/translations/myapp_%1").arg(languageCode); if (m_translator->load(path)) { qApp->installTranslator(m_translator); emit languageChanged(); } } signals: void languageChanged(); private: QTranslator* m_translator = nullptr; };
bash# Extract strings from source lupdate src/*.cpp qml/*.qml -ts translations/myapp_de.ts # Extract with options lupdate -recursive -locations relative -no-obsolete \ src/ qml/ -ts translations/*.ts # Compile translations lrelease translations/*.ts # Open in Qt Linguist linguist translations/myapp_de.ts
bash# Check translation completeness lconvert -if ts -i translations/myapp_de.ts -of csv -o status.csv # Custom script to report status for file in translations/*.ts; do total=$(grep -c '<source>' "$file") translated=$(grep -c 'type="finished"' "$file") echo "$file: $translated/$total translated" done
qt-cmake-project-generator - Project setupdesktop-i18n process - Full i18n workflowdocs-localization - Documentation localizationqt-cpp-specialist - Qt implementationlocalization-coordinator - Translation management| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 10,379 | 10,971 | +6% | 1 | 1 | 0% | 2,619 | 4,492 | +72% | 0 | 0 | — |
case-02 | fail→pass | 8,704 | 6,507 | -25% | 1 | 1 | 0% | 1,961 | 3,460 | +76% | 0 | 0 | — |
case-03 | fail→pass | 14,425 | 8,907 | -38% | 1 | 1 | 0% | 3,592 | 3,952 | +10% | 0 | 0 | — |
case-04 | pass→pass | 7,117 | 5,125 | -28% | 1 | 1 | 0% | 1,443 | 3,002 | +108% | 0 | 0 | — |
case-05 | fail→pass | 10,787 | 7,923 | -27% | 1 | 1 | 0% | 2,325 | 3,469 | +49% | 0 | 0 | — |
case-06 | pass→pass | 13,763 | 10,169 | -26% | 1 | 1 | 0% | 2,937 | 3,647 | +24% | 0 | 0 | — |
case-07 | pass→pass | 8,747 | 5,548 | -37% | 1 | 1 | 0% | 1,515 | 2,853 | +88% | 0 | 0 | — |
case-08 | pass→pass | 8,331 | 4,340 | -48% | 1 | 1 | 0% | 1,545 | 2,600 | +68% | 0 | 0 | — |
case-09 | pass→pass | 4,493 | 3,891 | -13% | 1 | 1 | 0% | 851 | 2,542 | +199% | 0 | 0 | — |
case-10 | pass→pass | 5,213 | 4,031 | -23% | 1 | 1 | 0% | 930 | 2,570 | +176% | 0 | 0 | — |
case-11 | pass→fail | 15,015 | 11,296 | -25% | 1 | 1 | 0% | 2,915 | 3,559 | +22% | 0 | 0 | — |
case-12 | pass→pass | 10,836 | 9,806 | -10% | 1 | 1 | 0% | 2,299 | 3,709 | +61% | 0 | 0 | — |
case-13 | pass→pass | 6,662 | 4,491 | -33% | 1 | 1 | 0% | 1,279 | 2,490 | +95% | 0 | 0 | — |
case-14 | pass→pass | 5,022 | 1,529 | -70% | 1 | 1 | 0% | 876 | 2,020 | +131% | 0 | 0 | — |
case-15 | fail→pass | 14,014 | 7,087 | -49% | 1 | 1 | 0% | 2,683 | 3,169 | +18% | 0 | 0 | — |
case-16 | pass→pass | 3,515 | 1,839 | -48% | 1 | 1 | 0% | 573 | 2,091 | +265% | 0 | 0 | — |
case-17 | pass→pass | 4,073 | 3,874 | -5% | 1 | 1 | 0% | 698 | 2,513 | +260% | 0 | 0 | — |
case-18 | pass→pass | 13,610 | 8,489 | -38% | 1 | 1 | 0% | 2,436 | 3,436 | +41% | 0 | 0 | — |
case-19 | pass→pass | 8,651 | 5,817 | -33% | 1 | 1 | 0% | 1,715 | 3,165 | +85% | 0 | 0 | — |
case-20 | pass→pass | 14,632 | 16,319 | +12% | 1 | 1 | 0% | 2,711 | 5,591 | +106% | 0 | 0 | — |
case-21 | pass→pass | 10,764 | 8,492 | -21% | 1 | 1 | 0% | 2,166 | 3,529 | +63% | 0 | 0 | — |
case-22 | pass→pass | 14,567 | 11,925 | -18% | 1 | 1 | 0% | 3,198 | 4,480 | +40% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +18 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.