Skip to content

Commit 56a7cd1

Browse files
committed
Read theme translations from project translation auxiliary files
1 parent 060fee7 commit 56a7cd1

File tree

4 files changed

+58
-14
lines changed

4 files changed

+58
-14
lines changed

src/config_generator/config_generator.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,21 @@ def __init__(self, config, logger, config_file_dir, use_cached_project_metadata,
248248
viewer_config_json = map_viewer_config.get('generator_config', {}).get('qwc2_config', {}).get('qwc2_config_file')
249249
try:
250250
with open(viewer_config_json, 'r') as fh:
251+
viewer_config = json.load(fh)
251252
assets_dir = os.path.join(
252253
qwc_base_dir,
253-
json.load(fh).get('assetsPath', 'assets').lstrip('/')
254+
viewer_config.get('assetsPath', 'assets').lstrip('/')
255+
)
256+
translations_dir = os.path.join(
257+
qwc_base_dir,
258+
viewer_config.get('translationsPath', 'translations').lstrip('/')
254259
)
255260
except:
256-
self.logger.warning("Failed to read assets path from viewer config.json, using default")
261+
self.logger.warning("Failed to read assets/translations path from viewer config.json, using default")
257262
assets_dir = os.path.join(qwc_base_dir, 'assets')
263+
translations_dir = os.path.join(qwc_base_dir, 'translations')
258264
self.logger.info(f"Assets destination: {assets_dir}")
265+
self.logger.info(f"Translations destination: {translations_dir}")
259266

260267
# Search for QGS projects in scan dir and automatically generate theme items
261268
self.search_qgs_projects(generator_config, config["themesConfig"])
@@ -264,7 +271,7 @@ def __init__(self, config, logger, config_file_dir, use_cached_project_metadata,
264271
capabilities_cache_dir = os.path.join(self.config_path, "__capabilities_cache")
265272
self.theme_reader = ThemeReader(
266273
generator_config, self.logger, self.config_models, config["themesConfig"],
267-
assets_dir, use_cached_project_metadata, capabilities_cache_dir
274+
assets_dir, translations_dir, use_cached_project_metadata, capabilities_cache_dir
268275
)
269276

270277
# load schema-versions.json

src/config_generator/map_viewer_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ def theme_item(self, cfg_item, themes_config, assets_dir, autogenExternalLayers,
445445
item['keywords'] = cap.get('keywords', '')
446446
item['onlineResource'] = cap.get('onlineResource', '')
447447
item['contact'] = cap.get('contact', {})
448+
item['translations'] = project_metadata['translations']
448449

449450

450451
projectCrs = project_metadata['project_crs']

src/config_generator/qgs_reader.py

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import html
22
import io
3+
import json
34
import math
45
import os
56
import re
@@ -24,24 +25,32 @@ def element_attr(element, attr, default=None):
2425
class QGSReader:
2526
""" Read QGIS projects and extract data for QWC config """
2627

27-
def __init__(self, config, logger, assets_dir, use_cached_project_metadata, global_print_layouts):
28+
def __init__(self, config, logger, assets_dir, translations_dir, use_cached_project_metadata, global_print_layouts):
2829
"""Constructor
2930
3031
:param obj config: Config generator config
3132
:param Logger logger: Application logger
3233
:param string assets_dir: Assets directory
34+
:param str translations_dir: Viewer translations directory
3335
:param bool use_cached_project_metadata: Whether to use cached project metadata
3436
:param list global_print_layouts: Global print layouts
3537
"""
3638
self.config = config
3739
self.logger = logger
3840
self.assets_dir = assets_dir
41+
self.translations_dir = translations_dir
3942
self.use_cached_project_metadata = use_cached_project_metadata
4043
self.global_print_layouts = global_print_layouts
4144

4245
self.qgs_resources_path = config.get('qgis_projects_base_dir', '/tmp/')
4346
self.qgs_ext = config.get('qgis_project_extension', '.qgs')
4447
self.nested_nrels = config.get('generate_nested_nrel_forms', False)
48+
try:
49+
with open(os.path.join(self.translations_dir, 'tsconfig.json')) as fh:
50+
self.viewer_languages = json.load(fh)['languages']
51+
except:
52+
self.logger.warning("Failed to detect viewer languages from tsconfig.json")
53+
self.viewer_languages = ["en-US"]
4554

4655
self.db_engine = DatabaseEngine()
4756

@@ -57,8 +66,9 @@ def read(self, map_prefix, theme_item, edit_datasets):
5766
try:
5867
if map_prefix.startswith("pg/"):
5968
parts = map_prefix.split("/")
60-
qgs_path = self.qgs_resources_path
69+
qgs_dir = self.qgs_resources_path
6170
qgs_filename = 'postgresql:///?service=qgisprojects&schema=%s&project=%s' % (parts[1], parts[2])
71+
projectname = parts[2]
6272

6373
qgis_projects_db = self.db_engine.db_engine("postgresql:///?service=qgisprojects")
6474

@@ -84,6 +94,8 @@ def read(self, map_prefix, theme_item, edit_datasets):
8494
else:
8595
qgs_filename = map_prefix + self.qgs_ext
8696
qgs_path = os.path.join(self.qgs_resources_path, qgs_filename)
97+
qgs_dir = os.path.dirname(qgs_path)
98+
projectname = os.path.basename(qgs_path).removesuffix(self.qgs_ext)
8799
if not os.path.exists(qgs_path):
88100
self.logger.error("Could not find QGS project '%s'" % qgs_filename)
89101
return None
@@ -131,9 +143,10 @@ def read(self, map_prefix, theme_item, edit_datasets):
131143

132144
return {
133145
"project_crs": self.__project_crs(root),
146+
"translations": self.__theme_translations(qgs_dir, projectname),
134147
"print_templates": self.__print_templates(root, shortname_map),
135148
"visibility_presets": self.__visibility_presets(root),
136-
"layer_metadata": self.__layer_metadata(root, shortname_map, map_prefix, edit_datasets, theme_item, qgs_path)
149+
"layer_metadata": self.__layer_metadata(root, shortname_map, map_prefix, edit_datasets, theme_item, qgs_dir),
137150
}
138151

139152

@@ -142,6 +155,28 @@ def __project_crs(self, root):
142155
authid = root.find('./projectCrs/spatialrefsys/authid')
143156
return authid.text if authid is not None else None
144157

158+
def __theme_translations(self, qgs_dir, projectname):
159+
""" Read theme portion of translations from <projectname>_<lang>.json. """
160+
all_translations = {}
161+
162+
for language in self.viewer_languages:
163+
translations = {}
164+
165+
json_file = os.path.join(qgs_dir, f"{projectname}_{language}.json")
166+
if not os.path.exists(json_file):
167+
json_file = os.path.join(qgs_dir, f"{projectname}_{language[0:2]}.json")
168+
if os.path.exists(json_file):
169+
self.logger.info('Reading project translations %s' % json_file)
170+
try:
171+
with open(json_file) as fh:
172+
translations = json.load(fh)['theme']
173+
except Exception as e:
174+
self.logger.info('Failed to read project translations %s: %s' % (json_file, str(e)))
175+
176+
if translations:
177+
all_translations[language] = translations
178+
179+
return all_translations
145180

146181
def __print_templates(self, root, shortname_map):
147182
""" Collect print templates from QGS and merge with global print layouts. """
@@ -248,7 +283,7 @@ def __visibility_presets(self, root):
248283
return result
249284

250285

251-
def __layer_metadata(self, root, shortname_map, map_prefix, edit_datasets, theme_item, qgs_path):
286+
def __layer_metadata(self, root, shortname_map, map_prefix, edit_datasets, theme_item, qgs_dir):
252287
""" Read additional layer metadata from QGS. """
253288
layers_metadata = {}
254289
# Collect metadata for layers
@@ -276,7 +311,7 @@ def __layer_metadata(self, root, shortname_map, map_prefix, edit_datasets, theme
276311

277312
# Edit metadata
278313
if editable:
279-
self.__layer_edit_metadata(root, layer_metadata, maplayer, layername, map_prefix, shortname_map, qgs_path, theme_item)
314+
self.__layer_edit_metadata(root, layer_metadata, maplayer, layername, map_prefix, shortname_map, qgs_dir, theme_item)
280315

281316
layers_metadata[layername] = layer_metadata
282317

@@ -291,7 +326,7 @@ def __layer_metadata(self, root, shortname_map, map_prefix, edit_datasets, theme
291326
return layers_metadata
292327

293328

294-
def __layer_edit_metadata(self, root, layer_metadata, maplayer, layername, map_prefix, shortnames, qgs_path, theme_item):
329+
def __layer_edit_metadata(self, root, layer_metadata, maplayer, layername, map_prefix, shortnames, qgs_dir, theme_item):
295330
""" Read layer metadata relevant for editing from QGS. """
296331

297332
provider = maplayer.find('provider').text
@@ -384,7 +419,7 @@ def __layer_edit_metadata(self, root, layer_metadata, maplayer, layername, map_p
384419

385420
# Generate form
386421
layer_metadata["edit_form"] = self.__generate_edit_form(
387-
root, qgs_path, map_prefix, shortnames, maplayer, layer_metadata, layername, theme_item
422+
root, qgs_dir, map_prefix, shortnames, maplayer, layer_metadata, layername, theme_item
388423
)
389424

390425

@@ -686,7 +721,7 @@ def __column_metadata(self, field_metadata, datasource, column, data_type_only =
686721
constraints['max'] = ranges[data_type]['max']
687722

688723

689-
def __generate_edit_form(self, project, qgs_path, map_prefix, shortnames, maplayer, layer_metadata, layername, theme_item):
724+
def __generate_edit_form(self, project, qgs_dir, map_prefix, shortnames, maplayer, layer_metadata, layername, theme_item):
690725
""" Copy / generate edit from from QGIS form settings. """
691726

692727
projectname = os.path.basename(map_prefix)
@@ -708,7 +743,7 @@ def __generate_edit_form(self, project, qgs_path, map_prefix, shortnames, maplay
708743
if editform is not None:
709744
formpath = editform.text
710745
if not os.path.isabs(formpath):
711-
formpath = os.path.join(os.path.dirname(qgs_path), formpath)
746+
formpath = os.path.join(qgs_dir, formpath)
712747
try:
713748
os.makedirs(outputdir, exist_ok=True)
714749
shutil.copy(formpath, outputfile)

src/config_generator/theme_reader.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ class ThemeReader():
1414
Reads project metadata for all theme items in the QWC2 theme configuration.
1515
"""
1616

17-
def __init__(self, config, logger, config_models, themes_config, assets_dir, use_cached_project_metadata, cache_dir):
17+
def __init__(self, config, logger, config_models, themes_config, assets_dir, translations_dir, use_cached_project_metadata, cache_dir):
1818
"""Constructor
1919
2020
:param obj config: ConfigGenerator config
2121
:param Logger logger: Logger
2222
:param ConfigModels config_models: Helper for ORM models
2323
:param dict themes_config: themes config
2424
:param str assets_dir: Viewer assets directory
25+
:param str translations_dir: Viewer translations directory
2526
:param bool use_cached_project_metadata: Whether to use cached project metadata if available
2627
:param str cache_dir: Project metadata cache directory
2728
"""
@@ -36,7 +37,7 @@ def __init__(self, config, logger, config_models, themes_config, assets_dir, use
3637
global_print_layouts = self.__search_global_print_layouts()
3738

3839
self.capabilities_reader = CapabilitiesReader(config, logger, use_cached_project_metadata, cache_dir)
39-
self.qgs_reader = QGSReader(config, logger, assets_dir, use_cached_project_metadata, global_print_layouts)
40+
self.qgs_reader = QGSReader(config, logger, assets_dir, translations_dir, use_cached_project_metadata, global_print_layouts)
4041

4142
self.default_qgis_server_url = config.get(
4243
'default_qgis_server_url', 'http://localhost:8001/ows/'

0 commit comments

Comments
 (0)