Coverage for baibu/localization/models.py: 100%
52 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-10-06 13:07 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-10-06 13:07 +0000
1import uuid
3from django.conf import settings
4from django.db import models
5from django.utils import timezone
6from django.utils.translation import gettext_lazy as _
9class TranslationSource(models.Model):
10 """The interface strings extracted from the code (a gettext template).
12 The newest row is the current template. The file itself lives in private
13 storage (``pot_key``).
14 """
16 id = models.UUIDField(primary_key=True, default=uuid.uuid7, editable=False)
17 pot_key = models.CharField(max_length=512)
18 # SHA-256 of the extracted entries, so an unchanged extraction is skipped.
19 content_hash = models.CharField(max_length=64)
20 entry_count = models.PositiveIntegerField(default=0)
21 created_by = models.ForeignKey(
22 settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name="+"
23 )
24 created_at = models.DateTimeField(default=timezone.now)
26 class Meta:
27 ordering = ["-created_at"]
28 get_latest_by = "created_at"
29 verbose_name = _("Source strings")
30 verbose_name_plural = _("Source strings")
32 def __str__(self) -> str:
33 return f"Source strings of {self.created_at:%Y-%m-%d %H:%M}"
36class TranslationCatalogue(models.Model):
37 """The working copy (draft) of one language's interface translations."""
39 language_code = models.CharField(_("Language"), max_length=24, unique=True)
40 # The draft .po file in private storage. Replaced on every save.
41 draft_key = models.CharField(max_length=512)
42 # The template last merged into the draft.
43 source = models.ForeignKey(TranslationSource, on_delete=models.SET_NULL, null=True, blank=True, related_name="+")
44 updated_by = models.ForeignKey(
45 settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name="+"
46 )
47 updated_at = models.DateTimeField(default=timezone.now)
48 created_at = models.DateTimeField(auto_now_add=True)
50 class Meta:
51 ordering = ["language_code"]
52 verbose_name = _("Translation catalogue")
53 verbose_name_plural = _("Translation catalogues")
54 permissions = [("edit_translations", _("Can edit and publish interface translations"))]
56 def __str__(self) -> str:
57 return self.language_code
60class TranslationPublication(models.Model):
61 """One publication of a language's translations: the audit trail.
63 Rows are never changed. Publishing again, or restoring an earlier
64 version, adds a row; the newest row for a language is what the site uses.
65 """
67 id = models.UUIDField(primary_key=True, default=uuid.uuid7, editable=False)
68 language_code = models.CharField(_("Language"), max_length=24, db_index=True)
69 version = models.PositiveIntegerField()
70 po_key = models.CharField(max_length=512)
71 mo_key = models.CharField(max_length=512)
72 total_count = models.PositiveIntegerField(default=0)
73 translated_count = models.PositiveIntegerField(default=0)
74 fuzzy_count = models.PositiveIntegerField(default=0)
75 restored_from = models.ForeignKey(
76 "self", on_delete=models.SET_NULL, null=True, blank=True, related_name="+", help_text=_("Set for a restore.")
77 )
78 published_by = models.ForeignKey(
79 settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name="+"
80 )
81 published_at = models.DateTimeField(default=timezone.now, db_index=True)
83 class Meta:
84 ordering = ["-published_at"]
85 verbose_name = _("Translation publication")
86 verbose_name_plural = _("Translation publications")
87 constraints = [
88 models.UniqueConstraint(fields=["language_code", "version"], name="localization_unique_version"),
89 ]
91 def __str__(self) -> str:
92 return f"{self.language_code} v{self.version}"