mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-15 19:45:46 +00:00
Adds a custom translation node class to strip dirty characters from translated strings
This commit is contained in:
102
InvenTree/part/templatetags/js_i18n.py
Normal file
102
InvenTree/part/templatetags/js_i18n.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
"""This module provides custom translation tags specifically for use with javascript code.
|
||||||
|
|
||||||
|
Translated strings are escaped, such that they can be used as string literals in a javascript file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django import template
|
||||||
|
from django.template import TemplateSyntaxError
|
||||||
|
from django.templatetags.i18n import TranslateNode
|
||||||
|
|
||||||
|
import bleach
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
class CustomTranslateNode(TranslateNode):
|
||||||
|
"""Custom translation node class, which sanitizes the translated strings for javascript use"""
|
||||||
|
|
||||||
|
def render(self, context):
|
||||||
|
"""Custom render function overrides / extends default behaviour"""
|
||||||
|
|
||||||
|
result = super().render(context)
|
||||||
|
|
||||||
|
result = bleach.clean(result)
|
||||||
|
|
||||||
|
# Remove any escape sequences
|
||||||
|
for seq in ['\a', '\b', '\f', '\n', '\r', '\t', '\v']:
|
||||||
|
result = result.replace(seq, '')
|
||||||
|
|
||||||
|
# Remove other disallowed characters
|
||||||
|
for c in ['\\', '`', ';', '|', '&']:
|
||||||
|
result = result.replace(c, '')
|
||||||
|
|
||||||
|
# Escape any quotes contained in the string
|
||||||
|
result = result.replace("'", r"\'")
|
||||||
|
result = result.replace('"', r'\"')
|
||||||
|
|
||||||
|
# Return the 'clean' resulting string
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@register.tag("translate")
|
||||||
|
@register.tag("trans")
|
||||||
|
def do_translate(parser, token):
|
||||||
|
"""Custom translation function, lifted from https://github.com/django/django/blob/main/django/templatetags/i18n.py
|
||||||
|
|
||||||
|
The only difference is that we pass this to our custom rendering node class
|
||||||
|
"""
|
||||||
|
|
||||||
|
bits = token.split_contents()
|
||||||
|
if len(bits) < 2:
|
||||||
|
raise TemplateSyntaxError("'%s' takes at least one argument" % bits[0])
|
||||||
|
message_string = parser.compile_filter(bits[1])
|
||||||
|
remaining = bits[2:]
|
||||||
|
|
||||||
|
noop = False
|
||||||
|
asvar = None
|
||||||
|
message_context = None
|
||||||
|
seen = set()
|
||||||
|
invalid_context = {"as", "noop"}
|
||||||
|
|
||||||
|
while remaining:
|
||||||
|
option = remaining.pop(0)
|
||||||
|
if option in seen:
|
||||||
|
raise TemplateSyntaxError(
|
||||||
|
"The '%s' option was specified more than once." % option,
|
||||||
|
)
|
||||||
|
elif option == "noop":
|
||||||
|
noop = True
|
||||||
|
elif option == "context":
|
||||||
|
try:
|
||||||
|
value = remaining.pop(0)
|
||||||
|
except IndexError:
|
||||||
|
raise TemplateSyntaxError(
|
||||||
|
"No argument provided to the '%s' tag for the context option."
|
||||||
|
% bits[0]
|
||||||
|
)
|
||||||
|
if value in invalid_context:
|
||||||
|
raise TemplateSyntaxError(
|
||||||
|
"Invalid argument '%s' provided to the '%s' tag for the context "
|
||||||
|
"option" % (value, bits[0]),
|
||||||
|
)
|
||||||
|
message_context = parser.compile_filter(value)
|
||||||
|
elif option == "as":
|
||||||
|
try:
|
||||||
|
value = remaining.pop(0)
|
||||||
|
except IndexError:
|
||||||
|
raise TemplateSyntaxError(
|
||||||
|
"No argument provided to the '%s' tag for the as option." % bits[0]
|
||||||
|
)
|
||||||
|
asvar = value
|
||||||
|
else:
|
||||||
|
raise TemplateSyntaxError(
|
||||||
|
"Unknown argument for '%s' tag: '%s'. The only options "
|
||||||
|
"available are 'noop', 'context' \"xxx\", and 'as VAR'."
|
||||||
|
% (
|
||||||
|
bits[0],
|
||||||
|
option,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
seen.add(option)
|
||||||
|
|
||||||
|
return CustomTranslateNode(message_string, noop, asvar, message_context)
|
Reference in New Issue
Block a user