Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
36 changes: 18 additions & 18 deletions linux/Main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
}
Expand All @@ -189,7 +189,7 @@ ApplicationWindow {
id: settingsPage
Page {
id: settingsPageItem
title: "Settings"
title: qsTr("Settings")

ScrollView {
anchors.fill: parent
Expand All @@ -200,7 +200,7 @@ ApplicationWindow {
padding: 20

Label {
text: "Settings"
text: qsTr("Settings")
font.pixelSize: 24
// center the label
anchors.horizontalCenter: parent.horizontalCenter
Expand All @@ -210,54 +210,54 @@ 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)
}
}

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
}
}

Row {
spacing: 5
Label {
text: "Bluetooth Retry Attempts:"
text: qsTr("Bluetooth Retry Attempts:")
anchors.verticalCenter: parent.verticalCenter
}
SpinBox {
Expand All @@ -279,7 +279,7 @@ ApplicationWindow {
}

Button {
text: "Rename"
text: qsTr("Rename")
onClicked: airPodsTrayApp.renameAirPods(newNameField.text)
}
}
Expand All @@ -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()
}

Expand Down
23 changes: 23 additions & 0 deletions linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#include <QTimer>
#include <QProcess>
#include <QRegularExpression>
#include <QTranslator>
#include <QLibraryInfo>
#include <QDir>
#include <QStandardPaths>

#include "airpods_packets.h"
#include "logger.h"
Expand Down Expand Up @@ -987,6 +991,25 @@ private slots:
int main(int argc, char *argv[]) {
QApplication app(argc, argv);

// Load translations
QTranslator translator;
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The QTranslator translator object is allocated on the stack in the main() function. Once main() returns, this object will be destroyed, which could cause issues if the application tries to access translations after the translator is destroyed. The translator should be allocated on the heap or kept alive for the application's lifetime.

Consider changing to:

QTranslator *translator = new QTranslator(&app);
QString locale = QLocale::system().name();

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;
    }
}

Copilot uses AI. Check for mistakes.
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");
Expand Down
151 changes: 151 additions & 0 deletions linux/translations/librepods_tr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="tr_TR">
<context>
<name>Main</name>
<message>
<source>Connected</source>
<translation>Bağlı</translation>
</message>
<message>
<source>Disconnected</source>
<translation>Bağlantı Kesildi</translation>
</message>
<message>
<source>Off</source>
<translation>Kapalı</translation>
</message>
<message>
<source>Noise Cancellation</source>
<translation>Gürültü Engelleme</translation>
</message>
<message>
<source>Transparency</source>
<translation>Şeffaflık</translation>
</message>
<message>
<source>Adaptive</source>
<translation>Uyarlanabilir</translation>
</message>
<message>
<source>Adaptive Noise Level: </source>
<translation>Uyarlanabilir Gürültü Seviyesi: </translation>
</message>
<message>
<source>Conversational Awareness</source>
<translation>Konuşma Farkındalığı</translation>
</message>
<message>
<source>Hearing Aid</source>
<translation>İşitme Cihazı</translation>
</message>
<message>
<source>Settings</source>
<translation>Ayarlar</translation>
</message>
<message>
<source>Pause Behavior When Removing AirPods:</source>
<translation>AirPods Çıkarıldığında Duraklatma Davranışı:</translation>
</message>
<message>
<source>One Removed</source>
<translation>Biri Çıkarıldığında</translation>
</message>
<message>
<source>Both Removed</source>
<translation>İkisi de Çıkarıldığında</translation>
</message>
<message>
<source>Never</source>
<translation>Asla</translation>
</message>
<message>
<source>Cross-Device Connectivity with Android</source>
<translation>Android ile Çapraz Cihaz Bağlantısı</translation>
</message>
<message>
<source>Auto-Start on Login</source>
<translation>Oturum Açıldığında Otomatik Başlat</translation>
</message>
<message>
<source>Enable System Notifications</source>
<translation>Sistem Bildirimlerini Etkinleştir</translation>
</message>
<message>
<source>One Bud ANC Mode</source>
<translation>Tek Kulaklık ANC Modu</translation>
</message>
<message>
<source>Enable ANC when using one AirPod
(More noise reduction, but uses more battery)</source>
<translation>Tek AirPod kullanırken ANC&apos;yi etkinleştir
(Daha fazla gürültü azaltma, ancak daha fazla pil kullanır)</translation>
</message>
<message>
<source>Bluetooth Retry Attempts:</source>
<translation>Bluetooth Yeniden Deneme Sayısı:</translation>
</message>
<message>
<source>Rename</source>
<translation>Yeniden Adlandır</translation>
</message>
<message>
<source>Change Phone MAC</source>
<translation>Telefon MAC Adresini Değiştir</translation>
</message>
<message>
<source>Show Magic Cloud Keys QR</source>
<translation>Magic Cloud Anahtarları QR&apos;ını Göster</translation>
</message>
</context>
<context>
<name>TrayIconManager</name>
<message>
<source>Battery Status: </source>
<translation>Pil Durumu: </translation>
</message>
<message>
<source>Open</source>
<translation>Aç</translation>
</message>
<message>
<source>Settings</source>
<translation>Ayarlar</translation>
</message>
<message>
<source>Toggle Conversational Awareness</source>
<translation>Konuşma Farkındalığını Aç/Kapat</translation>
</message>
<message>
<source>Adaptive</source>
<translation>Uyarlanabilir</translation>
</message>
<message>
<source>Transparency</source>
<translation>Şeffaflık</translation>
</message>
<message>
<source>Noise Cancellation</source>
<translation>Gürültü Engelleme</translation>
</message>
<message>
<source>Off</source>
<translation>Kapalı</translation>
</message>
<message>
<source>Quit</source>
<translation>Çıkış</translation>
</message>
</context>
<context>
<name>AirPodsTrayApp</name>
<message>
<source>AirPods Disconnected</source>
<translation>AirPods Bağlantısı Kesildi</translation>
</message>
<message>
<source>Your AirPods have been disconnected</source>
<translation>AirPods&apos;unuzun bağlantısı kesildi</translation>
</message>
</context>
</TS>
Loading
Loading