def handle_block(self, block_type, block_value): if hasattr(block_type, "get_translatable_segments"): return block_type.get_translatable_segments(block_value) elif isinstance(block_type, (blocks.CharBlock, blocks.TextBlock)): return [SegmentValue("", block_value)] elif isinstance(block_type, blocks.RichTextBlock): template, texts = extract_html_segments(block_value.source) return [TemplateValue("", "html", template, len(texts))] + [ SegmentValue.from_html("", text) for text in texts ] elif isinstance(block_type, (ImageChooserBlock, SnippetChooserBlock)): return self.handle_related_object_block(block_value) elif isinstance(block_type, blocks.StructBlock): return self.handle_struct_block(block_value) elif isinstance(block_type, blocks.ListBlock): return self.handle_list_block(block_value) elif isinstance(block_type, blocks.StreamBlock): return self.handle_stream_block(block_value) elif isinstance(block_type, blocks.ChoiceBlock): return [] else: raise Exception( "Unrecognised StreamField block type '{}'. Have you implemented get_translatable_segments on this class?".format( block_type.__class__.__name__ ) )
def test_listblock(self): block_id = uuid.uuid4() page = make_test_page_with_streamfield_block( str(block_id), "test_listblock", ["Test content", "Some more test content"]) translated_page = page.copy_for_translation(self.locale) ingest_segments( page, translated_page, self.src_locale, self.locale, [ SegmentValue(f"test_streamfield.{block_id}", "Tester le contenu", order=0), SegmentValue(f"test_streamfield.{block_id}", "Encore du contenu de test", order=1), ], ) translated_page.save() translated_page.refresh_from_db() self.assertEqual( translated_page.test_streamfield.stream_data, [{ "id": str(block_id), "type": "test_listblock", "value": ["Tester le contenu", "Encore du contenu de test"], }], )
def test_blockquoteblock(self): block_id = uuid.uuid4() page = make_test_page_with_streamfield_block(str(block_id), "test_blockquoteblock", "Test content") translated_page = page.copy_for_translation(self.locale) ingest_segments( page, translated_page, self.src_locale, self.locale, [ SegmentValue(f"test_streamfield.{block_id}", "Tester le contenu") ], ) translated_page.save() translated_page.refresh_from_db() self.assertEqual( translated_page.test_streamfield.stream_data, [{ "id": str(block_id), "type": "test_blockquoteblock", "value": "Tester le contenu", }], )
def test_childobjects(self): page = make_test_page() page.test_childobjects.add(TestChildObject(field="Test content")) page.save() child_translation_key = TestChildObject.objects.get().translation_key translated_page = page.copy_for_translation(self.locale) ingest_segments( page, translated_page, self.src_locale, self.locale, [ SegmentValue( f"test_childobjects.{child_translation_key}.field", "Tester le contenu", ) ], ) old_child_object = page.test_childobjects.get() new_child_object = translated_page.test_childobjects.get() self.assertNotEqual(old_child_object.id, new_child_object.id) self.assertEqual(old_child_object.locale, self.src_locale) self.assertEqual(new_child_object.locale, self.locale) self.assertEqual(old_child_object.translation_key, new_child_object.translation_key) self.assertEqual(new_child_object.field, "Tester le contenu")
def test_listblock(self): block_id = uuid.uuid4() page = make_test_page_with_streamfield_block( str(block_id), "test_listblock", ["Test content", "Some more test content"]) segments = extract_segments(page) self.assertEqual( segments, [ SegmentValue(f"test_streamfield.{block_id}", "Test content"), SegmentValue(f"test_streamfield.{block_id}", "Some more test content"), ], )
def ingest_messages(self, instance): if instance.translation_key in self.seen_objects: return self.seen_objects.add(instance.translation_key) segments = extract_segments(instance) # Ingest segments for dependencies first for segment in segments: if isinstance(segment, RelatedObjectValue): self.ingest_messages(segment.get_instance(self.source_locale)) text_segments = [ segment for segment in segments if isinstance(segment, SegmentValue) ] # Initialise translated segments by copying templates and related objects translated_segments = [ segment for segment in segments if isinstance(segment, (TemplateValue, RelatedObjectValue)) ] missing_segments = 0 for segment in text_segments: if segment.text in self.translations: translated_segments.append( SegmentValue( segment.path, self.translations[segment.text], order=segment.order, )) else: missing_segments += 1 if missing_segments: raise MissingSegmentsException(instance, missing_segments) translated_segments.sort(key=lambda segment: segment.order) try: translation = instance.get_translation(self.target_locale) except instance.__class__.DoesNotExist: translation = instance.copy_for_translation(self.target_locale) ingest_segments( instance, translation, self.source_locale, self.target_locale, translated_segments, ) if isinstance(translation, Page): translation.slug = slugify(translation.slug) revision = translation.save_revision() else: translation.save() return translation
def test_urlfield(self): page = make_test_page(test_urlfield="http://test-content.com/foo") segments = extract_segments(page) self.assertEqual( segments, [SegmentValue("test_urlfield", "http://test-content.com/foo")])
def test_text(self): segment = SegmentValue.from_html( "foo", "This is a paragraph. <b>This is some bold <i>and now italic</i></b> text", ) self.assertEqual( segment.text, "This is a paragraph. This is some bold and now italic text")
def test_html_with_ids(self): segment = SegmentValue.from_html( "foo", '<b>Bread</b>\xa0is a\xa0<a href="https://en.wikipedia.org/wiki/Staple_food">staple food</a>\xa0prepared from a\xa0<a href="https://en.wikipedia.org/wiki/Dough">dough</a>\xa0of\xa0<a href="https://en.wikipedia.org/wiki/Flour">flour</a>\xa0and\xa0<a href="https://en.wikipedia.org/wiki/Water">water</a>, usually by\xa0<a href="https://en.wikipedia.org/wiki/Baking">baking</a>. Throughout recorded history it has been popular around the world and is one of the oldest artificial foods, having been of importance since the dawn of\xa0<a href="https://en.wikipedia.org/wiki/Agriculture#History">agriculture</a>.', ) self.assertEqual( segment.html_with_ids, '<b>Bread</b> is a <a id="a1">staple food</a> prepared from a <a id="a2">dough</a> of <a id="a3">flour</a> and <a id="a4">water</a>, usually by <a id="a5">baking</a>. Throughout recorded history it has been popular around the world and is one of the oldest artificial foods, having been of importance since the dawn of <a id="a6">agriculture</a>.', )
def test_emailblock(self): block_id = uuid.uuid4() page = make_test_page_with_streamfield_block(str(block_id), "test_emailblock", "*****@*****.**") segments = extract_segments(page) self.assertEqual( segments, [SegmentValue(f"test_streamfield.{block_id}", "*****@*****.**")])
def test_blockquoteblock(self): block_id = uuid.uuid4() page = make_test_page_with_streamfield_block(str(block_id), "test_blockquoteblock", "Test content") segments = extract_segments(page) self.assertEqual( segments, [SegmentValue(f"test_streamfield.{block_id}", "Test content")])
def test_customfield(self): page = make_test_page(test_customfield="Test content") segments = extract_segments(page) self.assertEqual( segments, [ SegmentValue("test_customfield.foo", "Test content and some extra") ], )
def test_emailfield(self): page = make_test_page(test_emailfield="*****@*****.**") translated_page = page.copy_for_translation(self.locale) ingest_segments( page, translated_page, self.src_locale, self.locale, [SegmentValue("test_emailfield", "*****@*****.**")], ) self.assertEqual(translated_page.test_emailfield, "*****@*****.**")
def test_textfield(self): page = make_test_page(test_textfield="Test content") translated_page = page.copy_for_translation(self.locale) ingest_segments( page, translated_page, self.src_locale, self.locale, [SegmentValue("test_textfield", "Tester le contenu")], ) self.assertEqual(translated_page.test_textfield, "Tester le contenu")
def test_urlfield(self): page = make_test_page(test_urlfield="http://test-content.com/foo") translated_page = page.copy_for_translation(self.locale) ingest_segments( page, translated_page, self.src_locale, self.locale, [SegmentValue("test_urlfield", "http://test-content.fr/foo")], ) self.assertEqual(translated_page.test_urlfield, "http://test-content.fr/foo")
def test_urlblock(self): block_id = uuid.uuid4() page = make_test_page_with_streamfield_block( str(block_id), "test_urlblock", "http://test-content.com/foo") segments = extract_segments(page) self.assertEqual( segments, [ SegmentValue(f"test_streamfield.{block_id}", "http://test-content.com/foo") ], )
def test_replace_html_attrs(self): segment = SegmentValue.from_html( "foo.bar", 'This is some text. <foo> <b>Bold text</b> <a id="a1">A link and some more <b>Bold text</b></a>', ) segment.replace_html_attrs( {"a#a1": { "href": "http://changed-example.com" }}) self.assertEqual( segment.html, 'This is some text. <foo> <b>Bold text</b> <a href="http://changed-example.com">A link and some more <b>Bold text</b></a>', )
def test_childobjects(self): page = make_test_page() page.test_childobjects.add(TestChildObject(field="Test content")) page.save() child_translation_key = TestChildObject.objects.get().translation_key segments = extract_segments(page) self.assertEqual( segments, [ SegmentValue( f"test_childobjects.{child_translation_key}.field", "Test content") ], )
def test_snippet(self): test_snippet = TestSnippet.objects.create(field="Test content") translated_snippet = test_snippet.copy_for_translation(self.locale) translated_snippet.save() # Ingest segments into the snippet ingest_segments( test_snippet, translated_snippet, self.src_locale, self.locale, [SegmentValue("field", "Tester le contenu")], ) translated_snippet.save() self.assertEqual(translated_snippet.field, "Tester le contenu") # Now ingest a RelatedObjectValue into the page page = make_test_page(test_snippet=test_snippet) translated_page = page.copy_for_translation(self.locale) ingest_segments( page, translated_page, self.src_locale, self.locale, [RelatedObjectValue.from_instance("test_snippet", test_snippet)], ) # Check the translated snippet was linked to the translated page self.assertNotEqual(page.test_snippet_id, translated_page.test_snippet_id) self.assertEqual(page.test_snippet.locale, self.src_locale) self.assertEqual(translated_page.test_snippet.locale, self.locale) self.assertEqual( page.test_snippet.translation_key, translated_page.test_snippet.translation_key, ) self.assertEqual(translated_page.test_snippet.field, "Tester le contenu")
def test_customstructblock(self): block_id = uuid.uuid4() page = make_test_page_with_streamfield_block( str(block_id), "test_customstructblock", { "field_a": "Test content", "field_b": "Some more test content" }, ) translated_page = page.copy_for_translation(self.locale) ingest_segments( page, translated_page, self.src_locale, self.locale, [ SegmentValue( f"test_streamfield.{block_id}.foo", "Tester le contenu / Encore du contenu de test", ) ], ) translated_page.save() translated_page.refresh_from_db() self.assertEqual( translated_page.test_streamfield.stream_data, [{ "id": str(block_id), "type": "test_customstructblock", "value": { "field_a": "Tester le contenu", "field_b": "Encore du contenu de test", }, }], )
def test_customstructblock(self): block_id = uuid.uuid4() page = make_test_page_with_streamfield_block( str(block_id), "test_customstructblock", { "field_a": "Test content", "field_b": "Some more test content" }, ) segments = extract_segments(page) self.assertEqual( segments, [ SegmentValue( f"test_streamfield.{block_id}.foo", "Test content / Some more test content", ) ], )
def test_nestedstreamblock(self): block_id = uuid.uuid4() nested_block_id = uuid.uuid4() page = make_test_page_with_streamfield_block( str(block_id), "test_nestedstreamblock", [{ "id": str(nested_block_id), "type": "block_a", "value": "Test content" }], ) segments = extract_segments(page) self.assertEqual( segments, [ SegmentValue(f"test_streamfield.{block_id}.{nested_block_id}", "Test content") ], )
def get_translatable_segments(self, value): if not value: # Don't disrupt other tests return [] return [SegmentValue("foo", "{} and some extra".format(value))]
def test_segment_value(self): segment = SegmentValue.from_html( "foo.bar", 'This is some text. <foo> <b>Bold text</b> <a href="http://example.com">A link and some more <b>Bold text</b></a>', ) self.assertEqual(segment.path, "foo.bar") self.assertEqual(segment.order, 0) self.assertEqual( segment.text, "This is some text. <foo> Bold text A link and some more Bold text", ) self.assertEqual( segment.html_elements, [ SegmentValue.HTMLElement(25, 34, "b1", ("b", {})), SegmentValue.HTMLElement(56, 65, "b2", ("b", {})), SegmentValue.HTMLElement(35, 65, "a1", ("a", { "href": "http://example.com" })), ], ) self.assertEqual( segment.html, 'This is some text. <foo> <b>Bold text</b> <a href="http://example.com">A link and some more <b>Bold text</b></a>', ) self.assertEqual( segment.html_with_ids, 'This is some text. <foo> <b>Bold text</b> <a id="a1">A link and some more <b>Bold text</b></a>', ) self.assertEqual(segment.get_html_attrs(), {"a#a1": { "href": "http://example.com" }}) # .with_order() orderred = segment.with_order(123) self.assertEqual(segment.order, 0) self.assertEqual(orderred.order, 123) self.assertEqual(orderred.path, "foo.bar") self.assertEqual(orderred.text, segment.text) self.assertEqual(orderred.html_elements, segment.html_elements) self.assertEqual(orderred.html, segment.html) self.assertEqual(orderred.html_with_ids, segment.html_with_ids) # .wrap() wrapped = segment.wrap("baz") self.assertEqual(segment.path, "foo.bar") self.assertEqual(wrapped.path, "baz.foo.bar") self.assertEqual(wrapped.order, segment.order) self.assertEqual(wrapped.text, segment.text) self.assertEqual(wrapped.html_elements, segment.html_elements) self.assertEqual(wrapped.html, segment.html) self.assertEqual(wrapped.html_with_ids, segment.html_with_ids) # .unwrap() path_component, unwrapped = segment.unwrap() self.assertEqual(segment.path, "foo.bar") self.assertEqual(path_component, "foo") self.assertEqual(unwrapped.path, "bar") self.assertEqual(unwrapped.order, segment.order) self.assertEqual(unwrapped.text, segment.text) self.assertEqual(unwrapped.html_elements, segment.html_elements) self.assertEqual(unwrapped.html, segment.html) self.assertEqual(unwrapped.html_with_ids, segment.html_with_ids)
def extract_segments(instance): segments = [] for translatable_field in instance.get_translatable_fields(): field = translatable_field.get_field(instance.__class__) if hasattr(field, "get_translatable_segments"): segments.extend( segment.wrap(field.name) for segment in field.get_translatable_segments( field.value_from_object(instance) ) ) elif isinstance(field, StreamField): segments.extend( segment.wrap(field.name) for segment in StreamFieldSegmentExtractor(field).handle_stream_block( field.value_from_object(instance) ) ) elif isinstance(field, RichTextField): template, texts = extract_html_segments(field.value_from_object(instance)) field_segments = [TemplateValue("", "html", template, len(texts))] + [ SegmentValue.from_html("", text) for text in texts ] segments.extend(segment.wrap(field.name) for segment in field_segments) elif isinstance(field, (models.TextField, models.CharField)): if not field.choices: segments.append( SegmentValue(field.name, field.value_from_object(instance)) ) elif isinstance(field, (models.ForeignKey)) and issubclass( field.related_model, TranslatableMixin ): related_instance = getattr(instance, field.name) if related_instance: segments.append( RelatedObjectValue.from_instance(field.name, related_instance) ) elif ( isinstance(field, (models.ManyToOneRel)) and isinstance(field.remote_field, ParentalKey) and issubclass(field.related_model, TranslatableMixin) ): manager = getattr(instance, field.name) for child_instance in manager.all(): segments.extend( segment.wrap(str(child_instance.translation_key)).wrap(field.name) for segment in extract_segments(child_instance) ) class Counter: def __init__(self): self.value = 0 def next(self): self.value += 1 return self.value counter = Counter() return [ segment.with_order(counter.next()) for segment in segments if not segment.is_empty() ]
def test_slugfield(self): page = make_test_page(test_slugfield="test-content") segments = extract_segments(page) self.assertEqual(segments, [SegmentValue("test_slugfield", "test-content")])
def test_emailfield(self): page = make_test_page(test_emailfield="*****@*****.**") segments = extract_segments(page) self.assertEqual(segments, [SegmentValue("test_emailfield", "*****@*****.**")])
def get_translatable_segments(self, value): return [ SegmentValue("foo", "{} / {}".format(value["field_a"], value["field_b"])) ]
def make_test_page(**kwargs): root_page = Page.objects.get(id=1) kwargs.setdefault("title", "Test page") return root_page.add_child(instance=TestPage(**kwargs)) RICH_TEXT_TEST_INPUT = '<h1>This is a heading</h1><p>This is a paragraph. <foo> <b>Bold text</b></p><ul><li><a href="http://example.com">This is a link</a>.</li></ul>' RICH_TEXT_TEST_OUTPUT = [ TemplateValue( "", "html", '<h1><text position="0"></text></h1><p><text position="1"></text></p><ul><li><text position="2"></text></li></ul>', 3, ), SegmentValue("", "This is a heading", html_elements=[]), SegmentValue( "", "This is a paragraph. <foo> Bold text", html_elements=[SegmentValue.HTMLElement(27, 36, "b1", ("b", {}))], ), SegmentValue( "", "This is a link.", html_elements=[ SegmentValue.HTMLElement(0, 14, "a1", ("a", { "href": "http://example.com" })) ], ), ]
root_page = Page.objects.get(id=1) kwargs.setdefault("title", "Test page") return root_page.add_child(instance=TestPage(**kwargs)) RICH_TEXT_TEST_INPUT = '<h1>This is a heading</h1><p>This is a paragraph. <foo> <b>Bold text</b></p><ul><li><a href="http://example.com">This is a link</a></li></ul>' RICH_TEXT_TEST_FRENCH_SEGMENTS = [ TemplateValue( "", "html", '<h1><text position="0"></text></h1><p><text position="1"></text></p><ul><li><text position="2"></text></li></ul>', 3, order=9, ), SegmentValue("", "Ceci est une rubrique", html_elements=[], order=10), SegmentValue( "", "Ceci est un paragraphe. <foo> Texte en gras", html_elements=[SegmentValue.HTMLElement(30, 43, "b1", ("b", {}))], order=11, ), SegmentValue( "", "Ceci est un lien", html_elements=[ SegmentValue.HTMLElement(0, 16, "a1", ("a", { "href": "http://example.com" })) ], order=12,