跳转到主要内容

用于管理Django模型翻译的应用程序

项目描述

Build Status

django-linguist 是一个 Django 应用程序,用于灵活的模型翻译。

以下是一些定义此应用程序与其他应用程序区别的原则

  • 翻译存储在单个表中,并且您也可以为每个模型使用不同的一个

  • 没有“每个模型一个i18n表”,说“再见”给噩梦:)

  • 不再有痛苦的迁移

  • 不与模型类名绑定,您可以自由使用自己的标识符

  • 没有ORM查询技巧,它不会修补任何东西,这将使您升级Django变得更容易

  • 没有魔法,它使用元类和混入,一切都是明确的

  • 将现有项目接入非常简单

  • 已准备好Django管理界面

如果您正在寻找“每个模型一个国际化表格”的方法,django-parler 是一个不错的选择。

安装

$ pip install django-linguist

在您的 settings.py 中,将 linguist 添加到 INSTALLED_APPS

INSTALLED_APPS = (
    # Your other apps here
    'linguist',
)

然后同步数据库

# >= Django 1.7
$ python manage.py migrate linguist

# < Django 1.7
$ python manage.py syncdb

这就完了。

配置

模型

三步完成

  1. linguist.metaclasses.ModelMeta 添加到您的模型中作为元类

  2. linguist.mixins.ManagerMixin 添加到您的模型管理器

  3. 在您的模型的 Meta 中添加 linguist 设置

不用担心,这相当简单

from django.db import models
from django.utils.translation import gettext_lazy as _

from linguist.metaclasses import ModelMeta as LinguistMeta
from linguist.mixins import ManagerMixin as LinguistManagerMixin


class PostManager(LinguistManagerMixin, models.Manager):
    pass


class Post(models.Model, meta=LinguistMeta):
    title = models.CharField(max_length=255)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    objects = PostManager()

    class Meta:
        verbose_name = _('post')
        verbose_name_plural = _('posts')
        linguist = {
            'identifier': 'can-be-anything-you-want',
            'fields': ('title', 'body'),
            'default_language': 'fr',
        }

linguist 元数据需要以下内容

  • identifier:您模型的一个唯一标识符(可以是您想要的任何东西)

  • fields:要翻译的模型字段列表或元组

并且可选地需要以下内容

  • default_language:要使用的默认语言

  • default_language_field:包含要使用的默认语言的字段(见下文)

  • decider:要使用而不是默认的翻译模型(见下文)

这就完了。您准备好了。

每个实例的默认语言

有时,您需要在实例级别定义默认语言。Linguist 通过 default_language_field 选项支持此功能。在您的模型中添加一个用于存储默认语言的字段,然后简单地将该字段名称提供给 Linguist。

让我们举一个例子

from django.db import models
from django.utils.translation import gettext_lazy as _

from linguist.metaclasses import ModelMeta as LinguistMeta
from linguist.mixins import ManagerMixin as LinguistManagerMixin


class PostManager(LinguistManagerMixin, models.Manager):
    pass


class Post(models.Model, meta=LinguistMeta):
    title = models.CharField(max_length=255)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    lang = models.CharField(max_length=5, default='en')
    objects = PostManager()

    class Meta:
        verbose_name = _('post')
        verbose_name_plural = _('posts')
        linguist = {
            'identifier': 'can-be-anything-you-want',
            'fields': ('title', 'body'),
            'default_language': 'en',
            'default_language_field': 'lang',
        }

自定义翻译表

默认情况下,Linguist 将翻译存储到 linguist.models.Translation 表中。因此在一个表中。如果您需要为特定模型使用其他表,Linguist 提供了一种覆盖此行为的方法:使用 deciders

这实际上非常容易实现。

您可以在三步内完成它

  • 创建一个继承自 linguist.models.base.Translation 的模型

  • 别忘了将其定义为具体模型(在 Meta 中 abstract = False

  • 将此模型提供给 Linguist 元数据的 decider 选项

这个例子将为您带来光明

from django.db import models
from django.utils.translation import gettext_lazy as _

from linguist.metaclasses import ModelMeta as LinguistMeta
from linguist.mixins import ManagerMixin as LinguistManagerMixin
from linguist.models.base import Translation


# Our Post model decider
class PostTranslation(Translation):
    class Meta:
        abstract = False


class PostManager(LinguistManagerMixin, models.Manager):
    pass


class Post(models.Model, meta=LinguistMeta):
    title = models.CharField(max_length=255)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    objects = PostManager()

    class Meta:
        verbose_name = _('post')
        verbose_name_plural = _('posts')
        linguist = {
            'identifier': 'can-be-anything-you-want',
            'fields': ('title', 'body'),
            'default_language': 'fr',
            'decider': PostTranslation,
        }

django.contrib.admin

简单使用 linguist.admin.TranslatableModelAdmin

from django.contrib import admin
from linguist.admin import TranslatableModelAdmin
from .models import Post


class PostAdmin(TranslatableModelAdmin):
    list_display = ('title', 'body', 'created_at')

admin.site.register(Post, PostAdmin)

额外福利!您可以通过管理员类提供的 languages_column 属性在 list_display 中显示实例的语言

from django.contrib import admin
from linguist.admin import TranslatableModelAdmin
from .models import Post


class PostAdmin(TranslatableModelAdmin):
    list_display = ('title', 'body', 'languages_column', 'created_at')

admin.site.register(Post, PostAdmin)

它是如何工作的

Linguist 为您的模型添加了虚拟语言字段。对于上面的例子,如果我们有 enfritsettings.LANGUAGES 中,它将动态地在 Post 模型中添加以下字段

  • Post.title_en

  • Post.title_fr

  • Post.title_it

  • Post.body_en

  • Post.body_fr

  • Post.body_it

这些字段是虚拟的。它们不在 Post 表中。这些字段围绕 linguist.Translation 模型。所有翻译都将存储在此表中。

当您设置/获取 post.title 时,Linguist 将使用当前活动语言,并将设置/获取正确的字段。例如,如果您的默认语言是英语(en),那么 Post.title 将引用 post.title_en

ModelMixin 通过以下属性和方法增强您的模型

instance.linguist_identifier (只读属性)

您在相关翻译类中定义的模型标识符。指向 instance._linguist.identifier 的快捷方式。

instance.default_language (读写属性)

默认使用的语言。快捷方式指向 instance._linguist.default_language

instance.translatable_fields (只读属性)

在相关翻译类中定义的可翻译字段。快捷方式指向 instance._linguist.fields

instance.available_languages (只读属性)

此实例可用的语言(包含这些语言的翻译内容)。

instance.cached_translations_count (只读属性)

返回缓存的翻译数量。每次你设置新的语言并在可翻译字段上设置内容时,将为每种语言和字段创建一个缓存。它在实例保存时用于创建 Translation 对象。

instance.active_language()

设置实例的当前活动语言。

instance.clear_translations_cache()

删除所有缓存的翻译。请注意,你设置的所有内容都将被丢弃。因此,保存时不会创建/更新任何翻译。

# Let's create a new Post
>>> post = Post()

# Set English content
>>> post.activate_language('en')
>>> post.title = 'Hello'

# Now set French content
>>> post.activate_language('fr')
>>> post.title = 'Bonjour'

# Be sure everything works as expected for English
>>> post.activate_language('en')
>>> post.title
Hello

# And now for French
>>> post.activate_language('fr')
>>> post.title
Bonjour

# Sweet! Save translations!
>>> post.save()

预加载

为了提高性能,你可以预加载/预取翻译。

对于查询集(你的查询集必须继承自 Linguist 管理器/queryset)

>>> Post.objects.with_translations()

对于对象列表(所有你的对象都必须继承自 Linguist 模型)

>>> from linguist.helpers import prefetch_translations
>>> posts = list(Post.objects.all())
>>> prefetch_translations(posts)

对于实例(它必须继承自 Linguist 模型)

>>> post = Post.objects.first()
>>> post.prefetch_translations()

所有翻译都将缓存在实例中。数据库将不再被查询。

此预加载系统需要三个参数

  • field_names:要过滤的可翻译字段名称列表

  • languages:要过滤的语言列表

  • populate_missing:如果你想要填充缺失的翻译的缓存(默认为 True

  • chunks_length:翻译 SELECT IN ids 的块限制

例如,我们只想预取英文的帖子标题,而不用空字符串填充缺失的翻译

>>> Post.objects.with_translations(field_names=['title'], languages=['en'], populate_missing=False)

这对于

  • QuerySet with_translations()

  • 辅助 prefetch_translations()

  • 实例方法 prefetch_translations()

“填充缺失的翻译”是什么意思?

很简单。默认情况下,当你预取翻译时,实例缓存将用所有支持的语言(见 settings)中的空字符串填充。例如,如果你有 enfrit 作为支持的语言,并且只有英文翻译,那么如果你尝试访问其他语言,将返回空字符串而不会进行任何数据库查询。

>>> Post.objects.with_translations()
>>> post.title_fr # no database hit here because
''

现在,如果你显式将 populate_missing 设置为 False,如果找不到翻译,它将来自数据库。

>>> Post.objects.with_translations(populate_missing=False)
>>> post.title_fr # database hit here
''

开发

# Don't have pip?
$ sudo easy_install pip

# Don't already have virtualenv?
$ sudo pip install virtualenv

# Clone and install dependencies
$ git clone https://github.com/ulule/django-linguist.git
$ cd django-linguist
$ make devenv

# Enable virtual environment.
$ source .venv/bin/activate

# Launch tests
$ make test

# Launch example project
$ make serve

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解更多关于 安装包 的信息。

源代码分发

django-linguist-0.6.0.tar.gz (30.2 kB 查看哈希值)

上传时间 源代码

由以下机构支持

AWSAWS云计算和安全赞助商DatadogDatadog监控FastlyFastlyCDNGoogleGoogle下载分析MicrosoftMicrosoftPSF赞助商PingdomPingdom监控SentrySentry错误日志StatusPageStatusPage状态页