Django库,用于将模型和表单中的转换字符串外部化。
dj-labeler的Python项目详细描述
django模型最烦人的地方是,当你想做正确的事情时,它们的冗长。一旦你 如果有国际观众,你需要开始标记翻译字符串。创建Labeler是为了减少 通过外部化模型的标签、帮助文本和错误消息而产生的噪音。它甚至提供相同的功能 任何Django表格。
预计它将与django 1.8、1.9及更高版本一起使用。
安装
在pypi上,labeler可用作dj-labeler:
pip install dj-labeler
示例
想象一下我们的bookstore模型是这样的:
from django.db import models class Author(models.Model): name = models.CharField(max_length=200) published = models.BooleanField(default=False) birthdate = models.DateField(blank=True, null=True) class Book(models.Model): title = models.CharField(max_length=200) published_on = models.DateField(blank=True, null=True) isbn = models.CharField(max_length=50, unique=True) authors = models.ManyToManyField(Author)
现在你想开拓一个讲荷兰语的市场。而不是依赖于django的自动标签创建 根据字段名,您需要显式地声明每个字段的详细名称,并将其标记为 可翻译字符串。为了避免人们对荷兰语翻译产生任何困惑,你需要 提供尽可能多的上下文,因为作者的名称可能不需要与 一个类别。
所以你最终得到了这个:
from django.db import models from django.utils.translation import pgettext_lazy class Author(models.Model): name = models.CharField(pgettext_lazy('author', 'name'), max_length=200) published = models.BooleanField(pgettext_lazy('author', 'published'), editable=False) birthdate = models.DateField(pgettext_lazy('author', 'birthdate'), blank=True, null=True) class Meta: verbose_name = pgettext_lazy('author model', 'Author') verbose_name_plural = pgettext_lazy('author model (plural)', 'Authors') class Book(models.Model): title = models.CharField(pgettext_lazy('book', 'title'), max_length=200) published_on = models.DateField(pgettext_lazy('book (date)', 'published'), blank=True, null=True) isbn = models.CharField(pgettext_lazy('book', 'isbn'), max_length=50, unique=True) authors = models.ManyToManyField(Author, verbose_name=pgettext_lazy('book authors', 'authors')) class Meta: verbose_name = pgettext_lazy('author model', 'Book') verbose_name_plural = pgettext_lazy('author model (plural)', 'Books')
现在加上帮助文本,你会有很多噪音,使你很难辨别你作为一个程序员的属性 在开发时关心最多,比如最大长度和字段是可选的还是唯一的。
labeler将使应用程序能够使用噪音更小的可翻译字符串。让我们把字符串移到一个单独的文件中 我们将调用i18n.py(但任何名称都可以)并使用labeler的ModelTranslations:
# i18n.py from django.utils.translation import pgettext_lazy from labeler import ModelTranslations author = ModelTranslations( labels=dict( name=pgettext_lazy('author', 'name'), published=pgettext_lazy('author', 'published'), birthdate=pgettext_lazy('author', 'birthdate') ) help_texts=dict( birthdate=pgettext_lazy('author', 'When was the author born?') ), name=pgettext_lazy('author model', 'Author'), name_plural=pgettext_lazy('author model (plural)', 'Authors') ) book = ModelTranslations( labels=dict( title=pgettext_lazy('book', 'title'), published_on=pgettext_lazy('book (date)', 'published'), isbn=pgettext_lazy('book', 'isbn'), authors=pgettext_lazy('book authors', 'authors') ), help_texts=dict( isbn=pgettext_lazy('book', 'The ISBN will be validated against XYZ database') ), name=pgettext_lazy('author model', 'Book'), name_plural=pgettext_lazy('author model (plural)', 'Books') )
这仍然是一个很大的噪音,但至少我们已经把它隔离到一个单独的文件在我们的应用程序。现在,因为 ModelTranslations只是dict的扩展,您可以开始这样做:
# models.py from django.db import models from . import i18n class Author(models.Model): # as above class Meta: verbose_name = i18n.author['name'] verbose_name_plural = i18n.author['name_plural']
但这并不能减少噪音。相反,您应该使用^{tt3}的injectmethod/decorator$ (或FormTranslations处理表单时)。这将使我们的模型更精简,意味着:
# models.py from django.db import models from . import i18n @i18n.author.inject class Author(models.Model): name = models.CharField(max_length=200) published = models.BooleanField(default=False) birthdate = models.DateField(blank=True, null=True) @i18n.book.inject class Book(models.Model): title = models.CharField(max_length=200) published_on = models.DateField(blank=True, null=True, unique=True) isbn = models.CharField(max_length=50) authors = models.ManyToManyField(Author)
发现与我们最初版本的区别了吗?这个版本仅仅通过装饰我们的模型就使用了可翻译的字符串。 使用我们的模型翻译'inject。
用法
使用模型转换转换模型
ModelTranslations是一个简单的dict,上面添加了一些有用的方法和属性。什么都不需要, 但如果指定labels、help_texts或error_messages,则这些词典的键应该引用 对现有模型字段。
ModelTranslations key | Type | Maps to | Attribute |
---|---|---|---|
^{tt11}$ | dict | field | ^{tt15}$ |
^{tt12}$ | dict | field | ^{tt17}$ |
^{tt13}$ | dict | field | Updates ^{tt13}$ |
^{tt20}$ | str | Meta | ^{tt15}$ |
^{tt22}$ | str | Meta | ^{tt23}$ |
示例:
from django.utils.translation import ugettext_lazy as _ from labeler import ModelTranslations article = ModelTranslations( # verbose_name of the model's fields labels=dict( title=_('Title'), body=_('Body') ), # help_text of the model's fields help_texts=dict( title=_('No clickbait titles please!') ), # update to the listed fields' error_messages error_messages=dict( title=dict( unique=_('Title already exists') ) ), # verbose_name of the model name=_('article'), # verbose_name_plural of the model name_plural=_('articles'), # Handy dict of error messages for this model, not field-specific errors=dict( too_clickbaity=_('Please review the article.') ), # Handy dict for other kinds of messages messages=dict( first_publication=_('Congratulations! Your first article has been published') ), # It's just a dict; add whatever you want something_else='abc', publication_state={ 'published': _('Published'), 'draft': _('Draft'), 'trashed': _('Trashed') } )
当一切就绪,准备就绪时,只需将其注入您的模型:
from . import i18n @i18n.article.inject class Article(models.Model): # Fields and stuff
嵌套的标签、错误消息、错误消息和帮助文本词典也可用作属性。 这意味着自定义验证可能如下所示:
def clean_fields(self, exclude=None): super(MyModel, self).clean_fields(exclude) if 'title' not in exclude and calculate_clickbait_level(self.title) > 50: raise ValidationError({'title': i18n.article.errors['too_clickbaity']})
如果要处理大量嵌套的dict,可以使用resolve方法:
hard_way = i18n.article.get('errors', {}).get('fieldname', {}).get('invalid', {}).get('state') easier_way = i18n.article.resolve('errors.fieldname.invalid.state') easier_way == hard_way
使用formtranslations翻译表单
FormTranslations的工作方式与ModelTranslations完全相同,但它也支持嵌套字典 empty_labels覆盖表单字段上的默认空标签。
FormTranslations key | Type | Maps to | Attribute |
---|---|---|---|
^{tt11}$ | dict | field | ^{tt29}$ |
^{tt12}$ | dict | field | ^{tt17}$ |
^{tt27}$ | dict | field | ^{tt33}$ |
^{tt13}$ | dict | field | Updates ^{tt13}$ |
用法:
# i18n.py from django.utils.translation import ugettext_lazy as _ from labeler import FormTranslations article_form = FormTranslations( labels=dict( title=_('Title'), body=_('Body'), published=_('When to publish this article'), author=_('Author'), ), help_texts=dict( title=_('Limit to 100 characters please'), body=_('Formatting is not supported') ), empty_labels=dict( author=_('Please select an author') ), error_messages=dict( title=dict( unique=_('That title has already been used. Be more original!') ) ) ) # forms.py from django import forms from . import i18n from .models import Article @i18n.article_form.inject class ArticleForm(forms.ModelForm): class Meta: model = Article fields = ('title', 'body', 'published', 'author')
就这些了。
更改日志
v1.0.1
- 修复自述文件和项目信息中的代码