如何让Django管理员尊重波兰语等语法案例?

时间:2017-08-02 16:19:07

标签: django internationalization django-admin

Django允许覆盖verbose_name的{​​{1}}和verbose_name_plural,这允许我们为非英语语言指定正确的复数形式的Model名称(例如{{} 1}}作为Model的复数而不是默认的Kandydaci,在波兰语中看起来很奇怪。)

然而,对于具有语法案例的语言来说,这远远不够。例如,Django Admin兴高采烈地向我们展示了类似的内容:

enter image description here

(其中Kandydat代表Kandydats - Zaznacz kandydat do zmianySelect kandydat to change的名称

这是不正确的。在这句话中,模型名称应该显示在accusative case中,即Kandydat。但是,我不能简单地指定此Model的{​​{1}}为kandydata,因为这也会影响所有预期nominative case的地方 - 我找到了一个这样的地方所以远,这是表格列的标题:

enter image description here

这是不可理解的,因为表格标题应该被称为verbose_name而不是Model

如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

The string 'Select <verbose_name> to change' is declared inside the admin's main view

self.title = title % force_text(self.opts.verbose_name)

as a {{ title }} template variable

{% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}

So, touching the built-in view is out of question. But there is another way of doing it! You see, Django Admin templates are full of {% block %}s acting as placeholders in order to override them. Read more at the official docs about overriding Admin templates.

So, to your question.

  1. Under your project's root directory create a directory templates (if it doesn't exists already).
  2. Under my_project/templates/ create another one, admin.
  3. Under my_project/templates/admin/ create a file change_list.html.
  4. Inside my_project/templates/admin/change_list.html put these:

    {% extends 'admin/change_list.html' %}
    
    {% load myutils_filters %}
    
    {% comment %}
    You have to create an app that will hold all common tags/filters
    that are re-usable across your entire project.
    The model class itself is passed as cl.model
    {% endcomment %}
    
    {% block content_title %}{{ block.super|to_accusative:cl.model }}{% endblock %}
    
  5. Inside your myutils/templatetags/myutils_filters.py file put these:

    from django import template
    from django.utils.html import format_html
    from django.utils.encoding import force_text
    
    register = template.Library()
    
    @register.filter()
    def to_accusative(value, model):
        verbose_name = model._meta.verbose_name  # declared in Meta
        new_name = force_text(model.accusative case())  # a custom class method (lives in your Model)
        return format_html(value.replace(verbose_name, new_name))
    
  6. Finally, under your app's models.py, under each model class define a classmethod method like this:

    from django.db import models
    from django.utils.translation import ugettext_lazy as _
    
    class MyModel(models.Model):
        # model fields here
    
        def __str__():
            return self.a_field
    
        class Meta:
            verbose_name = 'verbose name'
            verbose_name_plural = 'verbose name plural'
            # accusative_case = 'accusative name case' # BAD. Raises error. Implement a class method intead ;)
    
        @classmethod
        def accusative_case(cls):
            # You'll define the Polish translation as soon as you run makemessages
            return _('Name in english of the accusative case')
    
  7. Run manage.py makemessages, manage.py compilemessages, reload your browser and voila!

Note: The above may look a little hackish but it works brilliant. Tested locally and works.