Merge pull request #1044 from lexcibien/master

Adding translation to app and Portuguese Brazilian translation
This commit is contained in:
Collin Kidder
2026-04-15 21:05:04 -04:00
committed by GitHub
14 changed files with 7443 additions and 3 deletions
+5
View File
@@ -57,7 +57,9 @@ jobs:
- name: Package
run: |
mkdir -p SavvyCAN.app/Contents/MacOS/translations
mkdir -p SavvyCAN.app/Contents/MacOS/help
cp -R translations/*.qm SavvyCAN.app/Contents/MacOS/translations
cp -R help/* SavvyCAN.app/Contents/MacOS/help
macdeployqt SavvyCAN.app -dmg
mv SavvyCAN.dmg SavvyCAN_x64.dmg
@@ -87,7 +89,9 @@ jobs:
- name: Package
run: |
mkdir -p SavvyCAN.app/Contents/MacOS/translations
mkdir -p SavvyCAN.app/Contents/MacOS/help
cp -R translations/*.qm SavvyCAN.app/Contents/MacOS/translations
cp -R help/* SavvyCAN.app/Contents/MacOS/help
macdeployqt SavvyCAN.app -dmg
mv SavvyCAN.dmg SavvyCAN_arm64.dmg
@@ -120,6 +124,7 @@ jobs:
mkdir package
copy "release/SavvyCAN.exe" package/
mkdir package/help
copy translations/*.qm package/translations/
copy help/*.md package/help/
mkdir package/help/images
copy help/images/*.* package/help/images/
+4
View File
@@ -7,6 +7,9 @@ build/
*.o
*.obj
# Compiled translations
*.qm
# Precompiled Headers
*.gch
*.pch
@@ -36,6 +39,7 @@ SavvyCAN
**/moc_*
**/ui_*.h
**/qrc_*.cpp
.qtc_clangd
SavvyCAN.pro.user.*
.qmake.stash
Makefile
+4
View File
@@ -1,11 +1,15 @@
[Desktop Entry]
Type=Application
Name=SavvyCAN
Name[pt_BR]=SavvyCAN
GenericName=CANBus reverse engineering tool
GenericName[pt_BR]=Ferramenta Rede CAN de engenharia reversa
Comment=Facilitates reverse engineering of canbus captures
Comment[pt_BR]=Facilitar engenharia reversa de capturas de Rede CAN
Exec=SavvyCAN
Icon=SavvyCAN
Terminal=false
Categories=Development;Electronics;IDE;
MimeType=text/x-application;
Keywords=embedded electronics;electronics;canbus;reverse engineering;
Keywords[pt_BR]=eletronica embarcada;eletronicos;canbus;engenharia reversa;
+6
View File
@@ -279,3 +279,9 @@ INSTALLS += helpfiles
INSTALLS += target
TRANSLATIONS += \
translations/SavvyCAN_en.ts \
translations/SavvyCAN_pt_BR.ts
DISTFILES += \
translations/pt_BR.qph
+26 -3
View File
@@ -1,5 +1,8 @@
#include "mainwindow.h"
#include <QApplication>
#include <QTranslator>
#include <QLocale>
#include <QDebug>
class SavvyCANApplication : public QApplication
{
@@ -39,11 +42,31 @@ int main(int argc, char *argv[])
a.setOrganizationName("EVTV");
a.setApplicationName("SavvyCAN");
a.setOrganizationDomain("evtv.me");
QSettings::setDefaultFormat(QSettings::IniFormat);
QSettings settings;
QString localeString = settings.value("Main/Language").toString();
if (localeString.isEmpty()) {
QLocale sysLocale = QLocale::system();
localeString = sysLocale.name();
settings.setValue("Main/Language", localeString);
}
QTranslator translator;
QLocale locale(localeString);
QString lang = locale.name();
QString shortLang = locale.name().left(2);
if (QString translationDir = QCoreApplication::applicationDirPath() + "/translations"; !translator.load("SavvyCAN_" + lang, translationDir)) {
translator.load("SavvyCAN_" + shortLang, translationDir);
}
a.installTranslator(&translator);
qInfo() << "Locale Value is:" << locale.name();
a.mainWindow = new MainWindow();
QSettings settings;
int fontSize = settings.value("Main/FontSize", 9).toUInt();
QFont sysFont = QFont(); //get default font
sysFont.setPointSize(fontSize);
@@ -52,8 +75,8 @@ int main(int argc, char *argv[])
a.mainWindow->show();
int retCode = a.exec();
delete a.mainWindow; a.mainWindow = NULL;
return retCode;
}
+50
View File
@@ -3,6 +3,10 @@
#include "helpwindow.h"
#include <qevent.h>
#include <QDebug>
#include <QDir>
#include <QRegExp>
#include <QCoreApplication>
#include <QDebug>
#include "simplecrypt.h"
//using this simple encryption library to obfuscate stored password a bit. It's not super secure but better than
@@ -10,6 +14,42 @@
//whatever key, you'd see it. Just behave yourselves
SimpleCrypt crypto(Q_UINT64_C(0xdeadbeefface6285));
static QStringList availableLanguageCodes()
{
QStringList codes;
QDir transDir(QCoreApplication::applicationDirPath() + "/translations");
QStringList list = transDir.entryList(QStringList() << "SavvyCAN_*.qm");
//* just for test purposes
if (list.isEmpty()) {
// maybe only ts files exist during development
list = transDir.entryList(QStringList() << "SavvyCAN_*.ts");
}
for (QString file : list) {
QRegExp re("SavvyCAN_(.*)\\.(qm|ts)");
if (re.indexIn(file) != -1) {
codes << re.cap(1);
}
}
return codes;
}
void MainSettingsDialog::populateLanguageCombo()
{
ui->comboLanguage->clear();
QStringList codes = availableLanguageCodes();
if (codes.isEmpty()) {
codes << "en"; // fallback
}
for (const QString &code : codes) {
QLocale locale(code);
QString name = locale.nativeLanguageName();
qInfo() << code;
if (name.isEmpty())
name = code;
ui->comboLanguage->addItem(name, code);
}
}
MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::MainSettingsDialog)
@@ -17,6 +57,8 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
QSettings settings;
ui->setupUi(this);
populateLanguageCombo();
//TODO: This is still hard coded to support only two buses. Sometimes there is none, sometimes 1, sometimes much more than 2. Fix this.
ui->comboSendingBus->addItem(tr("None"));
ui->comboSendingBus->addItem(tr("0"));
@@ -94,6 +136,12 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
ui->cbIgnoreDBCColors->setChecked(settings.value("Main/IgnoreDBCColors", false).toBool());
ui->cbColorsByCanId->setChecked(settings.value("Main/ColorsByCanId", false).toBool());
if (QString savedLang = settings.value("Main/Language").toString(); !savedLang.isEmpty()) {
int idx = ui->comboLanguage->findData(savedLang);
if (idx >= 0)
ui->comboLanguage->setCurrentIndex(idx);
}
int maxFramesDefault;
if (QSysInfo::WordSize > 32)
{
@@ -110,6 +158,7 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
ui->spinBytesPerLine->setValue(settings.value("Main/BytesPerLine", 8).toInt());
//just for simplicity they all call the same function and that function updates all settings at once
connect(ui->comboLanguage, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSettings()));
connect(ui->cbDisplayHex, SIGNAL(toggled(bool)), this, SLOT(updateSettings()));
connect(ui->cbFlowAutoRef, SIGNAL(toggled(bool)), this, SLOT(updateSettings()));
connect(ui->cbFlowUseTimestamp, SIGNAL(toggled(bool)), this, SLOT(updateSettings()));
@@ -179,6 +228,7 @@ void MainSettingsDialog::updateSettings()
{
QSettings settings;
settings.setValue("Main/Language", ui->comboLanguage->currentData().toString());
settings.setValue("Main/UseHex", ui->cbDisplayHex->isChecked());
settings.setValue("FlowView/AutoRef", ui->cbFlowAutoRef->isChecked());
settings.setValue("FlowView/UseTimestamp", ui->cbFlowUseTimestamp->isChecked());
+1
View File
@@ -25,6 +25,7 @@ public slots:
private:
Ui::MainSettingsDialog *ui;
void populateLanguageCombo();
void closeEvent(QCloseEvent *event);
bool eventFilter(QObject *obj, QEvent *event);
};
+13
View File
@@ -0,0 +1,13 @@
# Scripts
To run this scripts, first you must authorize your terminal to run:
```bash
chmod +x script/*.sh
```
Then you can run by using this command:
```bash
./scripts/the/script/you/want/to/run
```
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
PROJECT_ROOT="$(pwd)"
# To add this tool in Qt Creator:
# Category: Linguist
# Name: Release Translations (lrelease)
# Executable: lrelease
# Arguments: SavvyCAN.pro
# Working Directory: %{ActiveProject:Path}
echo "Generating .qm files..."
lrelease -verbose "$PROJECT_ROOT"/SavvyCAN.pro
echo ".qm files generated."
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
PROJECT_ROOT="$(pwd)"
# To add this tool in Qt Creator:
# Category: Linguist
# Name: Update Translations (lupdate)
# Executable: lupdate
# Arguments: -project SavvyCAN.pro
# Working Directory: %{ActiveProject:Path}
echo "Updating translation files..."
lupdate -verbose "$PROJECT_ROOT"/SavvyCAN.pro
echo "Translation files updated."
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+47
View File
@@ -0,0 +1,47 @@
<!DOCTYPE QPH>
<QPH sourcelanguage="en" language="pt_BR">
<phrase>
<source>New</source>
<target>Novo</target>
</phrase>
<phrase>
<source>Save</source>
<target>Salvar</target>
</phrase>
<phrase>
<source>Cancel</source>
<target>Cancelar</target>
</phrase>
<phrase>
<source>Connect</source>
<target>Conectar</target>
</phrase>
<phrase>
<source>Disconnect</source>
<target>Desconectar</target>
</phrase>
<phrase>
<source>Yes</source>
<target>Sim</target>
</phrase>
<phrase>
<source>No</source>
<target>Não</target>
</phrase>
<phrase>
<source>Bus</source>
<target>Barramento</target>
</phrase>
<phrase>
<source>Frame</source>
<target>Frame</target>
</phrase>
<phrase>
<source>Frames</source>
<target>Frames</target>
</phrase>
<phrase>
<source>Scan</source>
<target>Varredura</target>
</phrase>
</QPH>
+14
View File
@@ -53,6 +53,20 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>Language</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboLanguage"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>