diff --git a/python/server/auto_generated/qgsserversettings.sip.in b/python/server/auto_generated/qgsserversettings.sip.in
index c7863cc9ab73..27b8870cb449 100644
--- a/python/server/auto_generated/qgsserversettings.sip.in
+++ b/python/server/auto_generated/qgsserversettings.sip.in
@@ -39,7 +39,7 @@ Load settings according to current environment variables.
%Docstring
Load setting for a specific environment variable name.
-:return: true if loading is successful, false in case of an invalid name.
+:return: TRUE if loading is successful, FALSE in case of an invalid name.
%End
void logSummary() const;
@@ -58,7 +58,7 @@ Returns the ini file loaded by QSetting.
%Docstring
Returns parallel rendering setting.
-:return: true if parallel rendering is activated, false otherwise.
+:return: TRUE if parallel rendering is activated, FALSE otherwise.
%End
int maxThreads() const;
@@ -117,6 +117,24 @@ Returns the cache size.
Returns the cache directory.
:return: the directory.
+%End
+
+ QString overrideSystemLocale() const;
+%Docstring
+Overrides system locale
+
+:return: the optional override for system locale.
+
+.. versionadded:: 3.8
+%End
+
+ bool showGroupSeparator() const;
+%Docstring
+Show group (thousand) separator
+
+:return: if group separator must be shown, default to FALSE.
+
+.. versionadded:: 3.8
%End
};
diff --git a/src/server/qgsserver.cpp b/src/server/qgsserver.cpp
index 1cfc37dfaefd..53fe2810f584 100644
--- a/src/server/qgsserver.cpp
+++ b/src/server/qgsserver.cpp
@@ -156,6 +156,26 @@ QString QgsServer::configPath( const QString &defaultConfigPath, const QString &
return cfPath;
}
+void QgsServer::initLocale()
+{
+ // System locale override
+ if ( ! sSettings.overrideSystemLocale().isEmpty() )
+ {
+ QLocale::setDefault( QLocale( sSettings.overrideSystemLocale() ) );
+ }
+ // Number group separator settings
+ QLocale currentLocale;
+ if ( sSettings.showGroupSeparator() )
+ {
+ currentLocale.setNumberOptions( currentLocale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
+ }
+ else
+ {
+ currentLocale.setNumberOptions( currentLocale.numberOptions() |= QLocale::NumberOption::OmitGroupSeparator );
+ }
+ QLocale::setDefault( currentLocale );
+}
+
bool QgsServer::init()
{
if ( sInitialized )
@@ -191,6 +211,9 @@ bool QgsServer::init()
QgsServerLogger::instance()->setLogStderr();
}
+ // Configure locale
+ initLocale();
+
// log settings currently used
sSettings.logSummary();
diff --git a/src/server/qgsserver.h b/src/server/qgsserver.h
index 77bb82c42135..791a53384a1d 100644
--- a/src/server/qgsserver.h
+++ b/src/server/qgsserver.h
@@ -144,5 +144,8 @@ class SERVER_EXPORT QgsServer
//! cache
QgsConfigCache *mConfigCache = nullptr;
+
+ //! Initialize locale
+ static void initLocale();
};
#endif // QGSSERVER_H
diff --git a/src/server/qgsserversettings.cpp b/src/server/qgsserversettings.cpp
index e5590d26f74d..b0be9feb6a4e 100644
--- a/src/server/qgsserversettings.cpp
+++ b/src/server/qgsserversettings.cpp
@@ -139,6 +139,29 @@ void QgsServerSettings::initSettings()
QVariant()
};
mSettings[ sCacheSize.envVar ] = sCacheSize;
+
+ // system locale override
+ const Setting sOverrideSystemLocale = { QgsServerSettingsEnv::QGIS_SERVER_OVERRIDE_SYSTEM_LOCALE,
+ QgsServerSettingsEnv::DEFAULT_VALUE,
+ QStringLiteral( "Override system locale" ),
+ QStringLiteral( "/locale/userLocale" ),
+ QVariant::String,
+ QVariant( "" ),
+ QVariant()
+ };
+ mSettings[ sOverrideSystemLocale.envVar ] = sOverrideSystemLocale;
+
+ // show group separator
+ const Setting sShowGroupSeparator = { QgsServerSettingsEnv::QGIS_SERVER_SHOW_GROUP_SEPARATOR,
+ QgsServerSettingsEnv::DEFAULT_VALUE,
+ QStringLiteral( "Show group (thousands) separator" ),
+ QStringLiteral( "/locale/showGroupSeparator" ),
+ QVariant::String,
+ QVariant( false ),
+ QVariant()
+ };
+ mSettings[ sShowGroupSeparator.envVar ] = sShowGroupSeparator;
+
}
void QgsServerSettings::load()
@@ -319,3 +342,14 @@ QString QgsServerSettings::cacheDirectory() const
{
return value( QgsServerSettingsEnv::QGIS_SERVER_CACHE_DIRECTORY ).toString();
}
+
+QString QgsServerSettings::overrideSystemLocale() const
+{
+ return value( QgsServerSettingsEnv::QGIS_SERVER_OVERRIDE_SYSTEM_LOCALE ).toString();
+}
+
+bool QgsServerSettings::showGroupSeparator() const
+{
+ return value( QgsServerSettingsEnv::QGIS_SERVER_SHOW_GROUP_SEPARATOR ).toBool();
+}
+
diff --git a/src/server/qgsserversettings.h b/src/server/qgsserversettings.h
index 6008938c31a6..fd9cfd9e2f77 100644
--- a/src/server/qgsserversettings.h
+++ b/src/server/qgsserversettings.h
@@ -60,7 +60,9 @@ class SERVER_EXPORT QgsServerSettingsEnv : public QObject
QGIS_PROJECT_FILE,
MAX_CACHE_LAYERS,
QGIS_SERVER_CACHE_DIRECTORY,
- QGIS_SERVER_CACHE_SIZE
+ QGIS_SERVER_CACHE_SIZE,
+ QGIS_SERVER_SHOW_GROUP_SEPARATOR, //! Show group (thousands) separator when formatting numeric values, defaults to FALSE (since QGIS 3.8)
+ QGIS_SERVER_OVERRIDE_SYSTEM_LOCALE, //! Override system locale (since QGIS 3.8)
};
Q_ENUM( EnvVar )
};
@@ -88,41 +90,41 @@ class SERVER_EXPORT QgsServerSettings
/**
* Constructor.
- */
+ */
QgsServerSettings();
/**
* Load settings according to current environment variables.
- */
+ */
void load();
/**
* Load setting for a specific environment variable name.
- * \returns true if loading is successful, false in case of an invalid name.
- */
+ * \returns TRUE if loading is successful, FALSE in case of an invalid name.
+ */
bool load( const QString &envVarName );
/**
* Log a summary of settings currently loaded.
- */
+ */
void logSummary() const;
/**
* Returns the ini file loaded by QSetting.
- * \returns the path of the ini file or an empty string if none is loaded.
- */
+ * \returns the path of the ini file or an empty string if none is loaded.
+ */
QString iniFile() const;
/**
* Returns parallel rendering setting.
- * \returns true if parallel rendering is activated, false otherwise.
- */
+ * \returns TRUE if parallel rendering is activated, FALSE otherwise.
+ */
bool parallelRendering() const;
/**
* Returns the maximum number of threads to use.
- * \returns the number of threads.
- */
+ * \returns the number of threads.
+ */
int maxThreads() const;
/**
@@ -133,20 +135,20 @@ class SERVER_EXPORT QgsServerSettings
/**
* Returns the log level.
- * \returns the log level.
- */
+ * \returns the log level.
+ */
Qgis::MessageLevel logLevel() const;
/**
* Returns the QGS project file to use.
- * \returns the path of the QGS project or an empty string if none is defined.
- */
+ * \returns the path of the QGS project or an empty string if none is defined.
+ */
QString projectFile() const;
/**
* Returns the log file.
- * \returns the path of the log file or an empty string if none is defined.
- */
+ * \returns the path of the log file or an empty string if none is defined.
+ */
QString logFile() const;
/**
@@ -158,16 +160,30 @@ class SERVER_EXPORT QgsServerSettings
/**
* Returns the cache size.
- * \returns the cache size.
- */
+ * \returns the cache size.
+ */
qint64 cacheSize() const;
/**
* Returns the cache directory.
- * \returns the directory.
- */
+ * \returns the directory.
+ */
QString cacheDirectory() const;
+ /**
+ * Overrides system locale
+ * \returns the optional override for system locale.
+ * \since QGIS 3.8
+ */
+ QString overrideSystemLocale() const;
+
+ /**
+ * Show group (thousand) separator
+ * \returns if group separator must be shown, default to FALSE.
+ * \since QGIS 3.8
+ */
+ bool showGroupSeparator() const;
+
private:
void initSettings();
QVariant value( QgsServerSettingsEnv::EnvVar envVar ) const;
diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt
index b5bede31d1bb..f00bb8a10863 100644
--- a/tests/src/python/CMakeLists.txt
+++ b/tests/src/python/CMakeLists.txt
@@ -295,6 +295,7 @@ IF (WITH_SERVER)
ADD_PYTHON_TEST(PyQgsServerWMTS test_qgsserver_wmts.py)
ADD_PYTHON_TEST(PyQgsServerWFS test_qgsserver_wfs.py)
ADD_PYTHON_TEST(PyQgsServerWFST test_qgsserver_wfst.py)
+ ADD_PYTHON_TEST(PyQgsServerLocaleOverride test_qgsserver_locale_override.py)
ADD_PYTHON_TEST(PyQgsOfflineEditingWFS test_offline_editing_wfs.py)
ADD_PYTHON_TEST(PyQgsAuthManagerPasswordOWSTest test_authmanager_password_ows.py)
ADD_PYTHON_TEST(PyQgsAuthManagerPKIOWSTest test_authmanager_pki_ows.py)
diff --git a/tests/src/python/test_qgsserver_locale_override.py b/tests/src/python/test_qgsserver_locale_override.py
new file mode 100644
index 000000000000..6d186459e232
--- /dev/null
+++ b/tests/src/python/test_qgsserver_locale_override.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+"""QGIS Unit tests for QgsServer Locale Override Options.
+
+From build dir, run: ctest -R PyQgsServerLocaleOverride -V
+
+.. note:: This test needs env vars to be set before the server is
+ configured for the first time, for this
+ reason it cannot run as a test case of another server
+ test.
+
+.. note:: This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+"""
+__author__ = 'Alessandro Pasotti'
+__date__ = '01/04/2019'
+__copyright__ = 'Copyright 2019, The QGIS Project'
+# This will get replaced with a git SHA1 when you do a git archive
+__revision__ = '$Format:%H$'
+
+import os
+
+# Needed on Qt 5 so that the serialization of XML is consistent among all
+# executions
+os.environ['QT_HASH_SEED'] = '1'
+
+from utilities import (
+ unitTestDataPath,
+)
+from qgis.testing import unittest
+
+from test_qgsserver_wms import TestQgsServerWMSTestBase
+from qgis.core import QgsProject, QgsFontUtils
+from qgis.server import QgsServer
+
+
+class TestQgsServerWMSLocaleOverride(TestQgsServerWMSTestBase):
+ """QGIS Server WMS Tests for GetFeatureInfo request"""
+
+ # Set to True to re-generate reference files for this class
+ regenerate_reference = False
+
+ def setUp(self):
+ """Create the server instance"""
+ self.fontFamily = QgsFontUtils.standardTestFontFamily()
+ QgsFontUtils.loadStandardTestFonts(['All'])
+
+ self.testdata_path = unitTestDataPath('qgis_server') + '/'
+
+ d = unitTestDataPath('qgis_server') + '/'
+ self.projectPath = os.path.join(d, "project.qgs")
+
+ # Clean env just to be sure
+ env_vars = ['QUERY_STRING', 'QGIS_PROJECT_FILE']
+ for ev in env_vars:
+ try:
+ del os.environ[ev]
+ except KeyError:
+ pass
+
+ os.environ['QGIS_SERVER_OVERRIDE_SYSTEM_LOCALE'] = 'EN_us'
+ os.environ['QGIS_SERVER_SHOW_GROUP_SEPARATOR'] = '0'
+
+ self.server = QgsServer()
+
+ def testGetFeatureInfoThousandSeparator(self):
+
+ self.wms_request_compare('GetFeatureInfo',
+ '&layers=testlayer_thousands&styles=&' +
+ 'info_format=text%2Fxml&transparent=true&' +
+ 'width=600&height=400&srs=EPSG%3A3857&bbox=913190.6389747962%2C' +
+ '5606005.488876367%2C913235.426296057%2C5606035.347090538&' +
+ 'query_layers=testlayer_thousands&X=190&Y=320',
+ 'wms_getfeatureinfo-thousands-text-xml',
+ project='test_project_gfi_thousands.qgs',)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/testdata/qgis_server/test_project_gfi_thousands.qgs b/tests/testdata/qgis_server/test_project_gfi_thousands.qgs
new file mode 100644
index 000000000000..9512d78666b2
--- /dev/null
+++ b/tests/testdata/qgis_server/test_project_gfi_thousands.qgs
@@ -0,0 +1,643 @@
+
+
+
+ QGIS Test Project
+
+
+
+
+
+ +proj=longlat +datum=WGS84 +no_defs
+ 3452
+ 4326
+ EPSG:4326
+ WGS 84
+ longlat
+ WGS84
+ true
+
+
+
+
+
+
+
+
+ - testlayer_thousands_50dfd72a_7b73_4987_8bad_4de2936b2f54
+
+
+
+
+
+
+
+
+
+ degrees
+
+ 17.92067782886099891
+ 30.16118840528694989
+ 18.04813119270758293
+ 30.27189237230483343
+
+ 0
+
+
+ +proj=longlat +datum=WGS84 +no_defs
+ 3452
+ 4326
+ EPSG:4326
+ WGS 84
+ longlat
+ WGS84
+ true
+
+
+ 0
+
+
+
+
+
+
+
+ 8.20345930703634352
+ 44.90139483904469131
+ 8.20354699399348775
+ 44.90148252600183554
+
+ testlayer_thousands_50dfd72a_7b73_4987_8bad_4de2936b2f54
+ ./testlayer_thousands.shp|layername=testlayer_thousands
+
+
+
+ testlayer_thousands
+
+
+ +proj=longlat +datum=WGS84 +no_defs
+ 3452
+ 4326
+ EPSG:4326
+ WGS 84
+ longlat
+ WGS84
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ false
+
+
+
+
+ ogr
+
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "id"
+
+
+ 0
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+ 0
+ generatedlayout
+
+
+
+ "id"
+
+
+
+
+
+
+
+ 90
+ 4
+
+
+
+ Alessandro Pasotti
+ QGIS TestProject
+
+ QGIS dev team
+
+
+ 255
+ 255
+ 255
+ 0
+ 255
+ 255
+ 255
+
+
+
+ false
+
+
+
+
+
+ m2
+ meters
+
+
+
+
+
+
+
+ current_layer
+
+
+ 2
+
+ off
+
+ 0
+
+
+
+ 8
+
+ true
+
+ false
+ true
+
+ false
+
+ 1
+ 3452
+ +proj=longlat +datum=WGS84 +no_defs
+ EPSG:4326
+
+
+ 2
+ D
+ true
+
+
+
+
+ conditions unknown
+
+ false
+ Some UTF8 text èòù
+
+ 8.20315414376310059
+ 44.901236559338642
+ 8.204164917965862
+ 44.90159838674664172
+
+
+ 0
+ true
+ true
+ 50
+ false
+ false
+ 0
+ false
+ 16
+ 30
+
+
+
+
+ testlayer20150528120452665
+
+
+ testlayer20150528120452665
+
+
+ testlayer20150528120452665
+
+
+
+ elpaso@itopen.it
+
+
+ testlayer_0b835118_a5d5_4255_b5dd_f42253c0a4a0
+
+
+
+ None
+
+ testlayer20150528120452665
+
+
+
+
+ true
+ 1
+
+ 255
+
+
+
+ WGS84
+
+
+
+
+
+
+
+
+
+
+ QGIS Test Project
+
+
+
+
+
+
+
+
+
+
+
+
+ 2000-01-01T00:00:00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/testdata/qgis_server/testlayer_thousands.dbf b/tests/testdata/qgis_server/testlayer_thousands.dbf
new file mode 100644
index 000000000000..80a8419db0db
Binary files /dev/null and b/tests/testdata/qgis_server/testlayer_thousands.dbf differ
diff --git a/tests/testdata/qgis_server/testlayer_thousands.shp b/tests/testdata/qgis_server/testlayer_thousands.shp
new file mode 100644
index 000000000000..3a2fd07db68c
Binary files /dev/null and b/tests/testdata/qgis_server/testlayer_thousands.shp differ
diff --git a/tests/testdata/qgis_server/testlayer_thousands.shx b/tests/testdata/qgis_server/testlayer_thousands.shx
new file mode 100644
index 000000000000..4fcbb5877685
Binary files /dev/null and b/tests/testdata/qgis_server/testlayer_thousands.shx differ
diff --git a/tests/testdata/qgis_server/wms_getfeatureinfo-thousands-text-xml.txt b/tests/testdata/qgis_server/wms_getfeatureinfo-thousands-text-xml.txt
new file mode 100644
index 000000000000..321ae29337f9
--- /dev/null
+++ b/tests/testdata/qgis_server/wms_getfeatureinfo-thousands-text-xml.txt
@@ -0,0 +1,14 @@
+Content-Length: 366
+Content-Type: text/xml; charset=utf-8
+
+
+
+
+
+
+
+
+
+
+
+