From acd140e8d32de72d2715a490a84559edb46d52a2 Mon Sep 17 00:00:00 2001 From: Danfro Date: Thu, 23 Apr 2026 16:50:40 +0200 Subject: [PATCH 1/6] make app translatable and add German translation --- .gitignore | 1 - po/CMakeLists.txt | 34 +++++++ po/de.po | 182 +++++++++++++++++++++++++++++++++++++ po/ubcrypto.pot | 178 ++++++++++++++++++++++++++++++++++++ qml/AboutPage.qml | 10 +- qml/AddCoinDialog.qml | 6 +- qml/ChangeStats.qml | 8 +- qml/CoinCard.qml | 2 +- qml/CoinDetailPage.qml | 8 +- qml/DashboardPage.qml | 12 +-- qml/Main.qml | 8 +- qml/NewPortfolioDialog.qml | 6 +- qml/NewsPage.qml | 4 +- qml/PortfolioChart.qml | 6 +- qml/PortfolioItem.qml | 8 +- qml/PortfolioPage.qml | 8 +- qml/SplashScreen.qml | 4 +- 17 files changed, 439 insertions(+), 46 deletions(-) create mode 100644 po/CMakeLists.txt create mode 100644 po/de.po create mode 100644 po/ubcrypto.pot diff --git a/.gitignore b/.gitignore index 794f91e..41294cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ build -po *.user.* *.user __pycache__ diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt new file mode 100644 index 0000000..ac31544 --- /dev/null +++ b/po/CMakeLists.txt @@ -0,0 +1,34 @@ +include(FindGettext) +find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext) + +set(DOMAIN ${FULL_PROJECT_NAME}) +set(POT_FILE ${DOMAIN}.pot) +file(GLOB PO_FILES *.po) + +# Creates the .pot file containing the translations template +add_custom_target(${POT_FILE} ALL + COMMENT "Generating translation template" + COMMAND ${INTLTOOL_EXTRACT} --update --type=gettext/ini + --srcdir=${CMAKE_SOURCE_DIR} ${DESKTOP_FILE_NAME}.in + + COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} -o ${POT_FILE} + -D ${CMAKE_CURRENT_SOURCE_DIR} + -D ${CMAKE_CURRENT_BINARY_DIR} + --from-code=UTF-8 + --c++ --qt --language=javascript --add-comments=TRANSLATORS + --keyword=tr --keyword=tr:1,2 --keyword=N_ --keyword=_ + --package-name='${DOMAIN}' + --sort-by-file + ${I18N_SRC_FILES} + COMMAND ${CMAKE_COMMAND} -E copy ${POT_FILE} ${CMAKE_CURRENT_SOURCE_DIR}) + +# Builds the binary translations catalog for each language +# it finds source translations (*.po) for +foreach(PO_FILE ${PO_FILES}) + get_filename_component(LANG ${PO_FILE} NAME_WE) + gettext_process_po_files(${LANG} ALL PO_FILES ${PO_FILE}) + set(INSTALL_DIR ${CMAKE_INSTALL_LOCALEDIR}/share/locale/${LANG}/LC_MESSAGES) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LANG}.gmo + DESTINATION ${INSTALL_DIR} + RENAME ${DOMAIN}.mo) +endforeach(PO_FILE) diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..8ac4d1e --- /dev/null +++ b/po/de.po @@ -0,0 +1,182 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the ubcrypto package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: ubcrypto\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2026-04-22 22:01+0000\n" +"PO-Revision-Date: 2026-04-23 00:02+0200\n" +"Last-Translator: Daniel Frost \n" +"Language-Team: \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.4.2\n" + +#: ../qml/AboutPage.qml:29 ../qml/SplashScreen.qml:30 ubcrypto.desktop.in.h:1 +msgid "UBCrypto" +msgstr "UBCrypto" + +#: ../qml/AboutPage.qml:38 +msgid "" +"Your essential lightweight cryptocurrency tracking app for Ubuntu Touch. " +"Stay informed with live market data, manage your personal portfolio, and " +"enjoy a clean, intuitive user interface designed for mobile." +msgstr "" +"Deine essentielle leichtgewichtige Cryptowährungsverfolgungsapp für Ubuntu " +"Touch. Bleib informiert mit Echtzeit-Marktdaten, verwalte dein persönliches " +"Portfolio und genieße eine aufgeräumte, intuitive Benutzeroberfläche für " +"Mobilgeräte entwickelt." + +#: ../qml/AboutPage.qml:51 +msgid "Key Features" +msgstr "Hauptfunktionen" + +#: ../qml/AboutPage.qml:80 +msgid "Links" +msgstr "Links" + +#: ../qml/AboutPage.qml:89 +msgid "Source Code :" +msgstr "Quellcode:" + +#: ../qml/AddCoinDialog.qml:24 +msgid "Coin Symbol (e.g. BTC)" +msgstr "Coinkennzeichen (z.B. BTC)" + +#: ../qml/AddCoinDialog.qml:30 +msgid "Amount (e.g. 2.5)" +msgstr "Menge (z.B. 2,5)" + +#: ../qml/AddCoinDialog.qml:59 ../qml/NewPortfolioDialog.qml:38 +msgid "Cancel" +msgstr "Abbrechen" + +#: ../qml/ChangeStats.qml:31 +msgid "1h:" +msgstr "1 h:" + +#: ../qml/ChangeStats.qml:64 +msgid "24h:" +msgstr "24 h:" + +#: ../qml/CoinCard.qml:93 +msgid "Volume: " +msgstr "Volumen: " + +#: ../qml/CoinDetailPage.qml:20 +msgid "Current Price: " +msgstr "Aktueller Preis: " + +#: ../qml/CoinDetailPage.qml:33 +msgid "Chart Placeholder" +msgstr "Diagramm Platzhalter" + +#: ../qml/CoinDetailPage.qml:42 +msgid "Add to Watchlist" +msgstr "Zur Watchlist hinzufügen" + +#: ../qml/CoinDetailPage.qml:50 +msgid "Add to Portfolio" +msgstr "Zum Portfolio hinzufügen" + +#: ../qml/DashboardPage.qml:128 +msgid "All" +msgstr "Alle" + +#: ../qml/DashboardPage.qml:129 +msgid "Top Gainers" +msgstr "Top Gewinner" + +#: ../qml/DashboardPage.qml:130 +msgid "Top Losers" +msgstr "Top Verlierer" + +#: ../qml/DashboardPage.qml:166 +msgid "Search coins..." +msgstr "Coins suchen..." + +#: ../qml/DashboardPage.qml:240 +msgid "No data available." +msgstr "Keine Daten verfügbar." + +#: ../qml/DashboardPage.qml:247 ../qml/NewsPage.qml:21 +msgid "Refresh" +msgstr "Aktualisieren" + +#: ../qml/Main.qml:60 +msgid "HOME" +msgstr "START" + +#: ../qml/Main.qml:63 +msgid "PORTFOLIO" +msgstr "PORTFOLIO" + +#: ../qml/Main.qml:66 +msgid "NEWS" +msgstr "MELDUNGEN" + +#: ../qml/Main.qml:69 +msgid "ABOUT" +msgstr "ÜBER" + +#: ../qml/NewPortfolioDialog.qml:22 +msgid "Enter portfolio name" +msgstr "Portfolioname" + +#: ../qml/NewPortfolioDialog.qml:28 +msgid "Create" +msgstr "Erstellen" + +#: ../qml/NewsPage.qml:218 +msgid "Read More" +msgstr "Weiterlesen" + +#: ../qml/PortfolioChart.qml:16 +msgid "Portfolio Value Over Time" +msgstr "Portfoliowert über die Zeit" + +#: ../qml/PortfolioChart.qml:33 +msgid "Value (€)" +msgstr "Wert (€)" + +#: ../qml/PortfolioChart.qml:50 +msgid "Date" +msgstr "Datum" + +#: ../qml/PortfolioItem.qml:95 +msgid "Qty: " +msgstr "Menge: " + +#: ../qml/PortfolioItem.qml:102 +msgid "Profit/Loss: " +msgstr "Gewinn/Verlust: " + +#: ../qml/PortfolioItem.qml:111 +msgid "Unit: €" +msgstr "Einheit: €" + +#: ../qml/PortfolioItem.qml:119 +msgid "Current Value : €" +msgstr "Aktueller Wert: €" + +#: ../qml/PortfolioPage.qml:19 ../qml/PortfolioPage.qml:24 +msgid "Portfolio" +msgstr "Portfolio" + +#: ../qml/PortfolioPage.qml:71 +msgid "Add Coin" +msgstr "Coin hinzufügen" + +#: ../qml/PortfolioPage.qml:81 +msgid "Your Holdings Worth" +msgstr "Portfolio Gesamtwert" + +#: ../qml/SplashScreen.qml:41 +msgid "Your Market Insights, Instantly." +msgstr "Deine Marktinformationen, in Echtzeit." diff --git a/po/ubcrypto.pot b/po/ubcrypto.pot new file mode 100644 index 0000000..fc25087 --- /dev/null +++ b/po/ubcrypto.pot @@ -0,0 +1,178 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the ubcrypto package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: ubcrypto\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2026-04-23 14:45+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../qml/AboutPage.qml:29 ../qml/SplashScreen.qml:30 ubcrypto.desktop.in.h:1 +msgid "UBCrypto" +msgstr "" + +#: ../qml/AboutPage.qml:38 +msgid "" +"Your essential lightweight cryptocurrency tracking app for Ubuntu Touch. " +"Stay informed with live market data, manage your personal portfolio, and " +"enjoy a clean, intuitive user interface designed for mobile." +msgstr "" + +#: ../qml/AboutPage.qml:51 +msgid "Key Features" +msgstr "" + +#: ../qml/AboutPage.qml:80 +msgid "Links" +msgstr "" + +#: ../qml/AboutPage.qml:89 +msgid "Source Code :" +msgstr "" + +#: ../qml/AddCoinDialog.qml:24 +msgid "Coin Symbol (e.g. BTC)" +msgstr "" + +#: ../qml/AddCoinDialog.qml:30 +msgid "Amount (e.g. 2.5)" +msgstr "" + +#: ../qml/AddCoinDialog.qml:59 ../qml/NewPortfolioDialog.qml:38 +msgid "Cancel" +msgstr "" + +#: ../qml/ChangeStats.qml:31 +msgid "1h:" +msgstr "" + +#: ../qml/ChangeStats.qml:64 +msgid "24h:" +msgstr "" + +#: ../qml/CoinCard.qml:93 +msgid "Volume: " +msgstr "" + +#: ../qml/CoinDetailPage.qml:20 +msgid "Current Price: " +msgstr "" + +#: ../qml/CoinDetailPage.qml:33 +msgid "Chart Placeholder" +msgstr "" + +#: ../qml/CoinDetailPage.qml:42 +msgid "Add to Watchlist" +msgstr "" + +#: ../qml/CoinDetailPage.qml:50 +msgid "Add to Portfolio" +msgstr "" + +#: ../qml/DashboardPage.qml:128 +msgid "All" +msgstr "" + +#: ../qml/DashboardPage.qml:129 +msgid "Top Gainers" +msgstr "" + +#: ../qml/DashboardPage.qml:130 +msgid "Top Losers" +msgstr "" + +#: ../qml/DashboardPage.qml:166 +msgid "Search coins..." +msgstr "" + +#: ../qml/DashboardPage.qml:240 +msgid "No data available." +msgstr "" + +#: ../qml/DashboardPage.qml:247 ../qml/NewsPage.qml:21 +#: ../qml/PortfolioPage.qml:35 +msgid "Refresh" +msgstr "" + +#: ../qml/Main.qml:60 +msgid "HOME" +msgstr "" + +#: ../qml/Main.qml:63 +msgid "PORTFOLIO" +msgstr "" + +#: ../qml/Main.qml:66 +msgid "NEWS" +msgstr "" + +#: ../qml/Main.qml:69 +msgid "ABOUT" +msgstr "" + +#: ../qml/NewPortfolioDialog.qml:22 +msgid "Enter portfolio name" +msgstr "" + +#: ../qml/NewPortfolioDialog.qml:28 +msgid "Create" +msgstr "" + +#: ../qml/NewsPage.qml:218 +msgid "Read More" +msgstr "" + +#: ../qml/PortfolioChart.qml:16 +msgid "Portfolio Value Over Time" +msgstr "" + +#: ../qml/PortfolioChart.qml:33 +msgid "Value (€)" +msgstr "" + +#: ../qml/PortfolioChart.qml:50 +msgid "Date" +msgstr "" + +#: ../qml/PortfolioItem.qml:95 +msgid "Qty: " +msgstr "" + +#: ../qml/PortfolioItem.qml:102 +msgid "Profit/Loss: " +msgstr "" + +#: ../qml/PortfolioItem.qml:111 +msgid "Unit: €" +msgstr "" + +#: ../qml/PortfolioItem.qml:119 +msgid "Current Value : €" +msgstr "" + +#: ../qml/PortfolioPage.qml:20 ../qml/PortfolioPage.qml:25 +msgid "Portfolio" +msgstr "" + +#: ../qml/PortfolioPage.qml:98 +msgid "Add Coin" +msgstr "" + +#: ../qml/PortfolioPage.qml:108 +msgid "Your Holdings Worth" +msgstr "" + +#: ../qml/SplashScreen.qml:41 +msgid "Your Market Insights, Instantly." +msgstr "" diff --git a/qml/AboutPage.qml b/qml/AboutPage.qml index dfe4f93..1896e27 100644 --- a/qml/AboutPage.qml +++ b/qml/AboutPage.qml @@ -26,7 +26,7 @@ Page { // --- Section: About UBCrypto --- Text { - text: "UBCrypto" + text: i18n.tr("UBCrypto") color:AppTheme.getThemeColors(theme.name).textColorPrimary font.pixelSize: units.gu(3) // Larger font for app name font.bold: true @@ -35,7 +35,7 @@ Page { } Text { - text: "Your essential lightweight cryptocurrency tracking app for Ubuntu Touch. Stay informed with live market data, manage your personal portfolio, and enjoy a clean, intuitive user interface designed for mobile." + text: i18n.tr("Your essential lightweight cryptocurrency tracking app for Ubuntu Touch. Stay informed with live market data, manage your personal portfolio, and enjoy a clean, intuitive user interface designed for mobile.") font.pixelSize: units.gu(1.8) color:AppTheme.getThemeColors(theme.name).textColorPrimary width: parent.width @@ -48,7 +48,7 @@ Page { // --- Section: Key Features --- Text { - text: "Key Features" + text: i18n.tr("Key Features") font.pixelSize: units.gu(2.2) // Heading size font.bold: true color:AppTheme.getThemeColors(theme.name).textColorPrimary @@ -77,7 +77,7 @@ Page { // --- Section: Links --- Text { - text: "Links" + text: i18n.tr("Links") font.pixelSize: units.gu(2) font.bold: true color:AppTheme.getThemeColors(theme.name).textColorPrimary @@ -86,7 +86,7 @@ Page { } Text { - text: "Source Code : https://github.com/karthagokul/ubcrypto" + text: i18n.tr("Source Code :") + "https://github.com/karthagokul/ubcrypto" font.pixelSize: units.gu(1.6) color:AppTheme.getThemeColors(theme.name).textColorPrimary textFormat: Text.RichText diff --git a/qml/AddCoinDialog.qml b/qml/AddCoinDialog.qml index 39ca611..d276ea4 100644 --- a/qml/AddCoinDialog.qml +++ b/qml/AddCoinDialog.qml @@ -21,13 +21,13 @@ Dialog { TextField { id: coinSymbolField - placeholderText: "Coin Symbol (e.g. BTC)" + placeholderText: i18n.tr("Coin Symbol (e.g. BTC)") readOnly: editMode // make symbol non-editable in edit mode } TextField { id: coinAmountField - placeholderText: "Amount (e.g. 2.5)" + placeholderText: i18n.tr("Amount (e.g. 2.5)") inputMethodHints: Qt.ImhFormattedNumbersOnly } @@ -56,7 +56,7 @@ Dialog { } Button { - text: "Cancel" + text: i18n.tr("Cancel") onClicked: { coinSymbolField.text = ""; coinAmountField.text = ""; diff --git a/qml/ChangeStats.qml b/qml/ChangeStats.qml index 36029a7..be0fb57 100644 --- a/qml/ChangeStats.qml +++ b/qml/ChangeStats.qml @@ -28,7 +28,7 @@ Item { Layout.fillWidth: true Text { - text: "1h:" + text: i18n.tr("1h:") color: AppTheme.getThemeColors(theme.name).textColorPrimary font.pixelSize: units.gu(1.8) } @@ -61,7 +61,7 @@ Item { Layout.fillWidth: true Text { - text: "24h:" + text: i18n.tr("24h:") color: AppTheme.getThemeColors(theme.name).textColorPrimary font.pixelSize: units.gu(1.8) } @@ -91,7 +91,7 @@ Item { RowLayout { Layout.fillWidth: true Text { - text: "7d:" + text: i18n.tr("7d:") color: "#AAA" font.pixelSize: units.gu(1.5) } @@ -109,7 +109,7 @@ Item { RowLayout { Layout.fillWidth: true Text { - text: "30d:" + text: i18n.tr("30d:") color: "#AAA" font.pixelSize: units.gu(1.5) } diff --git a/qml/CoinCard.qml b/qml/CoinCard.qml index 4553038..78e7558 100644 --- a/qml/CoinCard.qml +++ b/qml/CoinCard.qml @@ -90,7 +90,7 @@ ListItem { } Text { - text: "Volume: " + formattedTotalVolume + text: i18n.tr("Volume: ") + formattedTotalVolume font.pixelSize: units.gu(1.6) color: AppTheme.getThemeColors(theme.name).textColorPrimary } diff --git a/qml/CoinDetailPage.qml b/qml/CoinDetailPage.qml index 505cd1e..2ce206c 100644 --- a/qml/CoinDetailPage.qml +++ b/qml/CoinDetailPage.qml @@ -17,7 +17,7 @@ Page { spacing: units.gu(2) Text { - text: "Current Price: " + price + text: i18n.tr("Current Price: ") + price font.pixelSize: units.gu(3) } @@ -30,7 +30,7 @@ Page { Text { anchors.centerIn: parent - text: "Chart Placeholder" + text: i18n.tr("Chart Placeholder") color: "#666" } } @@ -39,7 +39,7 @@ Page { spacing: units.gu(2) Button { - text: "Add to Watchlist" + text: i18n.tr("Add to Watchlist") onClicked: { console.log("Added to Watchlist"); // Save to local DB later @@ -47,7 +47,7 @@ Page { } Button { - text: "Add to Portfolio" + text: i18n.tr("Add to Portfolio") onClicked: { console.log("Added to Portfolio"); // Save to local DB later diff --git a/qml/DashboardPage.qml b/qml/DashboardPage.qml index 5a00018..1cb84fc 100644 --- a/qml/DashboardPage.qml +++ b/qml/DashboardPage.qml @@ -125,9 +125,9 @@ Page { Repeater { model: [ - { name: " All " }, - { name: " Top Gainers " }, - { name: " Top Losers " } + { name: i18n.tr("All") }, + { name: i18n.tr("Top Gainers") }, + { name: i18n.tr("Top Losers") } ] delegate: MouseArea { width: units.gu(12) @@ -163,7 +163,7 @@ Page { TextField { id: searchBox - placeholderText: "Search coins..." + placeholderText: i18n.tr("Search coins...") anchors.fill: parent font.pixelSize: units.gu(2) onTextChanged: { @@ -237,14 +237,14 @@ Page { width: parent.width // Make Column take full width of emptyState Label { - text: "No data available." + text: i18n.tr("No data available.") font.pixelSize: units.gu(2.2) horizontalAlignment: Text.AlignHCenter width: parent.width // Make Label fill its parent Column horizontally } Button { - text: "Refresh" + text: i18n.tr("Refresh") anchors.horizontalCenter: parent.horizontalCenter // Keep centering for the Button onClicked: { var coins = DB.getAllCoins(); diff --git a/qml/Main.qml b/qml/Main.qml index 0acb82a..d8228cc 100644 --- a/qml/Main.qml +++ b/qml/Main.qml @@ -57,16 +57,16 @@ MainView { Repeater { model: [ { - name: "HOME" + name: i18n.tr("HOME") }, { - name: "PORTFOLIO" + name: i18n.tr("PORTFOLIO") }, { - name: "NEWS" + name: i18n.tr("NEWS") }, { - name: "ABOUT" + name: i18n.tr("ABOUT") } ] diff --git a/qml/NewPortfolioDialog.qml b/qml/NewPortfolioDialog.qml index 27c643c..54dc8c4 100644 --- a/qml/NewPortfolioDialog.qml +++ b/qml/NewPortfolioDialog.qml @@ -19,13 +19,13 @@ Dialog { TextField { id: newPortfolioName - placeholderText: "Enter portfolio name" + text: i18n.tr("Enter portfolio name") } Row { spacing: units.gu(2) Button { - text: "Create" + text: i18n.tr("Create") onClicked: { if (newPortfolioName.text.length > 0) { portfolioCreated(newPortfolioName.text); @@ -35,7 +35,7 @@ Dialog { } } Button { - text: "Cancel" + text: i18n.tr("Cancel") onClicked: newPortfolioDialog.close() } } diff --git a/qml/NewsPage.qml b/qml/NewsPage.qml index 9f5668c..7fd2209 100644 --- a/qml/NewsPage.qml +++ b/qml/NewsPage.qml @@ -18,7 +18,7 @@ Page { actions: [ Action { iconName: "view-refresh" - text: "Refresh" + text: i18n.tr("Refresh") onTriggered: loadAllFeeds() } ] @@ -215,7 +215,7 @@ Page { } Text { - text: "Read More" + text: i18n.tr("Read More") Layout.fillWidth: true font.pixelSize: units.gu(1.5) color: linkColor diff --git a/qml/PortfolioChart.qml b/qml/PortfolioChart.qml index 290df80..bba2e24 100644 --- a/qml/PortfolioChart.qml +++ b/qml/PortfolioChart.qml @@ -13,7 +13,7 @@ Item { // Title Text { id: chartTitle - text: "Portfolio Value Over Time" + text: i18n.tr("Portfolio Value Over Time") anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter font.pixelSize: units.gu(2) // Assuming units is defined elsewhere, or use a fixed pixel size like 20 @@ -30,7 +30,7 @@ Item { ValueAxis { id: yAxis min: 0 - titleText: "Value (€)" + titletext: i18n.tr("Value ($)") } // ***** CHANGE THIS LINE ***** @@ -47,7 +47,7 @@ Item { DateTimeAxis { id: xAxis - titleText: "Date" + titletext: i18n.tr("Date") format: "MM-dd" // Or "yyyy-MM-dd", adjust as per clutter tips tickCount: 5 labelsAngle: -45 // Keeps labels from overlapping diff --git a/qml/PortfolioItem.qml b/qml/PortfolioItem.qml index 3930721..93ea97b 100644 --- a/qml/PortfolioItem.qml +++ b/qml/PortfolioItem.qml @@ -92,14 +92,14 @@ ListItem { spacing: units.gu(0.3) Text { - text: "Qty: " + quantity + text: i18n.tr("Qty: ") + quantity font.pixelSize: units.gu(1.5) color: AppTheme.getThemeColors(theme.name).textColorPrimary horizontalAlignment: Text.AlignRight } PriceWidget { - text: "Profit/Loss: " + Number(delta).toFixed(2) + "$" + text: i18n.tr("Profit/Loss: ") + Number(delta).toFixed(2) + "€" value:Number(delta).toFixed(2) font.bold: false font.pixelSize: units.gu(1.5) @@ -108,7 +108,7 @@ ListItem { } PriceWidget { - text: "Unit: $" + Number(price).toFixed(2) + text: i18n.tr("Unit: €") + Number(price).toFixed(2) font.bold:false font.pixelSize: units.gu(2) color: AppTheme.getThemeColors(theme.name).textColorPrimary @@ -116,7 +116,7 @@ ListItem { } PriceWidget { - text: "Current Value : $" + Number(total_value).toFixed(2) + text: i18n.tr("Current Value : €") + Number(total_value).toFixed(2) font.bold:false font.pixelSize: units.gu(2) color: AppTheme.getThemeColors(theme.name).textColorPrimary diff --git a/qml/PortfolioPage.qml b/qml/PortfolioPage.qml index a233b7b..deb50da 100644 --- a/qml/PortfolioPage.qml +++ b/qml/PortfolioPage.qml @@ -16,12 +16,12 @@ Page { actions: [ Action { iconName: "add" - text: "Portfolio" + text: i18n.tr("Portfolio") onTriggered: newPortfolioDialog.open() }, Action { iconName: "delete" - text: "Portfolio" + text: i18n.tr("Portfolio") onTriggered: { if (selectedPortfolio !== -1) { DB.deletePortfolio(selectedPortfolio) @@ -68,7 +68,7 @@ Page { } } Button { - text: "Add Coin" + text: i18n.tr("Add Coin") enabled: (selectedPortfolio !== -1) onClicked: { addCoinDialog.open() @@ -78,7 +78,7 @@ Page { // === Holdings Header === Text { - text: "Your Holdings" + " Worth ($" + totalValue.toFixed(2)+")" + text: i18n.tr("Your Holdings Worth") + " (€" + totalValue.toFixed(2) + ")" font.bold: true font.pixelSize: units.gu(2.2) } diff --git a/qml/SplashScreen.qml b/qml/SplashScreen.qml index b68dea2..99f3d52 100644 --- a/qml/SplashScreen.qml +++ b/qml/SplashScreen.qml @@ -27,7 +27,7 @@ Rectangle { } Text { - text: "UBCrypto" + text: i18n.tr("UBCrypto") font.pixelSize: units.gu(4) font.bold: true color: "#333" @@ -38,7 +38,7 @@ Rectangle { // --- Your Catchy Tagline with a simple Fade-In Animation --- Text { id: taglineText // Added an ID for clarity - text: "Your Market Insights, Instantly." + text: i18n.tr("Your Market Insights, Instantly.") font.pixelSize: units.gu(2.2) color: "#666" horizontalAlignment: Text.AlignHCenter From 988fffdae97b0ace0ff0ccba76db648b95688ef1 Mon Sep 17 00:00:00 2001 From: Danfro Date: Thu, 23 Apr 2026 16:53:13 +0200 Subject: [PATCH 2/6] increase the margin to allow longer translations --- qml/DashboardPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qml/DashboardPage.qml b/qml/DashboardPage.qml index 1cb84fc..379833a 100644 --- a/qml/DashboardPage.qml +++ b/qml/DashboardPage.qml @@ -121,7 +121,7 @@ Page { Row { // This Row lays out filter buttons horizontally anchors.centerIn: parent - spacing: units.gu(1) + spacing: units.gu(3) Repeater { model: [ From 3a05f6430edb00077b162a906bb47ed764762bc2 Mon Sep 17 00:00:00 2001 From: Danfro Date: Fri, 24 Apr 2026 20:19:13 +0200 Subject: [PATCH 3/6] use locale decimal separator and reformat strings to use .arg --- po/de.po | 39 ++++++++++++++++++++++++--------------- po/ubcrypto.pot | 22 +++++++++++++++------- qml/ChangeStats.qml | 8 ++++---- qml/CoinCard.qml | 2 +- qml/PortfolioItem.qml | 8 ++++---- qml/PortfolioPage.qml | 3 ++- 6 files changed, 50 insertions(+), 32 deletions(-) diff --git a/po/de.po b/po/de.po index 8ac4d1e..39b4e60 100644 --- a/po/de.po +++ b/po/de.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ubcrypto\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-22 22:01+0000\n" -"PO-Revision-Date: 2026-04-23 00:02+0200\n" +"POT-Creation-Date: 2026-04-24 18:15+0000\n" +"PO-Revision-Date: 2026-04-24 20:18+0200\n" "Last-Translator: Daniel Frost \n" "Language-Team: \n" "Language: de\n" @@ -65,6 +65,14 @@ msgstr "1 h:" msgid "24h:" msgstr "24 h:" +#: ../qml/ChangeStats.qml:94 +msgid "7d:" +msgstr "7d:" + +#: ../qml/ChangeStats.qml:112 +msgid "30d:" +msgstr "30d:" + #: ../qml/CoinCard.qml:93 msgid "Volume: " msgstr "Volumen: " @@ -106,6 +114,7 @@ msgid "No data available." msgstr "Keine Daten verfügbar." #: ../qml/DashboardPage.qml:247 ../qml/NewsPage.qml:21 +#: ../qml/PortfolioPage.qml:35 msgid "Refresh" msgstr "Aktualisieren" @@ -142,38 +151,38 @@ msgid "Portfolio Value Over Time" msgstr "Portfoliowert über die Zeit" #: ../qml/PortfolioChart.qml:33 -msgid "Value (€)" -msgstr "Wert (€)" +msgid "Value ($)" +msgstr "Wert ($)" #: ../qml/PortfolioChart.qml:50 msgid "Date" msgstr "Datum" #: ../qml/PortfolioItem.qml:95 -msgid "Qty: " -msgstr "Menge: " +msgid "Qty: %1" +msgstr "Menge: %1" #: ../qml/PortfolioItem.qml:102 -msgid "Profit/Loss: " -msgstr "Gewinn/Verlust: " +msgid "Profit/Loss: %1$" +msgstr "Gewinn/Verlust: %1 $" #: ../qml/PortfolioItem.qml:111 -msgid "Unit: €" -msgstr "Einheit: €" +msgid "Unit: $%1" +msgstr "Einheit: $%1" #: ../qml/PortfolioItem.qml:119 -msgid "Current Value : €" -msgstr "Aktueller Wert: €" +msgid "Current Value: $%1" +msgstr "Aktueller Wert: $ %1" -#: ../qml/PortfolioPage.qml:19 ../qml/PortfolioPage.qml:24 +#: ../qml/PortfolioPage.qml:20 ../qml/PortfolioPage.qml:25 msgid "Portfolio" msgstr "Portfolio" -#: ../qml/PortfolioPage.qml:71 +#: ../qml/PortfolioPage.qml:98 msgid "Add Coin" msgstr "Coin hinzufügen" -#: ../qml/PortfolioPage.qml:81 +#: ../qml/PortfolioPage.qml:108 msgid "Your Holdings Worth" msgstr "Portfolio Gesamtwert" diff --git a/po/ubcrypto.pot b/po/ubcrypto.pot index fc25087..7d972f0 100644 --- a/po/ubcrypto.pot +++ b/po/ubcrypto.pot @@ -8,13 +8,13 @@ msgid "" msgstr "" "Project-Id-Version: ubcrypto\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-23 14:45+0000\n" +"POT-Creation-Date: 2026-04-24 18:15+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../qml/AboutPage.qml:29 ../qml/SplashScreen.qml:30 ubcrypto.desktop.in.h:1 @@ -60,6 +60,14 @@ msgstr "" msgid "24h:" msgstr "" +#: ../qml/ChangeStats.qml:94 +msgid "7d:" +msgstr "" + +#: ../qml/ChangeStats.qml:112 +msgid "30d:" +msgstr "" + #: ../qml/CoinCard.qml:93 msgid "Volume: " msgstr "" @@ -138,7 +146,7 @@ msgid "Portfolio Value Over Time" msgstr "" #: ../qml/PortfolioChart.qml:33 -msgid "Value (€)" +msgid "Value ($)" msgstr "" #: ../qml/PortfolioChart.qml:50 @@ -146,19 +154,19 @@ msgid "Date" msgstr "" #: ../qml/PortfolioItem.qml:95 -msgid "Qty: " +msgid "Qty: %1" msgstr "" #: ../qml/PortfolioItem.qml:102 -msgid "Profit/Loss: " +msgid "Profit/Loss: %1$" msgstr "" #: ../qml/PortfolioItem.qml:111 -msgid "Unit: €" +msgid "Unit: $%1" msgstr "" #: ../qml/PortfolioItem.qml:119 -msgid "Current Value : €" +msgid "Current Value: $%1" msgstr "" #: ../qml/PortfolioPage.qml:20 ../qml/PortfolioPage.qml:25 diff --git a/qml/ChangeStats.qml b/qml/ChangeStats.qml index be0fb57..863df47 100644 --- a/qml/ChangeStats.qml +++ b/qml/ChangeStats.qml @@ -46,7 +46,7 @@ Item { Text { id: labelText - text: (change1h >= 0 ? "+" : "") + change1h.toFixed(1) + "%" + text: (change1h >= 0 ? "+" : "") + change1h.toFixed(1).toString().replace(".",Qt.locale().decimalPoint) + "%" color: "white" font.bold: true font.pixelSize: units.gu(1.6) @@ -75,7 +75,7 @@ Item { Text { id: labelText24 - text: (change24h >= 0 ? "+" : "") + change24h.toFixed(1) + "%" + text: (change24h >= 0 ? "+" : "") + change24h.toFixed(1).toString().replace(".",Qt.locale().decimalPoint) + "%" color: "white" font.bold: true font.pixelSize: units.gu(1.6) @@ -96,7 +96,7 @@ Item { font.pixelSize: units.gu(1.5) } Text { - text: (change7d >= 0 ? "+" : "") + change7d.toFixed(2) + "%" + text: (change7d >= 0 ? "+" : "") + change7d.toFixed(2).toString().replace(".",Qt.locale().decimalPoint) + "%" color: change7d >= 0 ? "green" : "red" font.pixelSize: units.gu(1.5) // font.bold: true @@ -114,7 +114,7 @@ Item { font.pixelSize: units.gu(1.5) } Text { - text: (change30d >= 0 ? "+" : "") + change30d.toFixed(2) + "%" + text: (change30d >= 0 ? "+" : "") + change30d.toFixed(2).toString().replace(".",Qt.locale().decimalPoint) + "%" color: change30d >= 0 ? "green" : "red" font.pixelSize: units.gu(1.5) // font.bold: true diff --git a/qml/CoinCard.qml b/qml/CoinCard.qml index 78e7558..f7662d7 100644 --- a/qml/CoinCard.qml +++ b/qml/CoinCard.qml @@ -23,7 +23,7 @@ ListItem { property real price_change_percentage_7d: 0 property real price_change_percentage_30d: 0 - property string formattedTotalVolume: coinCard.formatLargeNumber(totalVolume) // New property + property string formattedTotalVolume: coinCard.formatLargeNumber(totalVolume).toString().replace(".",Qt.locale().decimalPoint) // New property // Use Layout.implicitHeight for contentRow wrapped by RowLayout implicitHeight: contentLayout.implicitHeight + units.gu(2) // Adding padding for top/bottom diff --git a/qml/PortfolioItem.qml b/qml/PortfolioItem.qml index 93ea97b..d8359df 100644 --- a/qml/PortfolioItem.qml +++ b/qml/PortfolioItem.qml @@ -92,14 +92,14 @@ ListItem { spacing: units.gu(0.3) Text { - text: i18n.tr("Qty: ") + quantity + text: i18n.tr("Qty: %1").arg(quantity.toString().replace(".",Qt.locale().decimalPoint)) font.pixelSize: units.gu(1.5) color: AppTheme.getThemeColors(theme.name).textColorPrimary horizontalAlignment: Text.AlignRight } PriceWidget { - text: i18n.tr("Profit/Loss: ") + Number(delta).toFixed(2) + "€" + text: i18n.tr("Profit/Loss: %1$").arg(Number(delta).toFixed(2).toString().replace(".",Qt.locale().decimalPoint)) value:Number(delta).toFixed(2) font.bold: false font.pixelSize: units.gu(1.5) @@ -108,7 +108,7 @@ ListItem { } PriceWidget { - text: i18n.tr("Unit: €") + Number(price).toFixed(2) + text: i18n.tr("Unit: $%1").arg(Number(price).toFixed(2).toString().replace(".",Qt.locale().decimalPoint)) font.bold:false font.pixelSize: units.gu(2) color: AppTheme.getThemeColors(theme.name).textColorPrimary @@ -116,7 +116,7 @@ ListItem { } PriceWidget { - text: i18n.tr("Current Value : €") + Number(total_value).toFixed(2) + text: i18n.tr("Current Value: $%1").arg(Number(total_value).toFixed(2).toString().replace(".",Qt.locale().decimalPoint)) font.bold:false font.pixelSize: units.gu(2) color: AppTheme.getThemeColors(theme.name).textColorPrimary diff --git a/qml/PortfolioPage.qml b/qml/PortfolioPage.qml index deb50da..cbf6f70 100644 --- a/qml/PortfolioPage.qml +++ b/qml/PortfolioPage.qml @@ -78,7 +78,8 @@ Page { // === Holdings Header === Text { - text: i18n.tr("Your Holdings Worth") + " (€" + totalValue.toFixed(2) + ")" + text: i18n.tr("Your Holdings Worth") + ": $ " + totalValue.toFixed(2).toString().replace(".",Qt.locale().decimalPoint)) + color:AppTheme.getThemeColors(theme.name).textColorPrimary font.bold: true font.pixelSize: units.gu(2.2) } From a3538b67bc07b2712518e58a2b4202357586079d Mon Sep 17 00:00:00 2001 From: Danfro Date: Sat, 25 Apr 2026 08:37:26 +0200 Subject: [PATCH 4/6] drop leftover bracket --- qml/PortfolioPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qml/PortfolioPage.qml b/qml/PortfolioPage.qml index cbf6f70..ffd0bf5 100644 --- a/qml/PortfolioPage.qml +++ b/qml/PortfolioPage.qml @@ -78,7 +78,7 @@ Page { // === Holdings Header === Text { - text: i18n.tr("Your Holdings Worth") + ": $ " + totalValue.toFixed(2).toString().replace(".",Qt.locale().decimalPoint)) + text: i18n.tr("Your Holdings Worth") + ": $ " + totalValue.toFixed(2).toString().replace(".",Qt.locale().decimalPoint) color:AppTheme.getThemeColors(theme.name).textColorPrimary font.bold: true font.pixelSize: units.gu(2.2) From 76291b38f98f7156725e5c2ce45c557bd5dc505a Mon Sep 17 00:00:00 2001 From: Danfro Date: Sat, 25 Apr 2026 16:42:38 +0200 Subject: [PATCH 5/6] add two missing strings --- po/de.po | 33 +++++++++++++++++++-------------- po/ubcrypto.pot | 25 ++++++++++++------------- qml/AddCoinDialog.qml | 2 +- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/po/de.po b/po/de.po index 39b4e60..64a1e91 100644 --- a/po/de.po +++ b/po/de.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ubcrypto\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-24 18:15+0000\n" -"PO-Revision-Date: 2026-04-24 20:18+0200\n" +"POT-Creation-Date: 2026-04-25 14:41+0000\n" +"PO-Revision-Date: 2026-04-25 16:42+0200\n" "Last-Translator: Daniel Frost \n" "Language-Team: \n" "Language: de\n" @@ -53,6 +53,14 @@ msgstr "Coinkennzeichen (z.B. BTC)" msgid "Amount (e.g. 2.5)" msgstr "Menge (z.B. 2,5)" +#: ../qml/AddCoinDialog.qml:38 +msgid "Add" +msgstr "Hinzufügen" + +#: ../qml/AddCoinDialog.qml:38 +msgid "Update" +msgstr "Aktualisieren" + #: ../qml/AddCoinDialog.qml:59 ../qml/NewPortfolioDialog.qml:38 msgid "Cancel" msgstr "Abbrechen" @@ -65,14 +73,6 @@ msgstr "1 h:" msgid "24h:" msgstr "24 h:" -#: ../qml/ChangeStats.qml:94 -msgid "7d:" -msgstr "7d:" - -#: ../qml/ChangeStats.qml:112 -msgid "30d:" -msgstr "30d:" - #: ../qml/CoinCard.qml:93 msgid "Volume: " msgstr "Volumen: " @@ -114,7 +114,6 @@ msgid "No data available." msgstr "Keine Daten verfügbar." #: ../qml/DashboardPage.qml:247 ../qml/NewsPage.qml:21 -#: ../qml/PortfolioPage.qml:35 msgid "Refresh" msgstr "Aktualisieren" @@ -174,18 +173,24 @@ msgstr "Einheit: $%1" msgid "Current Value: $%1" msgstr "Aktueller Wert: $ %1" -#: ../qml/PortfolioPage.qml:20 ../qml/PortfolioPage.qml:25 +#: ../qml/PortfolioPage.qml:19 ../qml/PortfolioPage.qml:24 msgid "Portfolio" msgstr "Portfolio" -#: ../qml/PortfolioPage.qml:98 +#: ../qml/PortfolioPage.qml:71 msgid "Add Coin" msgstr "Coin hinzufügen" -#: ../qml/PortfolioPage.qml:108 +#: ../qml/PortfolioPage.qml:81 msgid "Your Holdings Worth" msgstr "Portfolio Gesamtwert" #: ../qml/SplashScreen.qml:41 msgid "Your Market Insights, Instantly." msgstr "Deine Marktinformationen, in Echtzeit." + +#~ msgid "7d:" +#~ msgstr "7d:" + +#~ msgid "30d:" +#~ msgstr "30d:" diff --git a/po/ubcrypto.pot b/po/ubcrypto.pot index 7d972f0..a30b363 100644 --- a/po/ubcrypto.pot +++ b/po/ubcrypto.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ubcrypto\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-24 18:15+0000\n" +"POT-Creation-Date: 2026-04-25 14:41+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -48,6 +48,14 @@ msgstr "" msgid "Amount (e.g. 2.5)" msgstr "" +#: ../qml/AddCoinDialog.qml:38 +msgid "Add" +msgstr "" + +#: ../qml/AddCoinDialog.qml:38 +msgid "Update" +msgstr "" + #: ../qml/AddCoinDialog.qml:59 ../qml/NewPortfolioDialog.qml:38 msgid "Cancel" msgstr "" @@ -60,14 +68,6 @@ msgstr "" msgid "24h:" msgstr "" -#: ../qml/ChangeStats.qml:94 -msgid "7d:" -msgstr "" - -#: ../qml/ChangeStats.qml:112 -msgid "30d:" -msgstr "" - #: ../qml/CoinCard.qml:93 msgid "Volume: " msgstr "" @@ -109,7 +109,6 @@ msgid "No data available." msgstr "" #: ../qml/DashboardPage.qml:247 ../qml/NewsPage.qml:21 -#: ../qml/PortfolioPage.qml:35 msgid "Refresh" msgstr "" @@ -169,15 +168,15 @@ msgstr "" msgid "Current Value: $%1" msgstr "" -#: ../qml/PortfolioPage.qml:20 ../qml/PortfolioPage.qml:25 +#: ../qml/PortfolioPage.qml:19 ../qml/PortfolioPage.qml:24 msgid "Portfolio" msgstr "" -#: ../qml/PortfolioPage.qml:98 +#: ../qml/PortfolioPage.qml:71 msgid "Add Coin" msgstr "" -#: ../qml/PortfolioPage.qml:108 +#: ../qml/PortfolioPage.qml:81 msgid "Your Holdings Worth" msgstr "" diff --git a/qml/AddCoinDialog.qml b/qml/AddCoinDialog.qml index d276ea4..d9c91d1 100644 --- a/qml/AddCoinDialog.qml +++ b/qml/AddCoinDialog.qml @@ -35,7 +35,7 @@ Dialog { spacing: units.gu(2) Button { - text: editMode ? "Update" : "Add" + text: editMode ? i18n.tr("Update") : i18n.tr("Add") onClicked: { if (coinSymbolField.text && coinAmountField.text) { var symbol = coinSymbolField.text; From 81fe1f0d7b703193c87d65fa88b5a56336fb1dbd Mon Sep 17 00:00:00 2001 From: Danfro Date: Sat, 25 Apr 2026 19:02:05 +0200 Subject: [PATCH 6/6] use .arg() for holdings value too --- qml/PortfolioPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qml/PortfolioPage.qml b/qml/PortfolioPage.qml index ffd0bf5..ff718e6 100644 --- a/qml/PortfolioPage.qml +++ b/qml/PortfolioPage.qml @@ -78,7 +78,7 @@ Page { // === Holdings Header === Text { - text: i18n.tr("Your Holdings Worth") + ": $ " + totalValue.toFixed(2).toString().replace(".",Qt.locale().decimalPoint) + text: i18n.tr("Your Holdings Worth: $%1").arg(totalValue.toFixed(2).toString().replace(".",Qt.locale().decimalPoint)) color:AppTheme.getThemeColors(theme.name).textColorPrimary font.bold: true font.pixelSize: units.gu(2.2)