def test_snippet(self): test_snippet = TestSnippet.objects.create(field="Test content") page = make_test_page(test_snippet=test_snippet) segments = extract_segments(page) self.assertEqual(segments, [ RelatedObjectSegmentValue.from_instance("test_snippet", test_snippet) ])
def handle_related_object_block(self, related_object): if related_object is None: return [] if isinstance(related_object, TranslatableMixin): return [ RelatedObjectSegmentValue.from_instance("", related_object) ] else: return [OverridableSegmentValue("", related_object.pk)]
def handle_related_object_block(self, related_object): if related_object is None: return [] # All FKs to translatable models should be translatable. # With the exception of pages that are special because we can localize them at runtime easily. # TODO: Perhaps we need a special type for pages where it links to the translation if availabe, # but falls back to the source if it isn't translated yet? # Note: This exact same decision was made for regular foreign keys in fields.py if isinstance(related_object, TranslatableMixin) and not isinstance( related_object, Page): return [ RelatedObjectSegmentValue.from_instance("", related_object) ] else: return [OverridableSegmentValue("", related_object.pk)]
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, [StringSegmentValue("field", "Tester le contenu")], ) translated_snippet.save() self.assertEqual(translated_snippet.field, "Tester le contenu") # Now ingest a RelatedObjectSegmentValue 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, [ RelatedObjectSegmentValue.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 extract_segments(instance): """ Extracts segments from the given model instance. Args: instance (Model): The model instance to extract segments from. Returns: list[StringSegmentValue, TemplateSegmentValue, RelatedObjectSegmentValue, or OverridableSegmentValue]: The segment values that have been extracted. """ segments = [] for translatable_field in get_translatable_fields(instance.__class__): field = translatable_field.get_field(instance.__class__) is_translatable = translatable_field.is_translated(instance) is_synchronized = translatable_field.is_synchronized(instance) is_overridable = translatable_field.is_overridable(instance) extract_overridables = is_synchronized and is_overridable if hasattr(field, "get_translatable_segments"): if is_translatable: segments.extend( segment.wrap(field.name) for segment in field.get_translatable_segments( field.value_from_object(instance))) elif isinstance(field, StreamField): if is_translatable: segments.extend( segment.wrap(field.name) for segment in StreamFieldSegmentExtractor( field, include_overridables=extract_overridables). handle_stream_block(field.value_from_object(instance))) elif isinstance(field, RichTextField): if is_translatable: template, strings = extract_strings( field.value_from_object(instance)) # Find all unique href values hrefs = set() for _string, attrs in strings: for tag_attrs in attrs.values(): if "href" in tag_attrs: hrefs.add(tag_attrs["href"]) field_segments = ([ TemplateSegmentValue("", "html", template, len(strings)) ] + [ StringSegmentValue("", string, attrs=attrs) for string, attrs in strings ] + [ OverridableSegmentValue(quote_path_component(href), href) for href in sorted(hrefs) ]) segments.extend( segment.wrap(field.name) for segment in field_segments) if extract_overridables: pass # TODO: Extract images and links elif isinstance(field, (models.TextField, models.CharField)): if not field.choices: value = field.value_from_object(instance) if value is None: continue if is_translatable: segments.append(StringSegmentValue(field.name, value)) elif extract_overridables: segments.append(OverridableSegmentValue(field.name, value)) elif isinstance(field, (models.ForeignKey)): if is_translatable: if not issubclass(field.related_model, TranslatableMixin): raise ImproperlyConfigured( "The foreign key `{}.{}.{}` was registered as a translatable " "field but the model it points to `{}.{}` is not translatable" .format( field.model._meta.app_label, field.model.__name__, field.name, field.related_model._meta.app_label, field.related_model.__name__, )) related_instance = getattr(instance, field.name) if related_instance: segments.append( RelatedObjectSegmentValue.from_instance( field.name, related_instance)) elif extract_overridables: related_instance = getattr(instance, field.name) if related_instance: segments.append( OverridableSegmentValue(field.name, related_instance.pk)) elif (isinstance(field, (models.ManyToOneRel)) and isinstance(field.remote_field, ParentalKey) and issubclass(field.related_model, TranslatableMixin)): manager = getattr(instance, field.name) if is_translatable: 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)) elif extract_overridables: pass # TODO 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 extract_segments(instance): segments = [] for translatable_field in get_translatable_fields(instance.__class__): if not translatable_field.is_translated(instance): continue 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, strings = extract_strings( field.value_from_object(instance)) field_segments = [ TemplateSegmentValue("", "html", template, len(strings)) ] + [ StringSegmentValue("", string, attrs=attrs) for string, attrs in strings ] segments.extend( segment.wrap(field.name) for segment in field_segments) elif isinstance(field, (models.TextField, models.CharField)): if not field.choices: segments.append( StringSegmentValue(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( RelatedObjectSegmentValue.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 handle_related_object_block(self, related_object): if related_object is None or not isinstance(related_object, TranslatableMixin): return [] return [RelatedObjectSegmentValue.from_instance("", related_object)]