diff --git a/linphone-desktop/assets/languages/en.ts b/linphone-desktop/assets/languages/en.ts
index 361c3c0e1..71311234a 100644
--- a/linphone-desktop/assets/languages/en.ts
+++ b/linphone-desktop/assets/languages/en.ts
@@ -859,6 +859,10 @@ Server url not configured.
languagesLabel
Language
+
+ systemLocale
+ System locale
+
SettingsWindow
diff --git a/linphone-desktop/assets/languages/fr.ts b/linphone-desktop/assets/languages/fr.ts
index 90e117183..810e2f75c 100644
--- a/linphone-desktop/assets/languages/fr.ts
+++ b/linphone-desktop/assets/languages/fr.ts
@@ -869,6 +869,10 @@ Url du serveur non configurée.
languagesLabel
Langue
+
+ systemLocale
+ Locale du système
+
SettingsWindow
diff --git a/linphone-desktop/src/app/App.cpp b/linphone-desktop/src/app/App.cpp
index 7775f2e00..9319b3ca7 100644
--- a/linphone-desktop/src/app/App.cpp
+++ b/linphone-desktop/src/app/App.cpp
@@ -29,18 +29,20 @@
#include "../components/settings/SettingsModel.hpp"
#include "../components/smart-search-bar/SmartSearchBarModel.hpp"
#include "../components/timeline/TimelineModel.hpp"
+#include "../utils.hpp"
#include "App.hpp"
+#include "DefaultTranslator.hpp"
#include "Logger.hpp"
+#include
#include
#include
-#include
-#include
-#include
#include
#include
+#define DEFAULT_LOCALE "en"
+
#define LANGUAGES_PATH ":/languages/"
#define WINDOW_ICON_PATH ":/assets/images/linphone_logo.svg"
@@ -53,45 +55,32 @@
App *App::m_instance = nullptr;
+inline bool installLocale (App &app, QTranslator &translator, const QLocale &locale) {
+ return translator.load(locale, LANGUAGES_PATH) && app.installTranslator(&translator);
+}
+
App::App (int &argc, char **argv) : QApplication(argc, argv) {
- this->setApplicationVersion("4.0");
+ setApplicationVersion("4.0");
- if (m_english_translator.load(QLocale(QLocale::English), LANGUAGES_PATH))
- installTranslator(&m_english_translator);
- else
- qWarning("Unable to install english translator.");
+ // List available locales.
+ for (const auto &locale : QDir(LANGUAGES_PATH).entryList())
+ m_available_locales << QLocale(locale);
- // Try to use default locale.
- QLocale current_locale = QLocale::system();
+ m_translator = new DefaultTranslator(this);
- if (m_default_translator.load(current_locale, LANGUAGES_PATH)) {
- installTranslator(&m_default_translator);
- m_locale = current_locale.name();
- } else {
- qWarning() << QStringLiteral("Unable to found translations for locale: %1.")
- .arg(current_locale.name());
+ // Try to use system locale.
+ QLocale sys_locale = QLocale::system();
+ if (installLocale(*this, *m_translator, sys_locale)) {
+ m_locale = sys_locale.name();
+ qInfo() << QStringLiteral("Use system locale: %1").arg(m_locale);
+ return;
}
-}
-// -----------------------------------------------------------------------------
-
-QQuickWindow *App::getCallsWindow () const {
- return m_calls_window;
-}
-
-QQuickWindow *App::getMainWindow () const {
- QQmlApplicationEngine &engine = const_cast(m_engine);
- return qobject_cast(engine.rootObjects().at(0));
-}
-
-QQuickWindow *App::getSettingsWindow () const {
- return m_settings_window;
-}
-
-// -----------------------------------------------------------------------------
-
-bool App::hasFocus () const {
- return getMainWindow()->isActive() || m_calls_window->isActive();
+ // Use english.
+ m_locale = DEFAULT_LOCALE;
+ if (!installLocale(*this, *m_translator, QLocale(m_locale)))
+ qFatal("Unable to install default translator.");
+ qInfo() << QStringLiteral("Use default locale: %1").arg(m_locale);
}
// -----------------------------------------------------------------------------
@@ -118,9 +107,30 @@ void App::initContentApp () {
// Init core.
CoreManager::init(m_parser.value("config"));
qInfo() << "Core manager initialized.";
-
qInfo() << "Activated selectors:" << QQmlFileSelector::get(&m_engine)->selector()->allSelectors();
+ // Try to use preferred locale.
+ {
+ QString locale = getConfigLocale();
+
+ if (!locale.isEmpty()) {
+ DefaultTranslator *translator = new DefaultTranslator(this);
+
+ if (installLocale(*this, *translator, QLocale(locale))) {
+ // Use config.
+ m_translator->deleteLater();
+ m_translator = translator;
+ m_locale = locale;
+
+ qInfo() << QStringLiteral("Use preferred locale: %1").arg(locale);
+ } else {
+ // Reset config.
+ setConfigLocale("");
+ translator->deleteLater();
+ }
+ }
+ }
+
// Register types ans make sub windows.
registerTypes();
createSubWindows();
@@ -177,6 +187,27 @@ void App::parseArgs () {
// -----------------------------------------------------------------------------
+QQuickWindow *App::getCallsWindow () const {
+ return m_calls_window;
+}
+
+QQuickWindow *App::getMainWindow () const {
+ QQmlApplicationEngine &engine = const_cast(m_engine);
+ return qobject_cast(engine.rootObjects().at(0));
+}
+
+QQuickWindow *App::getSettingsWindow () const {
+ return m_settings_window;
+}
+
+// -----------------------------------------------------------------------------
+
+bool App::hasFocus () const {
+ return getMainWindow()->isActive() || m_calls_window->isActive();
+}
+
+// -----------------------------------------------------------------------------
+
void App::registerTypes () {
qInfo() << "Registering types...";
@@ -323,6 +354,28 @@ void App::setTrayIcon () {
// -----------------------------------------------------------------------------
+QString App::getConfigLocale () const {
+ return ::Utils::linphoneStringToQString(
+ CoreManager::getInstance()->getCore()->getConfig()->getString(
+ SettingsModel::UI_SECTION, "locale", ""
+ )
+ );
+}
+
+void App::setConfigLocale (const QString &locale) {
+ CoreManager::getInstance()->getCore()->getConfig()->setString(
+ SettingsModel::UI_SECTION, "locale", ::Utils::qStringToLinphoneString(locale)
+ );
+
+ emit configLocaleChanged(locale);
+}
+
+QString App::getLocale () const {
+ return m_locale;
+}
+
+// -----------------------------------------------------------------------------
+
void App::quit () {
if (m_parser.isSet("selftest")) {
cout << tr("selftestResult").toStdString() << endl;
diff --git a/linphone-desktop/src/app/App.hpp b/linphone-desktop/src/app/App.hpp
index 14cfe8522..92ee4ee83 100644
--- a/linphone-desktop/src/app/App.hpp
+++ b/linphone-desktop/src/app/App.hpp
@@ -25,7 +25,6 @@
#include "../components/notifier/Notifier.hpp"
#include "AvatarProvider.hpp"
-#include "DefaultTranslator.hpp"
#include "ThumbnailProvider.hpp"
#include
@@ -37,10 +36,19 @@
// =============================================================================
+class DefaultTranslator;
+
class App : public QApplication {
Q_OBJECT;
+ Q_PROPERTY(QString configLocale READ getConfigLocale WRITE setConfigLocale NOTIFY configLocaleChanged);
+ Q_PROPERTY(QString locale READ getLocale CONSTANT);
+ Q_PROPERTY(QVariantList availableLocales READ getAvailableLocales CONSTANT);
+
public:
+ void initContentApp ();
+ void parseArgs ();
+
QQmlEngine *getEngine () {
return &m_engine;
}
@@ -54,16 +62,8 @@ public:
bool hasFocus () const;
- void initContentApp ();
-
Q_INVOKABLE QQuickWindow *getSettingsWindow () const;
- Q_INVOKABLE QString locale () const {
- return m_locale;
- }
-
- void parseArgs ();
-
static void create (int &argc, char **argv) {
if (!m_instance) {
// Instance must be exists before content.
@@ -78,6 +78,9 @@ public:
public slots:
void quit ();
+signals:
+ void configLocaleChanged (const QString &locale);
+
private:
App (int &argc, char **argv);
~App () = default;
@@ -86,6 +89,15 @@ private:
void createSubWindows ();
void setTrayIcon ();
+ QString getConfigLocale () const;
+ void setConfigLocale (const QString &locale);
+
+ QString getLocale () const;
+
+ QVariantList getAvailableLocales () const {
+ return m_available_locales;
+ }
+
QCommandLineParser m_parser;
QQmlApplicationEngine m_engine;
QQmlFileSelector *m_file_selector = nullptr;
@@ -93,11 +105,13 @@ private:
AvatarProvider m_avatar_provider;
ThumbnailProvider m_thumbnail_provider;
- DefaultTranslator m_default_translator;
- QTranslator m_english_translator;
+
+ DefaultTranslator *m_translator = nullptr;
Notifier *m_notifier = nullptr;
- QString m_locale = "en";
+
+ QVariantList m_available_locales;
+ QString m_locale;
QQuickWindow *m_calls_window = nullptr;
QQuickWindow *m_settings_window = nullptr;
diff --git a/linphone-desktop/src/app/DefaultTranslator.cpp b/linphone-desktop/src/app/DefaultTranslator.cpp
index f6604fe1e..df77ffa35 100644
--- a/linphone-desktop/src/app/DefaultTranslator.cpp
+++ b/linphone-desktop/src/app/DefaultTranslator.cpp
@@ -27,7 +27,7 @@
// =============================================================================
-DefaultTranslator::DefaultTranslator () {
+DefaultTranslator::DefaultTranslator (QObject *parent) : QTranslator(parent) {
QDirIterator it(":", QDirIterator::Subdirectories);
while (it.hasNext()) {
QFileInfo info(it.next());
diff --git a/linphone-desktop/src/app/DefaultTranslator.hpp b/linphone-desktop/src/app/DefaultTranslator.hpp
index 7ee1387ed..ba239c01a 100644
--- a/linphone-desktop/src/app/DefaultTranslator.hpp
+++ b/linphone-desktop/src/app/DefaultTranslator.hpp
@@ -30,7 +30,7 @@
class DefaultTranslator : public QTranslator {
public:
- DefaultTranslator ();
+ DefaultTranslator (QObject *parent = Q_NULLPTR);
~DefaultTranslator () = default;
QString translate (
diff --git a/linphone-desktop/src/components/settings/SettingsModel.hpp b/linphone-desktop/src/components/settings/SettingsModel.hpp
index be95f538d..a13968171 100644
--- a/linphone-desktop/src/components/settings/SettingsModel.hpp
+++ b/linphone-desktop/src/components/settings/SettingsModel.hpp
@@ -37,6 +37,8 @@ class SettingsModel : public QObject {
public:
SettingsModel (QObject *parent = Q_NULLPTR);
+ static const std::string UI_SECTION;
+
signals:
void autoAnswerStatusChanged (bool status);
void fileTransferUrlChanged (const QString &url);
@@ -49,8 +51,6 @@ private:
void setFileTransferUrl (const QString &url);
std::shared_ptr m_config;
-
- static const std::string UI_SECTION;
};
#endif // SETTINGS_MODEL_H_
diff --git a/linphone-desktop/src/main.cpp b/linphone-desktop/src/main.cpp
index 11175a1f2..2bfbce435 100644
--- a/linphone-desktop/src/main.cpp
+++ b/linphone-desktop/src/main.cpp
@@ -43,9 +43,11 @@ int main (int argc, char *argv[]) {
*/
App::create(argc, argv);
- App::getInstance()->parseArgs();
- App::getInstance()->initContentApp();
+
+ App *app = App::getInstance();
+ app->parseArgs();
+ app->initContentApp();
// Run!
- return App::getInstance()->exec();
+ return app->exec();
}
diff --git a/linphone-desktop/ui/modules/Linphone/Chat/Chat.qml b/linphone-desktop/ui/modules/Linphone/Chat/Chat.qml
index 438c68d94..0419ff70c 100644
--- a/linphone-desktop/ui/modules/Linphone/Chat/Chat.qml
+++ b/linphone-desktop/ui/modules/Linphone/Chat/Chat.qml
@@ -150,7 +150,7 @@ Rectangle {
// Cast section to integer because Qt converts the
// sectionDate in string!!!
text: new Date(section).toLocaleDateString(
- Qt.locale(App.locale())
+ Qt.locale(App.locale)
)
}
}
@@ -237,7 +237,7 @@ Rectangle {
color: ChatStyle.entry.time.color
font.pointSize: ChatStyle.entry.time.fontSize
text: $chatEntry.timestamp.toLocaleString(
- Qt.locale(App.locale()),
+ Qt.locale(App.locale),
'hh:mm'
)
verticalAlignment: Text.AlignVCenter
diff --git a/linphone-desktop/ui/modules/Linphone/Timeline.qml b/linphone-desktop/ui/modules/Linphone/Timeline.qml
index c9c56f0ad..a312a201e 100644
--- a/linphone-desktop/ui/modules/Linphone/Timeline.qml
+++ b/linphone-desktop/ui/modules/Linphone/Timeline.qml
@@ -160,7 +160,7 @@ ColumnLayout {
anchors.fill: parent
sourceComponent: TooltipArea {
text: $timelineEntry.timestamp.toLocaleString(
- Qt.locale(App.locale()),
+ Qt.locale(App.locale),
Locale.ShortFormat
)
}
diff --git a/linphone-desktop/ui/scripts/Utils/utils.js b/linphone-desktop/ui/scripts/Utils/utils.js
index 3289056be..d79a05e60 100644
--- a/linphone-desktop/ui/scripts/Utils/utils.js
+++ b/linphone-desktop/ui/scripts/Utils/utils.js
@@ -230,7 +230,7 @@ function _indexFinder (array, cb, context) {
var length = array.length
for (var i = 0; i < length; i++) {
- if (cb(array[index], index, array)) {
+ if (cb(array[i], i, array)) {
return i
}
}
@@ -274,6 +274,12 @@ function basename (str) {
// -----------------------------------------------------------------------------
+function capitalizeFirstLetter (str) {
+ return str.charAt(0).toUpperCase() + str.slice(1)
+}
+
+// -----------------------------------------------------------------------------
+
function dirname (str) {
var str2 = str
var length = str2.length - 1
@@ -342,6 +348,15 @@ function find (obj, cb, context) {
// -----------------------------------------------------------------------------
+function findIndex (array, cb, context) {
+ cb = _computeOptimizedCb(cb, context)
+
+ var key = _indexFinder(array, cb, context)
+ return key != null && key !== -1 ? key : null
+}
+
+// -----------------------------------------------------------------------------
+
function formatElapsedTime (seconds) {
seconds = parseInt(seconds, 10)
diff --git a/linphone-desktop/ui/views/App/Settings/SettingsUi.qml b/linphone-desktop/ui/views/App/Settings/SettingsUi.qml
index a32a9b16f..a34586b3b 100644
--- a/linphone-desktop/ui/views/App/Settings/SettingsUi.qml
+++ b/linphone-desktop/ui/views/App/Settings/SettingsUi.qml
@@ -1,6 +1,8 @@
import QtQuick 2.7
import Common 1.0
+import Linphone 1.0
+import Utils 1.0
import App.Styles 1.0
@@ -24,10 +26,49 @@ TabContainer {
label: qsTr('languagesLabel')
ComboBox {
- model: ListModel {
- ListElement { key: 'English'; value: 0 }
- ListElement { key: 'Français'; value: 1 }
+ function _getAvailableLocales () {
+ var locales = []
+
+ App.availableLocales.forEach(function (locale) {
+ locales.push({
+ key: Utils.capitalizeFirstLetter(locale.nativeLanguageName),
+ value: locale.name
+ })
+ })
+
+ return locales.sort(function (a, b) {
+ return a > b
+ })
}
+
+ model: ListModel {}
+
+ Component.onCompleted: {
+ var locales = _getAvailableLocales()
+
+ model.append({
+ key: qsTr('systemLocale'),
+ value: ''
+ })
+ locales.forEach(function (locale) {
+ model.append(locale)
+ })
+
+ var locale = App.configLocale
+ if (!locale.length) {
+ currentIndex = 0
+ return
+ }
+
+ var value = Qt.locale(locale).name
+ var index = Utils.findIndex(locales, function (locale) {
+ return locale.value === value
+ })
+
+ currentIndex = index != null ? index + 1 : 0
+ }
+
+ onActivated: App.configLocale = model.get(index).value
}
}
}