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")
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, )
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", )
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()
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
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")
def test_find_available_slug(self): with self.assertNumQueries(1): slug = find_available_slug(self.root_page, "unique-slug") self.assertEqual(slug, "unique-slug")