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

时间:2012-03-27 09:53:00

标签: 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"

等。这些类还有一个函数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

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

但是,如果我想将这些字符串国际化,则会出现错误:'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)}"

在类定义中,手动将参数名称添加为'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

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

2 个答案:

答案 0 :(得分:5)

  1. 在代码中, variable names should be meaningful within their context ,'meter_count'和'minute_count'是明确的,与'arg_0'和'arg_1'相比是无意义的

    < / LI>
  2. 使用 standard translation in python code ,它不易出错,并且被令人惊讶的makemessages命令识别

  3. 使用 use named-string interpolation (例如%(day)s)代替位置插值(例如,%s%d)不止一个参数,因为参数的顺序可能会根据语言而改变。即德语和拉丁语与名词/形容词顺序相反,日期根据语言等不同而有所不同......

  4. 使用 ran instead of runned ,仔细检查您的英语翻译字符串的语法有效性

  5. 此:

    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"
    

    变为:

    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")
    

答案 1 :(得分:1)

为了提供一种不同的方法来翻译包含数据库数据或任何用户生成内容的字符串,我强烈推荐Bablic。它们会跟踪您网站上显示的字符串,并通知您新的或未翻译的文本。它们还可以与基于云的翻译提供程序集成,以便即使是新提交的内容也可以立即翻译,而无需您跟踪或更新服务器端代码或配置。

也许这种方法更适合你?