diff --git a/wagtail_localize/segments/extract.py b/wagtail_localize/segments/extract.py index a36ffceef..a6aac3365 100644 --- a/wagtail_localize/segments/extract.py +++ b/wagtail_localize/segments/extract.py @@ -18,6 +18,13 @@ from ..strings import extract_strings +def quote_path_component(text): + """ + Puts quotes around the path compoenents, and escapes any special characters. + """ + return "'" + text.replace("\\", "\\\\") .replace("'", "\\'") + "'" + + class StreamFieldSegmentExtractor: def __init__(self, field, include_overridables=False): self.field = field @@ -55,7 +62,7 @@ def handle_block(self, block_type, block_value): StringSegmentValue("", string, attrs=attrs) for string, attrs in strings ] + [ - OverridableSegmentValue(href, href) + OverridableSegmentValue(quote_path_component(href), href) for href in hrefs ] return ret @@ -153,7 +160,7 @@ def extract_segments(instance): StringSegmentValue("", string, attrs=attrs) for string, attrs in strings ] + [ - OverridableSegmentValue(href, href) + OverridableSegmentValue(quote_path_component(href), href) for href in hrefs ] diff --git a/wagtail_localize/segments/ingest.py b/wagtail_localize/segments/ingest.py index 75aaa3f96..ff22277b1 100644 --- a/wagtail_localize/segments/ingest.py +++ b/wagtail_localize/segments/ingest.py @@ -12,13 +12,23 @@ from .types import OverridableSegmentValue, StringSegmentValue +def unquote_path_component(text): + """ + Removes quotes around a quoted path component, and unescapes any special characters. + """ + if text[0] != "'" or text[-1] != "'": + raise ValueError("value must be a quoted string") + + return text[1:-1].replace("\\'", "'").replace("\\\\", "\\") + + def organise_template_segments(segments): # The first segment is always the template, followed by the texts in order of their position segments.sort(key=lambda segment: segment.order) template = segments[0] xrefs = { - segment.path: segment.data + unquote_path_component(segment.path): segment.data for segment in segments if isinstance(segment, OverridableSegmentValue) and segment.data } diff --git a/wagtail_localize/segments/tests/test_segment_extraction.py b/wagtail_localize/segments/tests/test_segment_extraction.py index 6f8e28cdf..cfc4968b9 100644 --- a/wagtail_localize/segments/tests/test_segment_extraction.py +++ b/wagtail_localize/segments/tests/test_segment_extraction.py @@ -52,7 +52,7 @@ def make_test_page(**kwargs): } ), OverridableSegmentValue( - "http://example.com", + "'http://example.com'", "http://example.com" ) ] diff --git a/wagtail_localize/tests/test_edit_translation.py b/wagtail_localize/tests/test_edit_translation.py index 2204bfa3f..102a093b5 100644 --- a/wagtail_localize/tests/test_edit_translation.py +++ b/wagtail_localize/tests/test_edit_translation.py @@ -185,7 +185,7 @@ def test_edit_page_translation(self): self.assertEqual( [(segment['contentPath'], segment['value']) for segment in props['segments'] if segment['type'] == 'synchronised_value'], [ - ('test_richtextfield.http://example.com', 'http://example.com'), + ("test_richtextfield.'http://example.com'", 'http://example.com'), ('test_synchronized_emailfield', 'email@example.com'), ] ) @@ -200,7 +200,7 @@ def test_edit_page_translation(self): # Check synchronised value synchronised_value_segment = props['segments'][9] self.assertEqual(synchronised_value_segment['type'], 'synchronised_value') - self.assertEqual(synchronised_value_segment['contentPath'], 'test_richtextfield.http://example.com') + self.assertEqual(synchronised_value_segment['contentPath'], "test_richtextfield.'http://example.com'") self.assertEqual(synchronised_value_segment['location'], {'blockId': None, 'field': 'Test richtextfield', 'fieldHelpText': '', 'order': 6, 'subField': None, 'tab': 'content', 'widget': {'type': 'text'}}) self.assertEqual(synchronised_value_segment['value'], 'http://example.com') @@ -360,7 +360,7 @@ def test_override_types(self): self.assertEqual( [(segment['contentPath'], segment['location']['widget'], segment['value']) for segment in props['segments'] if segment['type'] == 'synchronised_value'], [ - ('test_richtextfield.http://example.com', {'type': 'text'}, 'http://example.com'), + ("test_richtextfield.'http://example.com'", {'type': 'text'}, 'http://example.com'), (f'test_streamfield.{url_block_id}', {'type': 'text'}, "https://wagtail.io/"), (f'test_streamfield.{page_block_id}', {'type': 'page_chooser', 'allowed_page_types': ['wagtailcore.page']}, self.page.id), (f'test_streamfield.{image_block_id}', {'type': 'image_chooser'}, self.page.test_synchronized_image.id),