From 2943dc60832c04e60b358359be63d006588c0e5d Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 20 Apr 2021 13:37:19 +0200 Subject: [PATCH 1/3] initial implementation as in #1485 --- .gitignore | 1 + .../management/commands/prerender.py | 63 +++++++++++++++++++ InvenTree/InvenTree/settings.py | 11 ++++ .../part/templatetags/inventree_extras.py | 29 +++++++++ InvenTree/templates/base.html | 29 ++++----- tasks.py | 1 + 6 files changed, 120 insertions(+), 14 deletions(-) create mode 100644 InvenTree/InvenTree/management/commands/prerender.py diff --git a/.gitignore b/.gitignore index b648ad00b98..eaa9e5574dd 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ docs/_build # Local static and media file storage (only when running in development mode) inventree_media inventree_static +static_i18n # Local config file config.yaml diff --git a/InvenTree/InvenTree/management/commands/prerender.py b/InvenTree/InvenTree/management/commands/prerender.py new file mode 100644 index 00000000000..b80f35d4213 --- /dev/null +++ b/InvenTree/InvenTree/management/commands/prerender.py @@ -0,0 +1,63 @@ +""" +Custom management command to prerender files +""" + +import django +from django.core.management.base import BaseCommand +from django.conf import settings +from django.template.loader import render_to_string +from django.utils.module_loading import import_string +from django.http.request import HttpRequest +from django.utils.translation import override as lang_over + +import time +import os + + +def render_file(file_name, source, target, locales, ctx): + """ renders a file into all provided locales """ + for locale in locales: + target_file = os.path.join(target, locale + '.' + file_name) + with open(target_file, 'w') as localised_file: + with lang_over(locale): + renderd = render_to_string(os.path.join(source, file_name), ctx) + localised_file.write(renderd) + + +class Command(BaseCommand): + """ + django command to prerender files + """ + + def handle(self, *args, **kwargs): + # static directorys + LC_DIR = settings.LOCALE_PATHS[0] + SOURCE_DIR = settings.STATICFILES_I18_SRC + TARTGET_DIR = settings.STATICFILES_I18_TRG + + # ensure static directory exists + if not os.path.exists(TARTGET_DIR): + os.mkdir(TARTGET_DIR) + + # collect locales + locales = {} + for locale in os.listdir(LC_DIR): + path = os.path.join(LC_DIR, locale) + if os.path.exists(path) and os.path.isdir(path): + locales[locale] = locale + + # render! + request = HttpRequest() + ctx = {} + processors = tuple(import_string(path) for path in settings.STATFILES_I18_PROCESORS) + for processor in processors: + ctx.update(processor(request)) + + for file in os.listdir(SOURCE_DIR, ): + path = os.path.join(SOURCE_DIR, file) + if os.path.exists(path) and os.path.isfile(path): + print(f"render {file}") + render_file(file, SOURCE_DIR, TARTGET_DIR, locales, ctx) + else: + raise NotImplementedError('Using multi-level directories is not implemented at this point') # TODO multilevel dir if needed + print(f"rendered all files in {SOURCE_DIR}") diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index b1256dcceeb..c4cc8e961ad 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -190,6 +190,17 @@ def get_setting(environment_var, backup_val, default_value=None): os.path.join(BASE_DIR, 'InvenTree', 'static'), ] +# Translated Template settings +STATICFILES_I18_PREFIX = 'i18n' +STATICFILES_I18_SRC = os.path.join(BASE_DIR, 'templates', 'js') +STATICFILES_I18_TRG = STATICFILES_DIRS[0] + '_' + STATICFILES_I18_PREFIX +STATICFILES_DIRS.append(STATICFILES_I18_TRG) +STATICFILES_I18_TRG = os.path.join(STATICFILES_I18_TRG, STATICFILES_I18_PREFIX) + +STATFILES_I18_PROCESORS = [ + 'InvenTree.context.status_codes', +] + # Color Themes Directory STATIC_COLOR_THEMES_DIR = os.path.join(STATIC_ROOT, 'css', 'color-themes') diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index cf56e01fbf0..a92d95c7663 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -6,6 +6,7 @@ from django import template from django.urls import reverse from django.utils.safestring import mark_safe +from django.templatetags.static import StaticNode from InvenTree import version, settings import InvenTree.helpers @@ -180,3 +181,31 @@ def object_link(url_name, pk, ref): ref_url = reverse(url_name, kwargs={'pk': pk}) return mark_safe('{}'.format(ref_url, ref)) + + +class I18nStaticNode(StaticNode): + """ + custom StaticNode + replaces a variable named *lng* in the path with the current language + """ + def render(self, context): + self.path.var = self.path.var.format(lng=context.request.LANGUAGE_CODE) + ret = super().render(context) + return ret + + +@register.tag('i18n_static') +def do_i18n_static(parser, token): + """ + Overrides normal static, adds language - lookup for prerenderd files #1485 + + usage (like static): + {% i18n_static path [as varname] %} + """ + bits = token.split_contents() + loc_name = settings.STATICFILES_I18_PREFIX + + # change path to called ressource + bits[1] = f"'{loc_name}/{{lng}}.{bits[1][1:-1]}'" + token.contents = ' '.join(bits) + return I18nStaticNode.handle_token(parser, token) diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html index 8ccf691ef5c..970d9f1016d 100644 --- a/InvenTree/templates/base.html +++ b/InvenTree/templates/base.html @@ -143,20 +143,21 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/tasks.py b/tasks.py index 895f3183cea..d775b943a0a 100644 --- a/tasks.py +++ b/tasks.py @@ -154,6 +154,7 @@ def static(c): as per Django requirements. """ + manage(c, "prerender") manage(c, "collectstatic --no-input") From 4d439db322ccd93f9107301773649cb1ffb0d20d Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 20 Apr 2021 13:48:05 +0200 Subject: [PATCH 2/3] fixing styling issues --- InvenTree/InvenTree/management/commands/prerender.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/InvenTree/InvenTree/management/commands/prerender.py b/InvenTree/InvenTree/management/commands/prerender.py index b80f35d4213..028536becbe 100644 --- a/InvenTree/InvenTree/management/commands/prerender.py +++ b/InvenTree/InvenTree/management/commands/prerender.py @@ -2,7 +2,6 @@ Custom management command to prerender files """ -import django from django.core.management.base import BaseCommand from django.conf import settings from django.template.loader import render_to_string @@ -10,7 +9,6 @@ from django.http.request import HttpRequest from django.utils.translation import override as lang_over -import time import os From 99dc02e2cbfe49a7595c042b82d32f882959f6bd Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 20 Apr 2021 14:39:28 +0200 Subject: [PATCH 3/3] cleaning up names / comments --- InvenTree/InvenTree/management/commands/prerender.py | 12 ++++++------ InvenTree/InvenTree/settings.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/InvenTree/InvenTree/management/commands/prerender.py b/InvenTree/InvenTree/management/commands/prerender.py index 028536becbe..28f4b21f151 100644 --- a/InvenTree/InvenTree/management/commands/prerender.py +++ b/InvenTree/InvenTree/management/commands/prerender.py @@ -28,14 +28,14 @@ class Command(BaseCommand): """ def handle(self, *args, **kwargs): - # static directorys + # static directories LC_DIR = settings.LOCALE_PATHS[0] SOURCE_DIR = settings.STATICFILES_I18_SRC - TARTGET_DIR = settings.STATICFILES_I18_TRG + TARGET_DIR = settings.STATICFILES_I18_TRG # ensure static directory exists - if not os.path.exists(TARTGET_DIR): - os.mkdir(TARTGET_DIR) + if not os.path.exists(TARGET_DIR): + os.makedirs(TARGET_DIR, exist_ok=True) # collect locales locales = {} @@ -47,7 +47,7 @@ def handle(self, *args, **kwargs): # render! request = HttpRequest() ctx = {} - processors = tuple(import_string(path) for path in settings.STATFILES_I18_PROCESORS) + processors = tuple(import_string(path) for path in settings.STATFILES_I18_PROCESSORS) for processor in processors: ctx.update(processor(request)) @@ -55,7 +55,7 @@ def handle(self, *args, **kwargs): path = os.path.join(SOURCE_DIR, file) if os.path.exists(path) and os.path.isfile(path): print(f"render {file}") - render_file(file, SOURCE_DIR, TARTGET_DIR, locales, ctx) + render_file(file, SOURCE_DIR, TARGET_DIR, locales, ctx) else: raise NotImplementedError('Using multi-level directories is not implemented at this point') # TODO multilevel dir if needed print(f"rendered all files in {SOURCE_DIR}") diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index c4cc8e961ad..53dcb470377 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -197,7 +197,7 @@ def get_setting(environment_var, backup_val, default_value=None): STATICFILES_DIRS.append(STATICFILES_I18_TRG) STATICFILES_I18_TRG = os.path.join(STATICFILES_I18_TRG, STATICFILES_I18_PREFIX) -STATFILES_I18_PROCESORS = [ +STATFILES_I18_PROCESSORS = [ 'InvenTree.context.status_codes', ]