Skip to content

Commit

Permalink
Add field_path field to TranslationContext
Browse files Browse the repository at this point in the history
  • Loading branch information
kaedroho committed Sep 27, 2021
1 parent fb488b9 commit 14d8b1a
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 14 deletions.
19 changes: 19 additions & 0 deletions wagtail_localize/migrations/0014_translationcontext_field_path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.2.4 on 2021-07-20 14:26

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('wagtail_localize', '0013_translationsource_schema_version'),
]

operations = [
migrations.AddField(
model_name='translationcontext',
name='field_path',
field=models.TextField(default=''),
preserve_default=False,
),
]
82 changes: 68 additions & 14 deletions wagtail_localize/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@
from django.utils import timezone
from django.utils.text import slugify
from django.utils.translation import gettext as _, gettext_lazy
from modelcluster.fields import ParentalKey
from modelcluster.models import (
ClusterableModel,
get_serializable_data_for_fields,
model_from_serializable_data,
)
from wagtail.core.models import Page, get_translatable_models, PageLogEntry
from wagtail.core import blocks
from wagtail.core.fields import StreamField
from wagtail.core.models import Page, get_translatable_models, PageLogEntry, TranslatableMixin
from wagtail.core.utils import find_available_slug

from .compat import DATE_FORMAT
Expand Down Expand Up @@ -497,23 +500,23 @@ def refresh_segments(self):
seen_related_object_segment_ids = []
seen_overridable_segment_ids = []

for segment in extract_segments(self.as_instance()):
instance = self.as_instance()
for segment in extract_segments(instance):
if isinstance(segment, TemplateSegmentValue):
seen_template_segment_ids.append(
TemplateSegment.from_value(self, segment).id
)
segment_obj = TemplateSegment.from_value(self, segment)
seen_template_segment_ids.append(segment_obj.id)
elif isinstance(segment, RelatedObjectSegmentValue):
seen_related_object_segment_ids.append(
RelatedObjectSegment.from_value(self, segment).id
)
segment_obj = RelatedObjectSegment.from_value(self, segment)
seen_related_object_segment_ids.append(segment_obj.id)
elif isinstance(segment, OverridableSegmentValue):
seen_overridable_segment_ids.append(
OverridableSegment.from_value(self, segment).id
)
segment_obj = OverridableSegment.from_value(self, segment)
seen_overridable_segment_ids.append(segment_obj.id)
else:
seen_string_segment_ids.append(
StringSegment.from_value(self, self.locale, segment).id
)
segment_obj = StringSegment.from_value(self, self.locale, segment)
seen_string_segment_ids.append(segment_obj.id)

# Make sure the segment's field_path is pre-populated
segment_obj.context.get_field_path(instance)

# Delete any segments that weren't mentioned
self.stringsegment_set.exclude(id__in=seen_string_segment_ids).delete()
Expand Down Expand Up @@ -1253,13 +1256,15 @@ class TranslationContext(models.Model):
Attributes:
object (ForeignKey to TranslatableObject): The object.
path (TextField): The content path.
field_path (TextField): the field path.
path_id (UUIDField): A hash of the path for efficient indexing of long content paths.
"""
object = models.ForeignKey(
TranslatableObject, on_delete=models.CASCADE, related_name="+"
)
path_id = models.UUIDField()
path = models.TextField()
field_path = models.TextField()

class Meta:
unique_together = [
Expand All @@ -1285,6 +1290,55 @@ def save(self, *args, **kwargs):

return super().save(*args, **kwargs)

def get_field_path(self, instance):
"""
Gets the field path for this context
Field path's were introduced in version 1.0, any contexts that were created before that release won't have one.
"""
if not self.field_path:
def get_field_path_from_field(instance, path_components):
field_name = path_components[0]
field = instance._meta.get_field(field_name)

if isinstance(field, StreamField):
def get_field_path_from_stream_block(stream_value, path_components):
stream_blocks_by_id = {
block.id: block
for block in stream_value
}
block_id = path_components[0]
block = stream_blocks_by_id[block_id]
block_def = stream_value.stream_block.child_blocks[block.block_type]

if isinstance(block_def, blocks.StructBlock):
return [block.block_type, path_components[1]]

elif isinstance(block_def, blocks.StreamBlock):
return [block.block_type] + get_field_path_from_stream_block(block.value, path_components[1:])

else:
return [block.block_type]

return [field_name] + get_field_path_from_stream_block(field.value_from_object(instance), path_components[1:])

elif (
isinstance(field, (models.ManyToOneRel))
and isinstance(field.remote_field, ParentalKey)
and issubclass(field.related_model, TranslatableMixin)
):
manager = getattr(instance, field_name)
child_instance = manager.get(translation_key=path_components[1])
return [field_name] + get_field_path_from_field(child_instance, path_components[2:])

else:
return [field_name]

self.field_path = '.'.join(get_field_path_from_field(instance, self.path.split('.')))
self.save(update_fields=['field_path'])

return self.field_path


class StringTranslation(models.Model):
"""
Expand Down

0 comments on commit 14d8b1a

Please sign in to comment.