mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-15 11:35:41 +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