使用未命名的字符串参数进行Django本地化

Xun*_*ang 2 python django localization internationalization

我在Django中创建了一些Badge类,每个类都包含一些字符串变量中的描述:

"You get this badge because you've runned %d meters in %d minutes"
"You get this badge because you've killed %d monsters of the type %s"
Run Code Online (Sandbox Code Playgroud)

这些类也有一个函数get_description(badge_level_requirements),因此在模板中它将与列表一起调用以组合特定用户的字符串:

class RunnerBadge(Badge):
    des=ugettext_lazy("You get this badge because you've runned %d meters in %d minutes")
    def get_description(cls,badge_level_requirements):
        return cls.des%badge_level_requirements
Run Code Online (Sandbox Code Playgroud)

并且我已经将需求列表存储在数据库中而没有任何参数名称:(如示例所示,不同的类具有不同数量的值来填充字符串,值也意味着不同的东西.所以我不能真的命名参数.

但是,如果我想将这些字符串国际化,那么就会出现错误:'msgid' format string with unnamed arguments cannot be properly localized并且无法为此事项生成语言文件.

有没有办法绕过这个错误?

更新

我遇到过这种绕过错误而不改变数据库的方法.在数据库中,级别要求以dict格式存储在文本字段中:

#Requirment of Runner's badge
"{'gold':(100,10),'silver':(50,5),'bronze':(25,2)}"
Run Code Online (Sandbox Code Playgroud)

在类定义中,手动将参数名称添加为'arg_0','arg_1'...到描述中.在用于填充描述字符串之前,将get_description方法更改为预处理数据.

class RunnersBadge(Badge):
    requirements=#get the previous dict from database
    description="You get this badge because you've runned %(arg_0)d meters in %(arg_1)d minutes"

    @classmethod
    def get_description(cls,level):
        '''
        This is actually a method of parent class Badge
        level is either 'gold','silver' or 'bronze'
        '''
        dic={}
        try:
            for (num,val) in enumerate(cls.requirements[level]):
                dic['arg_'+str(num)]=val
        except TypeError:
            dic['arg_0']=cls.requirements[level]


        return cls.description%dic
Run Code Online (Sandbox Code Playgroud)

此方法保留了大部分当前结构(逻辑和数据库).译者只需要处理"放置"这几个字.

jpi*_*pic 5

  1. 就像在代码中一样,变量名在其上下文中应该是有意义的,'meter_count'和'minute_count'是显式的,与'arg_0'和'arg_1'相比是无意义的

  2. 在python代码中使用标准转换,它不易出错,并且被令人惊讶的makemessages命令识别

  3. 使用使用命名字符串插值(例如,%(day)s),而不是位置的内插(例如,%s%d),只要你有超过一个参数更多,因为参数的顺序可以根据语言的变化.即德语和拉丁语反转名词/形容词顺序,日期根据语言等不同显示...

  4. 使用run而不是runned,仔细检查你的英文翻译字符串的语法有效性

这个:

class RunnersBadge(Badge):
    requirements=#get the previous dict from database
    description="You get this badge because you've runned %(arg_0)d meters in %(arg_1)d minutes"
Run Code Online (Sandbox Code Playgroud)

变为:

from django.utils.translation import ugettext as _

class RunnersBadge(Badge):
    requirements=#get the previous dict from database
    description=_("You get this badge because you've ran %(meter_count)d meters in %(minute_count)d minutes")
Run Code Online (Sandbox Code Playgroud)