bru*_*tas 5 python django django-modeltranslation
一段时间以来,我一直在使用django-modeltranslation来翻译 django 中的模型。它非常简单,并且在我一直在开发的应用程序上运行良好,其中所有模型翻译的内容都由最终用户插入表单。
例如:输入:内容,content_en,content_pt,...
我必须构建一个应用程序,我需要在其中翻译由 django 生成的“内置”模型字符串,例如“auth.permission.name”或“contenttypes.contenttype.name” ,并将它们添加到翻译 django.po 文件中。
它使用 post_migration 信号创建一个包含 ugettext_lazy 元素列表的文件,因此新字符串(例如新的 contenttype.name)被动态添加到 'django.po' 并加载到数据库中。
为了注册字符串,但我没有找到另一种注册方法并将它们动态添加到 django.po 文件中,所以我需要你的帮助
这是我所做的:
1.我创建了一个名为“tools”的应用程序,它是 INSTALLED_APPS 上的最后一个,所以它的迁移自然是最后一个被调用的。这个应用程序没有任何模型,它只是运行迁移,有 django-modeltranslation translation.py 文件和一个带有 post_migration 信号调用的应用程序配置。
# translations.py
from modeltranslation.translator import translator, TranslationOptions
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
class PermissionTranslationOptions(TranslationOptions):
fields = ('name',)
class ContentTypeTranslationOptions(TranslationOptions):
fields = ('name',)
translator.register(Permission, PermissionTranslationOptions)
translator.register(ContentType, ContentTypeTranslationOptions)
Run Code Online (Sandbox Code Playgroud)
2.运行 ' manage.py makemigrations ' 使用额外的 'name_*' 字段在 'auth' 和 'contenttypes' 应用程序上创建迁移。
3.应用程序有一个带有 post_migrate 信号的应用程序配置
# __init__.py
default_app_config = 'apps.tools.config.SystemConfig'
Run Code Online (Sandbox Code Playgroud)
# config.py
from django.apps import AppConfig
from django.db.models.signals import post_migrate
from apps.tools.translations.exporter import make_translations
from apps.tools.translations.importer import load_translations
def run_translations(sender, **kwargs):
# This creates the translations
make_translations()
# This loads the the translations to the db
load_translations()
class SystemConfig(AppConfig):
name = 'apps.tools'
verbose_name = 'Tools'
def ready(self):
# Call post migration operations
post_migrate.connect(run_translations, sender=self)
Run Code Online (Sandbox Code Playgroud)
4. make_translations() 在迁移后被调用并生成一个包含 uggettext_lazy 调用列表的文件。
这是我想改变的一点。我真的需要创建一个文件吗?
# exporter
import os
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.utils import translation
from django.contrib.contenttypes.management import update_all_contenttypes
# TODO
# It has got to be another way
def make_translations():
# lets go default
translation.activate("en")
update_all_contenttypes()
try:
f = open(os.path.join(os.path.realpath(os.path.dirname(__file__)), 'translations.py'), 'w')
# Write file
f.write("from django.utils.translation import ugettext_lazy as _\n\n")
# All Permissions to lazy text
f.write('permissions = {\n')
for perm in Permission.objects.all().order_by('id'):
f.write(' "'+str(perm.id)+'": _("'+perm.name+'"),\n')
f.write('}\n\n')
# All Content types to lazy text
f.write('content_types = {\n')
for content in ContentType.objects.all().order_by('id'):
f.write(' "'+str(content.id)+'": _("'+content.name+'"),\n')
f.write('}\n\n')
# Closing file
f.close()
# Importing file to get it registered with ugettext_lazy
try:
from apps.tools.translations import translations
except:
print('Could not import file')
pass
except:
print('Could not create file')
pass
Run Code Online (Sandbox Code Playgroud)
上面的结果是这样的文件:
from django.utils.translation import ugettext_lazy as _
permissions = {
"1": _("Can add permission"),
"2": _("Can change permission"),
"3": _("Can delete permission"),
"4": _("Can add group"),
...
}
content_types = {
"1": _("group"),
"2": _("user"),
"3": _("permission"),
"4": _("content type"),
"5": _("session"),
...
}
Run Code Online (Sandbox Code Playgroud)
5.运行'makemessages'会将这个字符串添加到'django.po'文件中,但是post_migration信号并没有停在这里,而是加载数据库中现有的编译字符串
# importer
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from django.utils import translation
def load_translations():
try:
from apps.tools.translations.translations import permissions, content_types
except:
# File does not exists
print('Translations could not be loaded')
return
# For each language
for lang in settings.LANGUAGES:
# Activate language
translation.activate(lang[0])
# Loading translated permissions
all_permissions = Permission.objects.all()
for permission in all_permissions:
permission.name = unicode(permissions[str(permission.id)])
permission.save()
# Loading translated content_types
all_contenttypes = ContentType.objects.all()
for contenttype in all_contenttypes:
contenttype.name = unicode(content_types[str(contenttype.id)])
contenttype.save()
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助
我读过你的帖子,不知怎的,我在权限翻译方面也遇到了同样的问题,我找到了一个非常简短的方法来解决这个问题:
但解决方案是:编辑类的此路径app_labeled_name装饰的函数,使其变为如下所示:property.pyenv/Lib/site-packages/django/contrib/contenttypes/models.pyContentType
@property
def app_labeled_name(self):
model = self.model_class()
if not model:
return self.model
return '%s | %s' % (apps.get_app_config(model._meta.app_label).verbose_name,
model._meta.verbose_name)
Run Code Online (Sandbox Code Playgroud)
技巧是使用apps.get_app_config(model._meta.app_label).verbose_name而不是model._meta.app_label,因此它将使用与应用程序子类verbose_name中为应用程序设置的任何使用相同的内容AppConfig。