Skip to content

Commit

Permalink
✨ (core): Added simply register of fields for translation
Browse files Browse the repository at this point in the history
  • Loading branch information
dd committed Jul 2, 2023
1 parent a3798af commit 195bd02
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 71 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -69,9 +69,8 @@ Refactoring old functionality and getting rid of unnecessary
* [x] Testing
* [x] Abstract model with publishing flag
* [x] Abstract model with the functionality of publishing in a certain period
* [ ] Universal manager worked with all abstract models
* i18n
* [ ] Field translation simplification functionality when using [django-modeltranslation](https://django-modeltranslation.readthedocs.io/en/latest/)
* [x] Field translation simplification functionality when using [django-modeltranslation](https://django-modeltranslation.readthedocs.io/en/latest/)
* [x] Localization of all texts in the library
* utils
* [x] Method and template tag for getting date range
Expand All @@ -85,6 +84,7 @@ Refactoring old functionality and getting rid of unnecessary

Adding new functionality. Can change.

* Universal manager worked with all abstract models
* Tests of all functionality
* Methods for encrypting and decrypting text content (To create various secrets, such as a link to change your password or activate your profile).
* Functionality for obtaining absolute links to resources presented on the front, located on another domain (When working through api) (utils methods, template tags and filters).
Expand Down
13 changes: 13 additions & 0 deletions docs/src/usage/core.md
Expand Up @@ -113,6 +113,19 @@ An abstract model that adds a sortable field, as well as a manager with sorting
show_source: false


## Translations

If you use [djano-modeltranslation](https://django-modeltranslation.readthedocs.io/en/latest/), then when connecting `meringue.core`, you can register fields for translations by setting the list of fields in the `m_translate_fields` field in the meta of the corresponding model:

```py
class FooModel(models.Model):
name = models.CharField(max_length=32)

class Meta:
m_translate_fields = ["name", ]
```


## Views


Expand Down
2 changes: 2 additions & 0 deletions meringue/core/__init__.py
@@ -1,5 +1,7 @@
import django

from meringue.core import options # nowa: F401


if django.VERSION < (3, 2):
default_app_config = "meringue.core.apps.Config"
2 changes: 1 addition & 1 deletion meringue/core/options.py
Expand Up @@ -3,5 +3,5 @@

options.DEFAULT_NAMES = (
*options.DEFAULT_NAMES,
"translate_fields",
"m_translate_fields",
)
2 changes: 1 addition & 1 deletion meringue/core/tests/test_teapots.py
Expand Up @@ -4,7 +4,7 @@

def test_check_teapot():
"""
Nominal mixin check
Im a teapot
"""
client = Client()
response = client.get(reverse("make_coffee"))
Expand Down
12 changes: 12 additions & 0 deletions meringue/core/tests/test_translation.py
@@ -0,0 +1,12 @@
from test_project.models import TranslatedModel


def test_translate_fields():
"""
Checking the registration of fields for translation
"""

instance = TranslatedModel()
assert hasattr(instance, "name")
assert hasattr(instance, "name_ru")
assert hasattr(instance, "name_en")
55 changes: 11 additions & 44 deletions meringue/core/translation.py
@@ -1,51 +1,18 @@
from importlib import import_module

from django.apps import apps
from django.conf import settings

from modeltranslation.translator import TranslationOptions
from modeltranslation.translator import translator


try:
from polymorphic.utils import get_base_polymorphic_model
except ImportError:
pass
else:
for app in settings.INSTALLED_APPS:
try:
models = import_module("%s.models" % app)
except ImportError:
bits = app.split(".")
app_name = import_module(bits[0])

for bit in bits[1:]:
app_name = getattr(app_name, bit)

if hasattr(app_name, "name"):
try:
models = import_module("%s.models" % app_name.name)
except ImportError:
continue
else:
continue

except AttributeError:
continue

for model in apps.get_models():
fields = getattr(model._meta, "translate_fields", [])
force = False

if not fields and get_base_polymorphic_model and get_base_polymorphic_model(model):
force = True
for model in apps.get_models():
fields = getattr(model._meta, "m_translate_fields", [])

if (fields or force) and model not in translator.get_registered_models():
translator.register(
model,
type(
str(model.__name__ + "Translation"),
(TranslationOptions,),
{"fields": fields},
),
)
if fields and model not in translator.get_registered_models():
translator.register(
model,
type(
str(model.__name__ + "Translation"),
(TranslationOptions,),
{"fields": fields},
),
)
29 changes: 16 additions & 13 deletions pyproject.toml
Expand Up @@ -125,7 +125,7 @@ description = "Lint environment"
detached = true
python = "3.11"
dependencies = [
"ruff==0.0.272",
"ruff==0.0.275",
"black==23.3.0",
]
[tool.hatch.envs.lint.scripts]
Expand All @@ -149,6 +149,7 @@ dependencies = [
"Faker==18.11.1",
"django==4.2",
"pytz==2023.3",
"django-modeltranslation==0.18.10",
]
[tool.hatch.envs.test.env-vars]
DJANGO_SETTINGS_MODULE = 'test_project.settings'
Expand All @@ -169,6 +170,7 @@ dependencies = [
[tool.hatch.envs.mtest.overrides]
matrix.django.dependencies = [
{ value = "django~={matrix:django}" },
{ value = "django-modeltranslation=={matrix:modeltranslation}" },
]
[tool.hatch.envs.mtest.env-vars]
DJANGO_SETTINGS_MODULE = 'test_project.settings'
Expand All @@ -177,7 +179,12 @@ PYTHONPATH = '.'
check = "pytest {args:-q}"
[[tool.hatch.envs.mtest.matrix]]
python = ["3.8", "3.9", "3.10", "3.11"]
django = ["2.0", "3.0", "4.0"]
django = ["2.0"]
modeltranslation = ["0.17.7"]
[[tool.hatch.envs.mtest.matrix]]
python = ["3.8", "3.9", "3.10", "3.11"]
django = ["3.0", "4.0"]
modeltranslation = ["0.18.10"]

[tool.hatch.envs.docs]
description = "Docs environment"
Expand All @@ -186,7 +193,7 @@ python = "3.11"
dependencies = [
"mkdocs[i18n]==1.4.3",
"mkdocs-literate-nav==0.6.0",
"mkdocs-material==9.1.15",
"mkdocs-material==9.1.17",
"mkdocs-git-revision-date-localized-plugin==1.2.0",
"mkdocs-git-authors-plugin==0.7.2",
"mkdocstrings[python]==0.22.0",
Expand Down Expand Up @@ -238,14 +245,15 @@ select = [
"YTT",
]
ignore = [
"RUF001", # Allow similar characters like latin `c` and cyrillic `с`
"RUF002", # Allow russian at docstrings
"RUF003", # Allow russian at comment
"FBT001", # Allow boolean args
"FBT002", # Allow boolean positional argument define
"FBT003", # Allow boolean positional values in function calls, like `dict.get(... True)`
"PLR0913", # Allow any number of function arguments
# # Allow non-abstract empty methods in abstract base classes
# "B027",
# # Allow boolean positional values in function calls, like `dict.get(... True)`
# "FBT003",
# # Ignore checks for possible passwords
# "S105", "S106", "S107",
# # Ignore complexity
Expand All @@ -259,28 +267,23 @@ ignore = [
# "F401",
# ]
[tool.ruff.extend-per-file-ignores]
"__init__.py" = ["F403"]
"__init__.py" = ["F401", "F403"]
"test_*.py" = ["S101", "PLR2004"]
"*/migrations/*" = ["I", "E", "Q"]

"*/migrations/*" = ["I", "E", "Q", "RUF"]
"test_project/*models.py" = ["RUF012"]
[tool.ruff.flake8-import-conventions]

[tool.ruff.flake8-import-conventions.extend-aliases]
"datetime" = "dt"

# [tool.ruff.flake8-quotes]
# inline-quotes = "single"

[tool.ruff.flake8-unused-arguments]
ignore-variadic-names = true

[tool.ruff.isort]
force-single-line = true
known-first-party = ["meringue"]
lines-after-imports = 2
no-lines-before = ["local-folder"]
section-order = ["future", "standard-library", "django", "third-party", "first-party", "local-folder"]

[tool.ruff.isort.sections]
django = ["django"]

Expand Down
22 changes: 17 additions & 5 deletions test_project/migrations/0001_initial.py
@@ -1,4 +1,4 @@
# Generated by Django 4.2 on 2023-06-24 14:41
# Generated by Django 4.2 on 2023-06-26 00:26

from django.db import migrations, models

Expand All @@ -17,7 +17,7 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ctime', models.DateTimeField(auto_now_add=True, help_text='Date and time of creation.')),
('mtime', models.DateTimeField(auto_now=True, help_text='Date and time of editing.')),
('title', models.CharField(max_length=10)),
('title', models.CharField(max_length=32)),
],
options={
'abstract': False,
Expand All @@ -29,7 +29,7 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date_from', models.DateTimeField(blank=True, help_text='Date and time of publication (inclusive).', null=True, verbose_name='Date from')),
('date_to', models.DateTimeField(blank=True, help_text='Date and time when to hide.', null=True, verbose_name='Date to')),
('title', models.CharField(max_length=10)),
('title', models.CharField(max_length=32)),
],
options={
'abstract': False,
Expand All @@ -40,7 +40,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_published', models.BooleanField(db_index=True, default=True, help_text='Show/Hide', verbose_name='Publication')),
('title', models.CharField(max_length=10)),
('title', models.CharField(max_length=32)),
],
options={
'abstract': False,
Expand All @@ -51,11 +51,23 @@ class Migration(migrations.Migration):
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('sorting', models.SmallIntegerField(default=0, help_text='Sorting order.', verbose_name='Sorting')),
('title', models.CharField(max_length=10)),
('title', models.CharField(max_length=32)),
],
options={
'ordering': ['sorting'],
'abstract': False,
},
),
migrations.CreateModel(
name='TranslatedModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32)),
('name_ru', models.CharField(max_length=32, null=True)),
('name_en', models.CharField(max_length=32, null=True)),
],
options={
'm_translate_fields': ['name'],
},
),
]
17 changes: 13 additions & 4 deletions test_project/models.py
Expand Up @@ -7,16 +7,25 @@


class CMTimeModel(CMTimeMixin):
title = models.CharField(max_length=10)
title = models.CharField(max_length=32)


class SortingModel(SortingMixin):
title = models.CharField(max_length=10)
title = models.CharField(max_length=32)


class PublicationModel(PublicationMixin):
title = models.CharField(max_length=10)
title = models.CharField(max_length=32)


class PublicationDatesModel(PublicationDatesMixin):
title = models.CharField(max_length=10)
title = models.CharField(max_length=32)


class TranslatedModel(models.Model):
name = models.CharField(max_length=32)

class Meta:
m_translate_fields = [
"name",
]
12 changes: 11 additions & 1 deletion test_project/settings.py
Expand Up @@ -13,6 +13,7 @@
# 'django.contrib.sessions',
# 'django.contrib.messages',
# 'django.contrib.staticfiles',
"modeltranslation",
"test_project",
"meringue.core",
]
Expand Down Expand Up @@ -82,7 +83,6 @@
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/

# LANGUAGE_CODE = 'en-us'

TIME_ZONE = "UTC"

Expand All @@ -102,4 +102,14 @@
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"


LANGUAGE_CODE = "ru"


gettext = lambda s: s # noqa:E731
LANGUAGES = (
("ru", gettext("Russian")),
("en", gettext("English")),
)


MERINGUE = {}

0 comments on commit 195bd02

Please sign in to comment.