diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 7f3336d64..629abd859 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -4,13 +4,18 @@ project(linux VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) -find_package(Qt6 REQUIRED COMPONENTS Quick Widgets Bluetooth DBus) +find_package(Qt6 REQUIRED COMPONENTS Quick Widgets Bluetooth DBus LinguistTools) find_package(OpenSSL REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(PULSEAUDIO REQUIRED libpulse) qt_standard_project_setup() +# Translation files +set(TS_FILES + translations/librepods_tr.ts +) + qt_add_executable(librepods main.cpp logger.h @@ -85,3 +90,13 @@ install(FILES assets/me.kavishdevar.librepods.desktop DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications") install(FILES assets/librepods.png DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps") + +# Translation support +qt_add_translations(librepods + TS_FILES ${TS_FILES} + QM_FILES_OUTPUT_VARIABLE QM_FILES +) + +# Install translation files +install(FILES ${QM_FILES} + DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/librepods/translations") diff --git a/linux/Main.qml b/linux/Main.qml index 4defa9bee..c7b235c33 100644 --- a/linux/Main.qml +++ b/linux/Main.qml @@ -81,7 +81,7 @@ ApplicationWindow { Label { anchors.centerIn: parent - text: airPodsTrayApp.airpodsConnected ? "Connected" : "Disconnected" + text: airPodsTrayApp.airpodsConnected ? qsTr("Connected") : qsTr("Disconnected") color: "white" font.pixelSize: 12 font.weight: Font.Medium @@ -130,7 +130,7 @@ ApplicationWindow { SegmentedControl { anchors.horizontalCenter: parent.horizontalCenter - model: ["Off", "Noise Cancellation", "Transparency", "Adaptive"] + model: [qsTr("Off"), qsTr("Noise Cancellation"), qsTr("Transparency"), qsTr("Adaptive")] currentIndex: airPodsTrayApp.deviceInfo.noiseControlMode onCurrentIndexChanged: airPodsTrayApp.setNoiseControlModeInt(currentIndex) visible: airPodsTrayApp.airpodsConnected @@ -153,21 +153,21 @@ ApplicationWindow { onValueChanged: if (pressed) debounceTimer.restart() Label { - text: "Adaptive Noise Level: " + parent.value + text: qsTr("Adaptive Noise Level: ") + parent.value anchors.top: parent.bottom } } Switch { visible: airPodsTrayApp.airpodsConnected - text: "Conversational Awareness" + text: qsTr("Conversational Awareness") checked: airPodsTrayApp.deviceInfo.conversationalAwareness onCheckedChanged: airPodsTrayApp.setConversationalAwareness(checked) } Switch { visible: airPodsTrayApp.airpodsConnected - text: "Hearing Aid" + text: qsTr("Hearing Aid") checked: airPodsTrayApp.deviceInfo.hearingAidEnabled onCheckedChanged: airPodsTrayApp.setHearingAidEnabled(checked) } @@ -189,7 +189,7 @@ ApplicationWindow { id: settingsPage Page { id: settingsPageItem - title: "Settings" + title: qsTr("Settings") ScrollView { anchors.fill: parent @@ -200,7 +200,7 @@ ApplicationWindow { padding: 20 Label { - text: "Settings" + text: qsTr("Settings") font.pixelSize: 24 // center the label anchors.horizontalCenter: parent.horizontalCenter @@ -210,19 +210,19 @@ ApplicationWindow { spacing: 5 // Small gap between label and ComboBox Label { - text: "Pause Behavior When Removing AirPods:" + text: qsTr("Pause Behavior When Removing AirPods:") } ComboBox { width: parent.width // Ensures full width - model: ["One Removed", "Both Removed", "Never"] + model: [qsTr("One Removed"), qsTr("Both Removed"), qsTr("Never")] currentIndex: airPodsTrayApp.earDetectionBehavior onActivated: airPodsTrayApp.earDetectionBehavior = currentIndex } } Switch { - text: "Cross-Device Connectivity with Android" + text: qsTr("Cross-Device Connectivity with Android") checked: airPodsTrayApp.crossDeviceEnabled onCheckedChanged: { airPodsTrayApp.setCrossDeviceEnabled(checked) @@ -230,26 +230,26 @@ ApplicationWindow { } Switch { - text: "Auto-Start on Login" + text: qsTr("Auto-Start on Login") checked: airPodsTrayApp.autoStartManager.autoStartEnabled onCheckedChanged: airPodsTrayApp.autoStartManager.autoStartEnabled = checked } Switch { - text: "Enable System Notifications" + text: qsTr("Enable System Notifications") checked: airPodsTrayApp.notificationsEnabled onCheckedChanged: airPodsTrayApp.notificationsEnabled = checked } Switch { visible: airPodsTrayApp.airpodsConnected - text: "One Bud ANC Mode" + text: qsTr("One Bud ANC Mode") checked: airPodsTrayApp.deviceInfo.oneBudANCMode onCheckedChanged: airPodsTrayApp.deviceInfo.oneBudANCMode = checked ToolTip { visible: parent.hovered - text: "Enable ANC when using one AirPod\n(More noise reduction, but uses more battery)" + text: qsTr("Enable ANC when using one AirPod\n(More noise reduction, but uses more battery)") delay: 500 } } @@ -257,7 +257,7 @@ ApplicationWindow { Row { spacing: 5 Label { - text: "Bluetooth Retry Attempts:" + text: qsTr("Bluetooth Retry Attempts:") anchors.verticalCenter: parent.verticalCenter } SpinBox { @@ -279,7 +279,7 @@ ApplicationWindow { } Button { - text: "Rename" + text: qsTr("Rename") onClicked: airPodsTrayApp.renameAirPods(newNameField.text) } } @@ -295,14 +295,14 @@ ApplicationWindow { } Button { - text: "Change Phone MAC" + text: qsTr("Change Phone MAC") onClicked: airPodsTrayApp.setPhoneMac(newPhoneMacField.text) } } Button { - text: "Show Magic Cloud Keys QR" + text: qsTr("Show Magic Cloud Keys QR") onClicked: keysQrDialog.show() } diff --git a/linux/main.cpp b/linux/main.cpp index 63456f7f1..94d341ea3 100644 --- a/linux/main.cpp +++ b/linux/main.cpp @@ -12,6 +12,10 @@ #include #include #include +#include +#include +#include +#include #include "airpods_packets.h" #include "logger.h" @@ -987,6 +991,25 @@ private slots: int main(int argc, char *argv[]) { QApplication app(argc, argv); + // Load translations + QTranslator *translator = new QTranslator(&app); + QString locale = QLocale::system().name(); + + // Try to load translation from various locations + QStringList translationPaths = { + QCoreApplication::applicationDirPath() + "/translations", + QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/librepods/translations", + "/usr/share/librepods/translations", + "/usr/local/share/librepods/translations" + }; + + for (const QString &path : translationPaths) { + if (translator->load("librepods_" + locale, path)) { + app.installTranslator(translator); + break; + } + } + QLocalServer::removeServer("app_server"); QFile stale("/tmp/app_server"); diff --git a/linux/translations/librepods_tr.ts b/linux/translations/librepods_tr.ts new file mode 100644 index 000000000..34521ab80 --- /dev/null +++ b/linux/translations/librepods_tr.ts @@ -0,0 +1,151 @@ + + + + + Main + + Connected + Bağlı + + + Disconnected + Bağlantı Kesildi + + + Off + Kapalı + + + Noise Cancellation + Gürültü Engelleme + + + Transparency + Şeffaflık + + + Adaptive + Uyarlanabilir + + + Adaptive Noise Level: + Uyarlanabilir Gürültü Seviyesi: + + + Conversational Awareness + Konuşma Farkındalığı + + + Hearing Aid + İşitme Cihazı + + + Settings + Ayarlar + + + Pause Behavior When Removing AirPods: + AirPods Çıkarıldığında Duraklatma Davranışı: + + + One Removed + Biri Çıkarıldığında + + + Both Removed + İkisi de Çıkarıldığında + + + Never + Asla + + + Cross-Device Connectivity with Android + Android ile Çapraz Cihaz Bağlantısı + + + Auto-Start on Login + Oturum Açıldığında Otomatik Başlat + + + Enable System Notifications + Sistem Bildirimlerini Etkinleştir + + + One Bud ANC Mode + Tek Kulaklık ANC Modu + + + Enable ANC when using one AirPod +(More noise reduction, but uses more battery) + Tek AirPod kullanırken ANC'yi etkinleştir +(Daha fazla gürültü azaltma, ancak daha fazla pil kullanır) + + + Bluetooth Retry Attempts: + Bluetooth Yeniden Deneme Sayısı: + + + Rename + Yeniden Adlandır + + + Change Phone MAC + Telefon MAC Adresini Değiştir + + + Show Magic Cloud Keys QR + Magic Cloud Anahtarları QR'ını Göster + + + + TrayIconManager + + Battery Status: + Pil Durumu: + + + Open + + + + Settings + Ayarlar + + + Toggle Conversational Awareness + Konuşma Farkındalığını Aç/Kapat + + + Adaptive + Uyarlanabilir + + + Transparency + Şeffaflık + + + Noise Cancellation + Gürültü Engelleme + + + Off + Kapalı + + + Quit + Çıkış + + + + AirPodsTrayApp + + AirPods Disconnected + AirPods Bağlantısı Kesildi + + + Your AirPods have been disconnected + AirPods'unuzun bağlantısı kesildi + + + diff --git a/linux/trayiconmanager.cpp b/linux/trayiconmanager.cpp index 5c811912a..738feecf1 100644 --- a/linux/trayiconmanager.cpp +++ b/linux/trayiconmanager.cpp @@ -36,7 +36,7 @@ void TrayIconManager::showNotification(const QString &title, const QString &mess void TrayIconManager::TrayIconManager::updateBatteryStatus(const QString &status) { - trayIcon->setToolTip("Battery Status: " + status); + trayIcon->setToolTip(tr("Battery Status: ") + status); updateIconFromBattery(status); } @@ -57,20 +57,20 @@ void TrayIconManager::updateConversationalAwareness(bool enabled) void TrayIconManager::setupMenuActions() { // Open action - QAction *openAction = new QAction("Open", trayMenu); + QAction *openAction = new QAction(tr("Open"), trayMenu); trayMenu->addAction(openAction); connect(openAction, &QAction::triggered, qApp, [this](){emit openApp();}); // Settings Menu - QAction *settingsMenu = new QAction("Settings", trayMenu); + QAction *settingsMenu = new QAction(tr("Settings"), trayMenu); trayMenu->addAction(settingsMenu); connect(settingsMenu, &QAction::triggered, qApp, [this](){emit openSettings();}); trayMenu->addSeparator(); // Conversational Awareness Toggle - caToggleAction = new QAction("Toggle Conversational Awareness", trayMenu); + caToggleAction = new QAction(tr("Toggle Conversational Awareness"), trayMenu); caToggleAction->setCheckable(true); trayMenu->addAction(caToggleAction); connect(caToggleAction, &QAction::triggered, this, [this](bool checked) @@ -81,10 +81,10 @@ void TrayIconManager::setupMenuActions() // Noise Control Options noiseControlGroup = new QActionGroup(trayMenu); const QPair noiseOptions[] = { - {"Adaptive", NoiseControlMode::Adaptive}, - {"Transparency", NoiseControlMode::Transparency}, - {"Noise Cancellation", NoiseControlMode::NoiseCancellation}, - {"Off", NoiseControlMode::Off}}; + {tr("Adaptive"), NoiseControlMode::Adaptive}, + {tr("Transparency"), NoiseControlMode::Transparency}, + {tr("Noise Cancellation"), NoiseControlMode::NoiseCancellation}, + {tr("Off"), NoiseControlMode::Off}}; for (auto option : noiseOptions) { @@ -100,7 +100,7 @@ void TrayIconManager::setupMenuActions() trayMenu->addSeparator(); // Quit action - QAction *quitAction = new QAction("Quit", trayMenu); + QAction *quitAction = new QAction(tr("Quit"), trayMenu); trayMenu->addAction(quitAction); connect(quitAction, &QAction::triggered, qApp, &QApplication::quit); }