wbwriter 1.46.13__py2.py3-none-any.whl → 1.47.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of wbwriter might be problematic. Click here for more details.

@@ -0,0 +1,24 @@
1
+ # Generated by Django 5.0.12 on 2025-03-03 10:28
2
+
3
+ import modeltrans.fields
4
+ from django.db import migrations
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('wbwriter', '0011_auto_20240103_0953'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name='article',
16
+ name='i18n',
17
+ field=modeltrans.fields.TranslationField(fields=['title', 'content', 'slug'], required_languages=(), virtual_fields=True),
18
+ ),
19
+ migrations.AddField(
20
+ model_name='publication',
21
+ name='i18n',
22
+ field=modeltrans.fields.TranslationField(fields=['title', 'slug', 'content'], required_languages=(), virtual_fields=True),
23
+ ),
24
+ ]
@@ -2,6 +2,7 @@ import datetime
2
2
  import json
3
3
  import re
4
4
  from contextlib import suppress
5
+ from copy import deepcopy
5
6
  from datetime import date, timedelta
6
7
 
7
8
  from celery import shared_task
@@ -14,10 +15,12 @@ from django.db.models import Count, Max, OuterRef, Subquery
14
15
  from django.db.models.functions import Coalesce
15
16
  from django_fsm import FSMField, transition
16
17
  from dynamic_preferences.registries import global_preferences_registry
18
+ from modeltrans.fields import TranslationField
17
19
  from rest_framework.reverse import reverse
18
20
  from slugify import slugify
19
21
  from wbcore.contrib.directory.models import Person
20
22
  from wbcore.contrib.documents.models import Document, DocumentType
23
+ from wbcore.contrib.i18n.translation import translate_string
21
24
  from wbcore.contrib.icons import WBIcon
22
25
  from wbcore.contrib.notifications.dispatch import send_notification
23
26
  from wbcore.contrib.notifications.utils import create_notification_type
@@ -418,6 +421,17 @@ class Article(TagModelMixin, PublishableMixin, WBModel):
418
421
  null=False,
419
422
  )
420
423
 
424
+ i18n = TranslationField(fields=["title", "content", "slug"])
425
+
426
+ def _translate_content(self, to_language: str) -> dict:
427
+ new_content = deepcopy(self.content)
428
+ for section_key in new_content.get("sections", {}):
429
+ for content_key, content_value in new_content["sections"][section_key]["content"].items():
430
+ new_content["sections"][section_key]["content"][content_key] = translate_string(
431
+ content_value, to_language
432
+ )
433
+ return new_content
434
+
421
435
  type = models.ForeignKey(
422
436
  "wbwriter.ArticleType",
423
437
  related_name="article",
@@ -1074,7 +1088,7 @@ class Article(TagModelMixin, PublishableMixin, WBModel):
1074
1088
  template_context["content"] = f"""
1075
1089
  <p>To generate the PDF, please correct the following errors:</p>
1076
1090
  <ul>
1077
- {''.join([f'<li>{error}</li>' for error in parser.errors])}
1091
+ {"".join([f"<li>{error}</li>" for error in parser.errors])}
1078
1092
  </ul>
1079
1093
  """
1080
1094
  html = template.Template(empty_template).render(template_context)
@@ -5,6 +5,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey
5
5
  from django.contrib.contenttypes.models import ContentType
6
6
  from django.db import models
7
7
  from django.utils.functional import cached_property
8
+ from modeltrans.fields import TranslationField
8
9
  from rest_framework.reverse import reverse
9
10
  from slugify import slugify
10
11
  from wbcore.contrib.tags.models import TagModelMixin
@@ -62,6 +63,8 @@ class Publication(TagModelMixin, models.Model):
62
63
  null=True,
63
64
  )
64
65
 
66
+ i18n = TranslationField(fields=["title", "slug", "content"])
67
+
65
68
  parser = models.ForeignKey(
66
69
  "wbwriter.PublicationParser",
67
70
  related_name="parsed_publication",
@@ -58,7 +58,10 @@ class DependantArticleModelSerializer(ModelSerializer):
58
58
  )
59
59
 
60
60
 
61
- class ArticleModelSerializer(TagSerializerMixin, ModelSerializer):
61
+ from wbcore.contrib.i18n.serializers.mixins import ModelTranslateSerializerMixin
62
+
63
+
64
+ class ArticleModelSerializer(ModelTranslateSerializerMixin, TagSerializerMixin, ModelSerializer):
62
65
  """Serializes a subset of the fields of of the Article model to minimize
63
66
  workload on serializing lists of instances.
64
67
  """
@@ -81,7 +84,7 @@ class ArticleModelSerializer(TagSerializerMixin, ModelSerializer):
81
84
  @register_resource()
82
85
  def metainformationinstance(self, instance, request, user):
83
86
  return {
84
- "metainformationinstance": f'{reverse("wbwriter:metainformationinstancearticle-list", args=[instance.id], request=request)}',
87
+ "metainformationinstance": f"{reverse('wbwriter:metainformationinstancearticle-list', args=[instance.id], request=request)}",
85
88
  }
86
89
 
87
90
  @register_resource()
@@ -162,6 +165,7 @@ class ArticleModelSerializer(TagSerializerMixin, ModelSerializer):
162
165
  "tags",
163
166
  "_tags",
164
167
  "_additional_resources",
168
+ "_i18n",
165
169
  )
166
170
 
167
171
 
@@ -357,4 +361,5 @@ class ArticleFullModelSerializer(ArticleModelSerializer):
357
361
  "tags",
358
362
  "_tags",
359
363
  "_additional_resources",
364
+ "_i18n",
360
365
  )
@@ -556,7 +556,11 @@ class TestArticleCloning:
556
556
  del article_clone_dict["teaser_image"]
557
557
  article_dict["name"] += "_clone"
558
558
  article_dict["slug"] += "-clone"
559
+ article_dict["slug_en_us"] += "-clone"
560
+ article_dict["slug_i18n"] += "-clone"
559
561
  article_dict["title"] += " (Clone)"
562
+ article_dict["title_i18n"] += " (Clone)"
563
+ article_dict["title_en_us"] += " (Clone)"
560
564
  article_dict["author"] = user.profile.id
561
565
  assert article_dict == article_clone_dict
562
566
  assert Article.objects.count() == 4
@@ -8,6 +8,7 @@ from rest_framework.response import Response
8
8
  from reversion.views import RevisionMixin
9
9
  from wbcore.contrib.authentication.authentication import JWTCookieAuthentication
10
10
  from wbcore.contrib.directory.models import Person
11
+ from wbcore.contrib.i18n.viewsets import ModelTranslateMixin
11
12
  from wbcore.utils.views import CloneMixin
12
13
  from wbcore.viewsets import ModelViewSet, RepresentationViewSet
13
14
 
@@ -99,7 +100,9 @@ class ArticleInstancePermissionMixin:
99
100
  return False
100
101
 
101
102
 
102
- class ArticleModelViewSet(ArticleInstancePermissionMixin, CloneMixin, RevisionMixin, ModelViewSet):
103
+ class ArticleModelViewSet(
104
+ ModelTranslateMixin, ArticleInstancePermissionMixin, CloneMixin, RevisionMixin, ModelViewSet
105
+ ):
103
106
  # LIST_DOCUMENTATION = "wbwriter/viewsets/documentation/article.md"
104
107
 
105
108
  serializer_class = ArticleFullModelSerializer
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wbwriter
3
- Version: 1.46.13
3
+ Version: 1.47.0
4
4
  Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
5
5
  Requires-Dist: pillow==9.1.*
6
6
  Requires-Dist: reportlab==3.*
@@ -16,20 +16,21 @@ wbwriter/migrations/0001_initial_squashed_squashed_0008_alter_article_author_alt
16
16
  wbwriter/migrations/0009_dependantarticle.py,sha256=OCxWFj68ToPelJJ_Hlrt3PXZy56zvup8YWpCoAjU62g,1314
17
17
  wbwriter/migrations/0010_alter_article_options.py,sha256=S2CVb5wVXHpwok3gehyedMrZMVbwj75m6LkrVg5dhv8,520
18
18
  wbwriter/migrations/0011_auto_20240103_0953.py,sha256=UnaHFJM7DVOSEfS0wm8rWEh9H2_wDcmKPYFRJYIx1Gs,1321
19
+ wbwriter/migrations/0012_i18n.py,sha256=24cClx1sWYh-VEo-IApTiSr5nNvV1CtINiaWRHFztMA,724
19
20
  wbwriter/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
21
  wbwriter/models/__init__.py,sha256=opUUL36nRzxJypQNupPM8NxUj-u4uuB11IDn5XSkjVE,248
21
- wbwriter/models/article.py,sha256=TztDqKHhRvMzFuQ-K7TNEH2wIvXnjI5OGCf1sqnbBcI,44451
22
+ wbwriter/models/article.py,sha256=lclDk1T0P-4GTpmq1ki2PDlbTvprIjQisVqGqMKuTeE,45109
22
23
  wbwriter/models/article_type.py,sha256=hofB200Y11LFanpICNgWYDa5-Qg-K4X2fXv6qccBP_0,1999
23
24
  wbwriter/models/block.py,sha256=tn2sklo7s401Y0Ww5M09Y9Wv-yivEvAR1eM5raG7gtc,835
24
25
  wbwriter/models/block_parameter.py,sha256=bHBp9bo5EEiZKTzhYfBwkidcS6kZVy81vtcAlx7xzck,524
25
26
  wbwriter/models/in_editor_template.py,sha256=1LqnxkAw9Iyh8EmjWnf3O3TUmneng0Zp4OTFpGgSphg,3411
26
27
  wbwriter/models/meta_information.py,sha256=8Ipozrv8ndsBUZKIAc-Qcg57xr5IMpjfoSG-DbL_0qQ,3020
27
28
  wbwriter/models/mixins.py,sha256=-1P0bQCS76H2D8Mj1Bwhzv3KsNwnkts9f75lGUrcxFU,249
28
- wbwriter/models/publication_models.py,sha256=u7JHwnsIcrGxqgwsY6WqyDSuOtz5FUy3NYspMKCAPBc,5180
29
+ wbwriter/models/publication_models.py,sha256=k6lmyEux7GegtSmBn-X7xXfrFZRASkahXxYt9S1EFuA,5293
29
30
  wbwriter/models/style.py,sha256=b-CnU9K5D6adePdz4LpCdwXjK2750V3QnFv39wK-JLA,262
30
31
  wbwriter/models/template.py,sha256=i6b_qmkUJIbrFqNaeld3gSjR7GLeU-EfKJiPsfjFA_Y,928
31
32
  wbwriter/serializers/__init__.py,sha256=zPzGMOsxp8yEZ5m2sATEeqlZaktNWbXCx8oZefeiCa4,828
32
- wbwriter/serializers/article.py,sha256=PbBL7BMgy9D2USWCGxt15eOd7pv-EHZ6jykh8gWWu78,13495
33
+ wbwriter/serializers/article.py,sha256=m5lYQP4J7rn_ZNMnyi69IPYs2HTt7tSlYoXmXuKbcrU,13651
33
34
  wbwriter/serializers/article_type.py,sha256=VmMVI0dreuX83GtwtzD0n3-tvmNMnbtc2KIqjAB7beI,426
34
35
  wbwriter/serializers/in_editor_template.py,sha256=hZ0icXVJtiipFSzY3cF0p6X4_0XaKdeMYwjUhgPoDLI,1032
35
36
  wbwriter/serializers/meta_information.py,sha256=zMNU6WYXJVO5L29Depm6FB-FnFMrnAttRI32PmNpt3w,2046
@@ -44,11 +45,11 @@ wbwriter/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
45
  wbwriter/tests/conftest.py,sha256=1vehReFFD4YZHYbOeCEFIuufIeC1QmbUV0mS4VmAXKU,982
45
46
  wbwriter/tests/signals.py,sha256=ay1kQIaHT7a_kymGimdq1MWj_8UjNqlYW-oyN13WK6c,989
46
47
  wbwriter/tests/test_filter.py,sha256=dhXiMsjSkwsTdsHMZt2cUt3QzCECvKgN3te5DLee5qM,2663
47
- wbwriter/tests/test_model.py,sha256=pOdwMkgvEL8kWnT6QT4xCn7GU_jxxL5xgorg5F8jrLk,29216
48
+ wbwriter/tests/test_model.py,sha256=kTz68WYfR65x8G9UCXbRRswwQVIPNCQFHRLso-XEd_k,29408
48
49
  wbwriter/tests/test_writer.py,sha256=XRmfaH-o4ItekFjw1dnIyMzw7veTCw6KH_PouQgFRRQ,1584
49
50
  wbwriter/tests/tests.py,sha256=9quRn44Xi1XIKKIXKCBRmtSpARJowjm7_Edw40Mutdw,332
50
51
  wbwriter/viewsets/__init__.py,sha256=FSoHcwxYukis44flBOwKaoa6fABkNI66lzaTXaYEZxk,722
51
- wbwriter/viewsets/article.py,sha256=virp7CYjVaeAabzvAezMq7SxyWd4x2EfoOh0Nk8qoh0,9706
52
+ wbwriter/viewsets/article.py,sha256=hVMRnRpmafv2rpGRQi1d9wvaPP1499XvLnKivJMpTNk,9794
52
53
  wbwriter/viewsets/article_type.py,sha256=wEeJXy3uPav0ZrV3sD1UHEpKdH37ZjwssKeNfaJJV4s,1503
53
54
  wbwriter/viewsets/buttons.py,sha256=6ClY6ddqiPheulgz2j_kw80YqjMgXBt1G4_sSiYE-Tg,2844
54
55
  wbwriter/viewsets/in_editor_template.py,sha256=6ocFTerOYKrAoVTXKI8yEaDInGVpgiyI0tl1E4otusY,1713
@@ -70,6 +71,6 @@ wbwriter/viewsets/endpoints/meta_information.py,sha256=m7rVbfTNjsQNibmqtAG4DvXSJ
70
71
  wbwriter/viewsets/titles/__init__.py,sha256=INLTvGeBi5Xro7i3FlJ2fesh-TjKbxRBlfsAyeg3h7k,131
71
72
  wbwriter/viewsets/titles/publication_title_config.py,sha256=-39C_Enz8J1o-DWgRz89VFMV0r4MReKx-r-Tpf9MlVM,807
72
73
  wbwriter/viewsets/titles/reviewer_article_title_config.py,sha256=YzRjuUwbe6vBwWhYLrCe6woGCpQ9c7AwkujKqPh5mLw,183
73
- wbwriter-1.46.13.dist-info/METADATA,sha256=M4UZimxSYcUtgVhukgKGXRf8_ELy-wRGESXMu4Imh6I,231
74
- wbwriter-1.46.13.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
75
- wbwriter-1.46.13.dist-info/RECORD,,
74
+ wbwriter-1.47.0.dist-info/METADATA,sha256=vkX7rfOmtCjmC8xrGZa0WrOvL3Hk45KyJ-zoGYB8W_k,230
75
+ wbwriter-1.47.0.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
76
+ wbwriter-1.47.0.dist-info/RECORD,,