测试Django国际化 - 模拟gettext

7 投票
4 回答
6213 浏览
提问于 2025-04-16 13:21

我正在给一个Django项目做国际化处理,也就是让它支持多种语言。这个项目有一个独立的部分,负责后台任务,它是通过rabbitmq来调用的。我想测试一下这个部分的国际化和本地化功能。不过我们的应用还没有翻译好,估计也要一段时间才能完成。我想在翻译开始之前先写好单元测试。

我想模拟一些翻译的效果,让 _("任何内容") 返回一个固定的字符串,这样我就可以测试它是否在尝试翻译内容,而不需要我提前设置所有的翻译。

我试着使用了 mock 这个库,但是 with mock.patch('django.utils.translations.ugettext_lazy'), my_function_that_just_returns_one_string): 这个方法没有成功。因为 _ 是通过 from django.utils.translations import ugettext_lazy as _ 这种方式导入的。

4 个回答

2

我看了你的解决方案,觉得它既聪明又简单,特别是在没有提供翻译字符串的情况下测试国际化支持。不过,我担心的是,translation这个包总是能正常工作,我们习惯了它的存在,所以看到它内部的复杂代码,尤其是在注释很多的测试代码中,可能会让我感到害怕(笑)。

我觉得创建一个测试应用程序,并把它添加到测试设置中的INSTALLED_APPS里,这样它自己提供翻译会更干净利落。你的测试可以简化为translation.activate('fr'); self.assertEqual('xxx_anything', gettext('anything'), 'i18n support should be activated.')

通过简单的测试,其他开发者可以很快跟进,看到测试应用的包里有一个/locale目录,这样就能立刻理解你的做法了。

3

你可以通过以下方法来替换默认翻译对象中的 ugettext 方法:

from django.utils.translation.trans_real import get_language, translation

translation(get_language()).ugettext = mock_ugettext
2

我找不到现成的方法来做到这一点。不过,通过阅读Django的源代码,我想出了一个有点笨拙、不太可靠的方法。这个方法是查看当前活动的DjangoTranslation对象,然后对它们的ugettext方法进行包装。我在这里描述了这个过程:http://www.technomancy.org/python/django-i18n-test-translation-by-manually-setting-translations/

撰写回答