Skip to content

Commit 6d6850e

Browse files
committed
Cleanup loading of translations.
The new code clearly distinguishes between loading default translations from the "base" theme and loading (additional) translations from the (inherited) themes. Also the former method put the directories onto sys.path and imported the translation files as modules. This not only keeps the whole module in memory (which might be neglectable nowadays) but also requires extra code to reload the module for each theme. The new method loads the file and executes it using exec(). As a side-effect, this also fixed the bug that translations provided by the "base" theme got lost if another theme provided additional message strings.
1 parent b1b9bb0 commit 6d6850e

File tree

1 file changed

+39
-31
lines changed

1 file changed

+39
-31
lines changed

nikola/utils.py

+39-31
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from collections import defaultdict, OrderedDict
4646
from html import unescape as html_unescape
4747
from importlib import reload as _reload
48+
from pathlib import Path
4849
from unicodedata import normalize as unicodenormalize
4950
from urllib.parse import quote as urlquote
5051
from urllib.parse import unquote as urlunquote
@@ -710,41 +711,48 @@ def load_messages(themes, translations, default_lang, themes_dirs):
710711
and "younger" themes have priority.
711712
"""
712713
messages = Functionary(dict, default_lang)
713-
oldpath = list(sys.path)
714-
found = {lang: False for lang in translations.keys()}
714+
found = {lang: False for lang in translations}
715+
completion_status = found.copy()
715716
last_exception = None
716-
completion_status = {lang: False for lang in translations.keys()}
717+
718+
def load_msgs(lang, folder):
719+
globals = {}
720+
msg_file = folder / f'messages_{lang}.py'
721+
try:
722+
pysrc = msg_file.read_bytes()
723+
exec(pysrc, globals)
724+
except Exception as ex:
725+
last_exception = ex # noqa: F841
726+
return globals.get('MESSAGES', {})
727+
728+
# load default translations provided by "base" theme
729+
default_folder = Path(get_theme_path_real('base', themes_dirs)) / 'messages'
730+
english = load_msgs('en', default_folder)
731+
for lang in translations:
732+
messages[lang].update(english)
733+
messages[lang].update(load_msgs(lang, default_folder))
734+
735+
# load translations for each theme
717736
for theme_name in themes[::-1]:
718-
msg_folder = os.path.join(get_theme_path(theme_name), 'messages')
719-
default_folder = os.path.join(get_theme_path_real('base', themes_dirs), 'messages')
720-
sys.path.insert(0, default_folder)
721-
sys.path.insert(0, msg_folder)
722-
723-
english = __import__('messages_en')
724-
# If we don't do the reload, the module is cached
725-
_reload(english)
726-
for lang in translations.keys():
727-
try:
728-
translation = __import__('messages_' + lang)
729-
# If we don't do the reload, the module is cached
730-
_reload(translation)
731-
found[lang] = True
732-
if sorted(translation.MESSAGES.keys()) != sorted(english.MESSAGES.keys()):
733-
completion_status[lang] = completion_status[lang] or False
734-
else:
735-
completion_status[lang] = True
736-
737-
messages[lang].update(english.MESSAGES)
738-
for k, v in translation.MESSAGES.items():
739-
if v:
740-
messages[lang][k] = v
741-
del translation
742-
except ImportError as orig:
743-
last_exception = orig
744-
del english
745-
sys.path = oldpath
737+
msg_folder = Path(get_theme_path(theme_name)) / 'messages'
738+
# load English default from this theme
739+
english = load_msgs('en', msg_folder)
740+
messages[lang].update(english) # FIXME: This will overwrite translated strings
741+
for lang in translations:
742+
translation = load_msgs(lang, msg_folder)
743+
if not translation:
744+
continue
745+
found[lang] = True
746+
for k, v in translation.items():
747+
if v:
748+
messages[lang][k] = v
749+
if set(translation) != set(english):
750+
completion_status[lang] = completion_status[lang] or False
751+
else:
752+
completion_status[lang] = True
746753

747754
if not all(found.values()):
755+
print(lang, last_exception)
748756
raise LanguageNotFoundError(lang, last_exception)
749757
for lang, status in completion_status.items():
750758
if not status and lang not in INCOMPLETE_LANGUAGES_WARNED:

0 commit comments

Comments
 (0)