Example #1
0
    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"),
            ],
        )
Example #6
0
    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. &lt;foo&gt; <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. &lt;foo&gt; <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")
            ],
        )
Example #23
0
    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. &lt;foo&gt; <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. &lt;foo&gt; <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. &lt;foo&gt; <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)
Example #25
0
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", "*****@*****.**")])
Example #28
0
 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. &lt;foo&gt; <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. &lt;foo&gt; <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,