Example #1
0
    def test_find_available_slug_ignore_page_id(self):
        with self.assertNumQueries(1):
            slug = find_available_slug(self.root_page,
                                       "home",
                                       ignore_page_id=self.second_home_page.id)

        self.assertEqual(slug, "home-1")
Example #2
0
    def _action_from_data(self, instance, data):
        destination_page_id = data.get("destination_page_id")
        if destination_page_id is None:
            destination = instance.get_parent()
        else:
            destination = get_object_or_404(Page, id=destination_page_id)

        update_attrs = {}
        if "slug" in data:
            update_attrs["slug"] = data["slug"]
        else:
            # If user didn't specify a particular slug, find an available one
            available_slug = find_available_slug(destination, instance.slug)
            if available_slug != instance.slug:
                update_attrs["slug"] = available_slug

        if "title" in data:
            update_attrs["title"] = data["title"]

        return CopyPageAction(
            page=instance,
            to=destination,
            recursive=data["recursive"],
            keep_live=data["keep_live"],
            update_attrs=update_attrs,
            user=self.request.user,
        )
Example #3
0
    def _copy_for_translation(self, page, locale, copy_parents, alias,
                              exclude_fields):
        # Find the translated version of the parent page to create the new page under
        parent = page.get_parent().specific
        slug = page.slug

        if not parent.is_root():
            try:
                translated_parent = parent.get_translation(locale)
            except parent.__class__.DoesNotExist:
                if not copy_parents:
                    raise ParentNotTranslatedError(
                        "Parent page is not translated.")

                translated_parent = parent.copy_for_translation(
                    locale, copy_parents=True, alias=True)
        else:
            # Don't duplicate the root page for translation. Create new locale as a sibling
            translated_parent = parent

            # Append language code to slug as the new page
            # will be created in the same section as the existing one
            slug += "-" + locale.language_code

        # Find available slug for new page
        slug = find_available_slug(translated_parent, slug)

        if alias:
            return page.create_alias(
                parent=translated_parent,
                update_slug=slug,
                update_locale=locale,
                reset_translation_key=False,
            )

        else:
            # Update locale on translatable child objects as well
            def process_child_object(original_page, page_copy, child_relation,
                                     child_object):
                from wagtail.core.models import TranslatableMixin

                if isinstance(child_object, TranslatableMixin):
                    child_object.locale = locale

            return page.copy(
                to=translated_parent,
                update_attrs={
                    "locale": locale,
                    "slug": slug,
                },
                copy_revisions=False,
                keep_live=False,
                reset_translation_key=False,
                process_child_object=process_child_object,
                exclude_fields=exclude_fields,
                log_action="wagtail.copy_for_translation",
            )
Example #4
0
def sync_localized_slugs(request, page):
    for translation in page.get_translations():
        translation.slug = find_available_slug(translation.get_parent(),
                                               page.slug,
                                               ignore_page_id=translation.id)

        if translation.alias_of_id is not None:
            # This is still an alias rather than a published
            # localized page, so we can only save it as we
            # would any plain Django model:
            translation.save()

        else:
            # If it's a real page, it needs to go through
            # the revision/publication process.
            translation.save_revision().publish()
Example #5
0
    def create_or_update_translation(self,
                                     locale,
                                     user=None,
                                     publish=True,
                                     copy_parent_pages=False,
                                     fallback=False):
        """
        Creates/updates a translation of the object into the specified locale
        based on the content of this source and the translated strings
        currently in translation memory.
        """
        original = self.as_instance()
        created = False

        # Only pages can be saved as draft
        if not publish and not isinstance(original, Page):
            raise CannotSaveDraftError

        try:
            translation = self.get_translated_instance(locale)
        except models.ObjectDoesNotExist:
            if isinstance(original, Page):
                translation = original.copy_for_translation(
                    locale, copy_parents=copy_parent_pages)
            else:
                translation = original.copy_for_translation(locale)

            created = True

        copy_synchronised_fields(original, translation)

        segments = self.get_segments_for_translation(locale, fallback=fallback)

        try:
            with transaction.atomic():
                # Ingest all translated segments
                ingest_segments(original, translation, self.locale, locale,
                                segments)

                if isinstance(translation, Page):
                    # Make sure the slug is valid
                    translation.slug = find_available_slug(
                        translation.get_parent(),
                        slugify(translation.slug),
                        ignore_page_id=translation.id)
                    translation.save()

                    # Create a new revision
                    page_revision = translation.save_revision(user=user)

                    if publish:
                        page_revision.publish()
                else:
                    translation.save()
                    page_revision = None

        except ValidationError as e:
            # If the validation error's field matches the context of a translation,
            # set that error message on that translation.
            # TODO (someday): Add support for errors raised from streamfield
            for field_name, errors in e.error_dict.items():
                try:
                    context = TranslationContext.objects.get(
                        object=self.object, path=field_name)

                except TranslationContext.DoesNotExist:
                    # TODO (someday): How would we handle validation errors for non-translatable fields?
                    continue

                # Check for string translation
                try:
                    string_translation = StringTranslation.objects.get(
                        translation_of_id__in=StringSegment.objects.filter(
                            source=self).values_list('string_id', flat=True),
                        context=context,
                        locale=locale,
                    )

                    string_translation.set_field_error(errors)

                except StringTranslation.DoesNotExist:
                    pass

                # Check for segment override
                try:
                    segment_override = SegmentOverride.objects.get(
                        context=context,
                        locale=locale,
                    )

                    segment_override.set_field_error(errors)

                except SegmentOverride.DoesNotExist:
                    pass

            raise

        # Log that the translation was made
        TranslationLog.objects.create(source=self,
                                      locale=locale,
                                      page_revision=page_revision)

        return translation, created
Example #6
0
    def test_find_available_slug_already_used(self):
        # Even though the first two slugs are already used, this still requires only one query to find a unique one
        with self.assertNumQueries(1):
            slug = find_available_slug(self.root_page, "home")

        self.assertEqual(slug, "home-2")
Example #7
0
    def test_find_available_slug(self):
        with self.assertNumQueries(1):
            slug = find_available_slug(self.root_page, "unique-slug")

        self.assertEqual(slug, "unique-slug")