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_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_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_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() ]