prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Fix translation coverage
  The translation coverage is not working due to the changed language model a while ago...
  Error: `'Language' object has no attribute 'name'`
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `backend/cms/views/analytics/translation_coverage_view.py`
  Content:
  ```
  1 """Views related to the statistics module"""
  2 from django.contrib.auth.decorators import login_required
  3 from django.utils.decorators import method_decorator
  4 from django.views.generic import TemplateView
  5 from django.shortcuts import render
  6 
  7 from ...models import Language, Page, PageTranslation
  8 from ...decorators import region_permission_required
  9 
  10 
  11 @method_decorator(login_required, name='dispatch')
  12 @method_decorator(region_permission_required, name='dispatch')
  13 class TranslationCoverageView(TemplateView):
  14     """
  15     Class to create the statistic page, that can be found via -> "Statistiken"
  16     """
  17     template_name = 'analytics/translation_coverage.html'
  18     base_context = {'current_menu_item': 'translation_coverage'}
  19 
  20     def get(self, request, *args, **kwargs):
  21 
  22         languages = Language.objects.all()
  23 
  24         languages = list(map(lambda x: [x.code, x.name, x.id], languages))
  25 
  26         all_pages = Page.objects.count()
  27 
  28         # pylint: disable=consider-using-enumerate
  29         for i in range(len(languages)):
  30             translated_count = PageTranslation.objects.filter(language_id=languages[i][2]).count()
  31             languages[i].append(translated_count)
  32             languages[i].append(all_pages - languages[i][3])
  33 
  34         return render(
  35             request,
  36             self.template_name,
  37             {
  38                 **self.base_context,
  39                 'coverages': languages
  40             }
  41         )
  42
  ```
  
  Path: `backend/cms/models/pages/page_translation.py`
  Content:
  ```
  1 """Models representing a page and page translation with content
  2 """
  3 import logging
  4 
  5 from django.conf import settings
  6 from django.db import models
  7 from django.utils import timezone
  8 
  9 from .page import Page
  10 from ..languages.language import Language
  11 from ...constants import status
  12 
  13 
  14 logger = logging.getLogger(__name__)
  15 
  16 
  17 class PageTranslation(models.Model):
  18     """Class defining a Translation of a Page
  19 
  20     Args:
  21         models : Class inherit of django-Models
  22     """
  23 
  24     page = models.ForeignKey(Page, related_name='translations', on_delete=models.CASCADE)
  25     language = models.ForeignKey(
  26         Language,
  27         related_name='page_translations',
  28         on_delete=models.CASCADE
  29     )
  30     slug = models.SlugField(max_length=200, blank=True, allow_unicode=True)
  31     title = models.CharField(max_length=250)
  32     text = models.TextField(blank=True)
  33     status = models.CharField(max_length=6, choices=status.CHOICES, default=status.DRAFT)
  34     currently_in_translation = models.BooleanField(default=False)
  35     version = models.PositiveIntegerField(default=0)
  36     minor_edit = models.BooleanField(default=False)
  37     creator = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL)
  38     created_date = models.DateTimeField(default=timezone.now)
  39     last_updated = models.DateTimeField(auto_now=True)
  40 
  41     @property
  42     def foreign_object(self):
  43         return self.page
  44 
  45     @property
  46     def ancestor_path(self):
  47         return '/'.join([
  48             ancestor.get_first_translation([self.language.code]).slug
  49             for ancestor in self.page.get_ancestors()
  50         ])
  51 
  52     @property
  53     def permalink(self):
  54         return '/'.join(filter(None, [
  55             self.page.region.slug,
  56             self.language.code,
  57             self.ancestor_path,
  58             self.slug
  59         ]))
  60 
  61     @property
  62     def available_languages(self):
  63         languages = self.page.languages
  64         languages.remove(self.language)
  65         available_languages = {}
  66         for language in languages:
  67             other_translation = self.page.get_public_translation(language.code)
  68             if other_translation:
  69                 available_languages[language.code] = {
  70                     'id': other_translation.id,
  71                     'url': other_translation.permalink
  72                 }
  73         return available_languages
  74 
  75     @property
  76     def source_translation(self):
  77         source_language_tree_node = self.page.region.language_tree_nodes.get(language=self.language).parent
  78         if source_language_tree_node:
  79             return self.page.get_translation(source_language_tree_node.code)
  80         return None
  81 
  82     @property
  83     def latest_public_revision(self):
  84         return self.page.translations.filter(
  85             language=self.language,
  86             status=status.PUBLIC,
  87         ).first()
  88 
  89     @property
  90     def latest_major_revision(self):
  91         return self.page.translations.filter(
  92             language=self.language,
  93             minor_edit=False,
  94         ).first()
  95 
  96     @property
  97     def latest_major_public_revision(self):
  98         return self.page.translations.filter(
  99             language=self.language,
  100             status=status.PUBLIC,
  101             minor_edit=False,
  102         ).first()
  103 
  104     @property
  105     def previous_revision(self):
  106         version = self.version - 1
  107         return self.page.translations.filter(
  108             language=self.language,
  109             version=version,
  110         ).first()
  111 
  112     @property
  113     def is_outdated(self):
  114         source_translation = self.source_translation
  115         # If self.language is the root language, this translation can never be outdated
  116         if not source_translation:
  117             return False
  118         # If the source translation is outdated, this translation can not be up to date
  119         if source_translation.is_outdated:
  120             return True
  121         self_revision = self.latest_major_public_revision
  122         source_revision = source_translation.latest_major_public_revision
  123         # If on of the translations has no major public revision, it cannot be outdated
  124         if not self_revision or not source_revision:
  125             return False
  126         return self_revision.last_updated < source_revision.last_updated
  127 
  128     @property
  129     def combined_text(self):
  130         """
  131         Combines the text from the PageTranslation with the text from the mirrored page.
  132         """
  133         if self.page.mirrored_page_first:
  134             return self.page.get_mirrored_text(self.language.code) + self.text
  135         return self.text + self.page.get_mirrored_text(self.language.code)
  136 
  137     def __str__(self):
  138         if self.id:
  139             return '(id: {}, lang: {}, slug: {})'.format(self.id, self.language.code, self.slug)
  140         return super(PageTranslation, self).__str__()
  141 
  142     class Meta:
  143         ordering = ['page', '-version']
  144         default_permissions = ()
  145
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/backend/cms/models/pages/page_translation.py b/backend/cms/models/pages/page_translation.py
  --- a/backend/cms/models/pages/page_translation.py
  +++ b/backend/cms/models/pages/page_translation.py
  @@ -120,7 +120,7 @@
               return True
           self_revision = self.latest_major_public_revision
           source_revision = source_translation.latest_major_public_revision
  -        # If on of the translations has no major public revision, it cannot be outdated
  +        # If one of the translations has no major public revision, it cannot be outdated
           if not self_revision or not source_revision:
               return False
           return self_revision.last_updated < source_revision.last_updated
  @@ -134,9 +134,21 @@
               return self.page.get_mirrored_text(self.language.code) + self.text
           return self.text + self.page.get_mirrored_text(self.language.code)
   
  +    @classmethod
  +    def get_translations(cls, region, language):
  +        return cls.objects.filter(page__region=region, language=language).distinct('page')
  +
  +    @classmethod
  +    def get_outdated_translations(cls, region, language):
  +        return [t for t in cls.objects.filter(page__region=region, language=language).distinct('page') if t.is_outdated]
  +
  +    @classmethod
  +    def get_up_to_date_translations(cls, region, language):
  +        return [t for t in cls.objects.filter(page__region=region, language=language).distinct('page') if not t.is_outdated]
  +
       def __str__(self):
           if self.id:
  -            return '(id: {}, lang: {}, slug: {})'.format(self.id, self.language.code, self.slug)
  +            return '(id: {}, page_id: {}, lang: {}, version: {}, slug: {})'.format(self.id, self.page.id, self.language.code, self.version, self.slug)
           return super(PageTranslation, self).__str__()
   
       class Meta:
  diff --git a/backend/cms/views/analytics/translation_coverage_view.py b/backend/cms/views/analytics/translation_coverage_view.py
  --- a/backend/cms/views/analytics/translation_coverage_view.py
  +++ b/backend/cms/views/analytics/translation_coverage_view.py
  @@ -4,7 +4,7 @@
   from django.views.generic import TemplateView
   from django.shortcuts import render
   
  -from ...models import Language, Page, PageTranslation
  +from ...models import PageTranslation, Region
   from ...decorators import region_permission_required
   
   
  @@ -12,30 +12,31 @@
   @method_decorator(region_permission_required, name='dispatch')
   class TranslationCoverageView(TemplateView):
       """
  -    Class to create the statistic page, that can be found via -> "Statistiken"
  +    Class to create the translation coverage statistic
       """
       template_name = 'analytics/translation_coverage.html'
       base_context = {'current_menu_item': 'translation_coverage'}
   
       def get(self, request, *args, **kwargs):
   
  -        languages = Language.objects.all()
  +        region = Region.get_current_region(request)
  +        num_pages = region.pages.count()
  +        languages = []
   
  -        languages = list(map(lambda x: [x.code, x.name, x.id], languages))
  -
  -        all_pages = Page.objects.count()
  -
  -        # pylint: disable=consider-using-enumerate
  -        for i in range(len(languages)):
  -            translated_count = PageTranslation.objects.filter(language_id=languages[i][2]).count()
  -            languages[i].append(translated_count)
  -            languages[i].append(all_pages - languages[i][3])
  +        for language in region.languages:
  +            page_translations = PageTranslation.get_translations(region, language)
  +            languages.append({
  +                'translated_name': language.translated_name,
  +                'num_page_translations_up_to_date': len([t for t in page_translations if not t.is_outdated]),
  +                'num_page_translations_outdated': len([t for t in page_translations if t.is_outdated]),
  +                'num_page_translations_missing': num_pages - page_translations.count()
  +            })
   
           return render(
               request,
               self.template_name,
               {
                   **self.base_context,
  -                'coverages': languages
  +                'languages': languages
               }
           )
  
verification_info: {"golden_diff": "diff --git a/backend/cms/models/pages/page_translation.py b/backend/cms/models/pages/page_translation.py\n--- a/backend/cms/models/pages/page_translation.py\n+++ b/backend/cms/models/pages/page_translation.py\n@@ -120,7 +120,7 @@\n             return True\n         self_revision = self.latest_major_public_revision\n         source_revision = source_translation.latest_major_public_revision\n-        # If on of the translations has no major public revision, it cannot be outdated\n+        # If one of the translations has no major public revision, it cannot be outdated\n         if not self_revision or not source_revision:\n             return False\n         return self_revision.last_updated < source_revision.last_updated\n@@ -134,9 +134,21 @@\n             return self.page.get_mirrored_text(self.language.code) + self.text\n         return self.text + self.page.get_mirrored_text(self.language.code)\n \n+    @classmethod\n+    def get_translations(cls, region, language):\n+        return cls.objects.filter(page__region=region, language=language).distinct('page')\n+\n+    @classmethod\n+    def get_outdated_translations(cls, region, language):\n+        return [t for t in cls.objects.filter(page__region=region, language=language).distinct('page') if t.is_outdated]\n+\n+    @classmethod\n+    def get_up_to_date_translations(cls, region, language):\n+        return [t for t in cls.objects.filter(page__region=region, language=language).distinct('page') if not t.is_outdated]\n+\n     def __str__(self):\n         if self.id:\n-            return '(id: {}, lang: {}, slug: {})'.format(self.id, self.language.code, self.slug)\n+            return '(id: {}, page_id: {}, lang: {}, version: {}, slug: {})'.format(self.id, self.page.id, self.language.code, self.version, self.slug)\n         return super(PageTranslation, self).__str__()\n \n     class Meta:\ndiff --git a/backend/cms/views/analytics/translation_coverage_view.py b/backend/cms/views/analytics/translation_coverage_view.py\n--- a/backend/cms/views/analytics/translation_coverage_view.py\n+++ b/backend/cms/views/analytics/translation_coverage_view.py\n@@ -4,7 +4,7 @@\n from django.views.generic import TemplateView\n from django.shortcuts import render\n \n-from ...models import Language, Page, PageTranslation\n+from ...models import PageTranslation, Region\n from ...decorators import region_permission_required\n \n \n@@ -12,30 +12,31 @@\n @method_decorator(region_permission_required, name='dispatch')\n class TranslationCoverageView(TemplateView):\n     \"\"\"\n-    Class to create the statistic page, that can be found via -> \"Statistiken\"\n+    Class to create the translation coverage statistic\n     \"\"\"\n     template_name = 'analytics/translation_coverage.html'\n     base_context = {'current_menu_item': 'translation_coverage'}\n \n     def get(self, request, *args, **kwargs):\n \n-        languages = Language.objects.all()\n+        region = Region.get_current_region(request)\n+        num_pages = region.pages.count()\n+        languages = []\n \n-        languages = list(map(lambda x: [x.code, x.name, x.id], languages))\n-\n-        all_pages = Page.objects.count()\n-\n-        # pylint: disable=consider-using-enumerate\n-        for i in range(len(languages)):\n-            translated_count = PageTranslation.objects.filter(language_id=languages[i][2]).count()\n-            languages[i].append(translated_count)\n-            languages[i].append(all_pages - languages[i][3])\n+        for language in region.languages:\n+            page_translations = PageTranslation.get_translations(region, language)\n+            languages.append({\n+                'translated_name': language.translated_name,\n+                'num_page_translations_up_to_date': len([t for t in page_translations if not t.is_outdated]),\n+                'num_page_translations_outdated': len([t for t in page_translations if t.is_outdated]),\n+                'num_page_translations_missing': num_pages - page_translations.count()\n+            })\n \n         return render(\n             request,\n             self.template_name,\n             {\n                 **self.base_context,\n-                'coverages': languages\n+                'languages': languages\n             }\n         )\n", "issue": "Fix translation coverage\nThe translation coverage is not working due to the changed language model a while ago...\r\nError: `'Language' object has no attribute 'name'`\n", "before_files": [{"content": "\"\"\"Views related to the statistics module\"\"\"\nfrom django.contrib.auth.decorators import login_required\nfrom django.utils.decorators import method_decorator\nfrom django.views.generic import TemplateView\nfrom django.shortcuts import render\n\nfrom ...models import Language, Page, PageTranslation\nfrom ...decorators import region_permission_required\n\n\n@method_decorator(login_required, name='dispatch')\n@method_decorator(region_permission_required, name='dispatch')\nclass TranslationCoverageView(TemplateView):\n    \"\"\"\n    Class to create the statistic page, that can be found via -> \"Statistiken\"\n    \"\"\"\n    template_name = 'analytics/translation_coverage.html'\n    base_context = {'current_menu_item': 'translation_coverage'}\n\n    def get(self, request, *args, **kwargs):\n\n        languages = Language.objects.all()\n\n        languages = list(map(lambda x: [x.code, x.name, x.id], languages))\n\n        all_pages = Page.objects.count()\n\n        # pylint: disable=consider-using-enumerate\n        for i in range(len(languages)):\n            translated_count = PageTranslation.objects.filter(language_id=languages[i][2]).count()\n            languages[i].append(translated_count)\n            languages[i].append(all_pages - languages[i][3])\n\n        return render(\n            request,\n            self.template_name,\n            {\n                **self.base_context,\n                'coverages': languages\n            }\n        )\n", "path": "backend/cms/views/analytics/translation_coverage_view.py"}, {"content": "\"\"\"Models representing a page and page translation with content\n\"\"\"\nimport logging\n\nfrom django.conf import settings\nfrom django.db import models\nfrom django.utils import timezone\n\nfrom .page import Page\nfrom ..languages.language import Language\nfrom ...constants import status\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass PageTranslation(models.Model):\n    \"\"\"Class defining a Translation of a Page\n\n    Args:\n        models : Class inherit of django-Models\n    \"\"\"\n\n    page = models.ForeignKey(Page, related_name='translations', on_delete=models.CASCADE)\n    language = models.ForeignKey(\n        Language,\n        related_name='page_translations',\n        on_delete=models.CASCADE\n    )\n    slug = models.SlugField(max_length=200, blank=True, allow_unicode=True)\n    title = models.CharField(max_length=250)\n    text = models.TextField(blank=True)\n    status = models.CharField(max_length=6, choices=status.CHOICES, default=status.DRAFT)\n    currently_in_translation = models.BooleanField(default=False)\n    version = models.PositiveIntegerField(default=0)\n    minor_edit = models.BooleanField(default=False)\n    creator = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL)\n    created_date = models.DateTimeField(default=timezone.now)\n    last_updated = models.DateTimeField(auto_now=True)\n\n    @property\n    def foreign_object(self):\n        return self.page\n\n    @property\n    def ancestor_path(self):\n        return '/'.join([\n            ancestor.get_first_translation([self.language.code]).slug\n            for ancestor in self.page.get_ancestors()\n        ])\n\n    @property\n    def permalink(self):\n        return '/'.join(filter(None, [\n            self.page.region.slug,\n            self.language.code,\n            self.ancestor_path,\n            self.slug\n        ]))\n\n    @property\n    def available_languages(self):\n        languages = self.page.languages\n        languages.remove(self.language)\n        available_languages = {}\n        for language in languages:\n            other_translation = self.page.get_public_translation(language.code)\n            if other_translation:\n                available_languages[language.code] = {\n                    'id': other_translation.id,\n                    'url': other_translation.permalink\n                }\n        return available_languages\n\n    @property\n    def source_translation(self):\n        source_language_tree_node = self.page.region.language_tree_nodes.get(language=self.language).parent\n        if source_language_tree_node:\n            return self.page.get_translation(source_language_tree_node.code)\n        return None\n\n    @property\n    def latest_public_revision(self):\n        return self.page.translations.filter(\n            language=self.language,\n            status=status.PUBLIC,\n        ).first()\n\n    @property\n    def latest_major_revision(self):\n        return self.page.translations.filter(\n            language=self.language,\n            minor_edit=False,\n        ).first()\n\n    @property\n    def latest_major_public_revision(self):\n        return self.page.translations.filter(\n            language=self.language,\n            status=status.PUBLIC,\n            minor_edit=False,\n        ).first()\n\n    @property\n    def previous_revision(self):\n        version = self.version - 1\n        return self.page.translations.filter(\n            language=self.language,\n            version=version,\n        ).first()\n\n    @property\n    def is_outdated(self):\n        source_translation = self.source_translation\n        # If self.language is the root language, this translation can never be outdated\n        if not source_translation:\n            return False\n        # If the source translation is outdated, this translation can not be up to date\n        if source_translation.is_outdated:\n            return True\n        self_revision = self.latest_major_public_revision\n        source_revision = source_translation.latest_major_public_revision\n        # If on of the translations has no major public revision, it cannot be outdated\n        if not self_revision or not source_revision:\n            return False\n        return self_revision.last_updated < source_revision.last_updated\n\n    @property\n    def combined_text(self):\n        \"\"\"\n        Combines the text from the PageTranslation with the text from the mirrored page.\n        \"\"\"\n        if self.page.mirrored_page_first:\n            return self.page.get_mirrored_text(self.language.code) + self.text\n        return self.text + self.page.get_mirrored_text(self.language.code)\n\n    def __str__(self):\n        if self.id:\n            return '(id: {}, lang: {}, slug: {})'.format(self.id, self.language.code, self.slug)\n        return super(PageTranslation, self).__str__()\n\n    class Meta:\n        ordering = ['page', '-version']\n        default_permissions = ()\n", "path": "backend/cms/models/pages/page_translation.py"}], "after_files": [{"content": "\"\"\"Views related to the statistics module\"\"\"\nfrom django.contrib.auth.decorators import login_required\nfrom django.utils.decorators import method_decorator\nfrom django.views.generic import TemplateView\nfrom django.shortcuts import render\n\nfrom ...models import PageTranslation, Region\nfrom ...decorators import region_permission_required\n\n\n@method_decorator(login_required, name='dispatch')\n@method_decorator(region_permission_required, name='dispatch')\nclass TranslationCoverageView(TemplateView):\n    \"\"\"\n    Class to create the translation coverage statistic\n    \"\"\"\n    template_name = 'analytics/translation_coverage.html'\n    base_context = {'current_menu_item': 'translation_coverage'}\n\n    def get(self, request, *args, **kwargs):\n\n        region = Region.get_current_region(request)\n        num_pages = region.pages.count()\n        languages = []\n\n        for language in region.languages:\n            page_translations = PageTranslation.get_translations(region, language)\n            languages.append({\n                'translated_name': language.translated_name,\n                'num_page_translations_up_to_date': len([t for t in page_translations if not t.is_outdated]),\n                'num_page_translations_outdated': len([t for t in page_translations if t.is_outdated]),\n                'num_page_translations_missing': num_pages - page_translations.count()\n            })\n\n        return render(\n            request,\n            self.template_name,\n            {\n                **self.base_context,\n                'languages': languages\n            }\n        )\n", "path": "backend/cms/views/analytics/translation_coverage_view.py"}, {"content": "\"\"\"Models representing a page and page translation with content\n\"\"\"\nimport logging\n\nfrom django.conf import settings\nfrom django.db import models\nfrom django.utils import timezone\n\nfrom .page import Page\nfrom ..languages.language import Language\nfrom ...constants import status\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass PageTranslation(models.Model):\n    \"\"\"Class defining a Translation of a Page\n\n    Args:\n        models : Class inherit of django-Models\n    \"\"\"\n\n    page = models.ForeignKey(Page, related_name='translations', on_delete=models.CASCADE)\n    language = models.ForeignKey(\n        Language,\n        related_name='page_translations',\n        on_delete=models.CASCADE\n    )\n    slug = models.SlugField(max_length=200, blank=True, allow_unicode=True)\n    title = models.CharField(max_length=250)\n    text = models.TextField(blank=True)\n    status = models.CharField(max_length=6, choices=status.CHOICES, default=status.DRAFT)\n    currently_in_translation = models.BooleanField(default=False)\n    version = models.PositiveIntegerField(default=0)\n    minor_edit = models.BooleanField(default=False)\n    creator = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL)\n    created_date = models.DateTimeField(default=timezone.now)\n    last_updated = models.DateTimeField(auto_now=True)\n\n    @property\n    def foreign_object(self):\n        return self.page\n\n    @property\n    def ancestor_path(self):\n        return '/'.join([\n            ancestor.get_first_translation([self.language.code]).slug\n            for ancestor in self.page.get_ancestors()\n        ])\n\n    @property\n    def permalink(self):\n        return '/'.join(filter(None, [\n            self.page.region.slug,\n            self.language.code,\n            self.ancestor_path,\n            self.slug\n        ]))\n\n    @property\n    def available_languages(self):\n        languages = self.page.languages\n        languages.remove(self.language)\n        available_languages = {}\n        for language in languages:\n            other_translation = self.page.get_public_translation(language.code)\n            if other_translation:\n                available_languages[language.code] = {\n                    'id': other_translation.id,\n                    'url': other_translation.permalink\n                }\n        return available_languages\n\n    @property\n    def source_translation(self):\n        source_language_tree_node = self.page.region.language_tree_nodes.get(language=self.language).parent\n        if source_language_tree_node:\n            return self.page.get_translation(source_language_tree_node.code)\n        return None\n\n    @property\n    def latest_public_revision(self):\n        return self.page.translations.filter(\n            language=self.language,\n            status=status.PUBLIC,\n        ).first()\n\n    @property\n    def latest_major_revision(self):\n        return self.page.translations.filter(\n            language=self.language,\n            minor_edit=False,\n        ).first()\n\n    @property\n    def latest_major_public_revision(self):\n        return self.page.translations.filter(\n            language=self.language,\n            status=status.PUBLIC,\n            minor_edit=False,\n        ).first()\n\n    @property\n    def previous_revision(self):\n        version = self.version - 1\n        return self.page.translations.filter(\n            language=self.language,\n            version=version,\n        ).first()\n\n    @property\n    def is_outdated(self):\n        source_translation = self.source_translation\n        # If self.language is the root language, this translation can never be outdated\n        if not source_translation:\n            return False\n        # If the source translation is outdated, this translation can not be up to date\n        if source_translation.is_outdated:\n            return True\n        self_revision = self.latest_major_public_revision\n        source_revision = source_translation.latest_major_public_revision\n        # If one of the translations has no major public revision, it cannot be outdated\n        if not self_revision or not source_revision:\n            return False\n        return self_revision.last_updated < source_revision.last_updated\n\n    @property\n    def combined_text(self):\n        \"\"\"\n        Combines the text from the PageTranslation with the text from the mirrored page.\n        \"\"\"\n        if self.page.mirrored_page_first:\n            return self.page.get_mirrored_text(self.language.code) + self.text\n        return self.text + self.page.get_mirrored_text(self.language.code)\n\n    @classmethod\n    def get_translations(cls, region, language):\n        return cls.objects.filter(page__region=region, language=language).distinct('page')\n\n    @classmethod\n    def get_outdated_translations(cls, region, language):\n        return [t for t in cls.objects.filter(page__region=region, language=language).distinct('page') if t.is_outdated]\n\n    @classmethod\n    def get_up_to_date_translations(cls, region, language):\n        return [t for t in cls.objects.filter(page__region=region, language=language).distinct('page') if not t.is_outdated]\n\n    def __str__(self):\n        if self.id:\n            return '(id: {}, page_id: {}, lang: {}, version: {}, slug: {})'.format(self.id, self.page.id, self.language.code, self.version, self.slug)\n        return super(PageTranslation, self).__str__()\n\n    class Meta:\n        ordering = ['page', '-version']\n        default_permissions = ()\n", "path": "backend/cms/models/pages/page_translation.py"}]}