测试 django 国际化 - 模拟 gettext

发布于 2024-10-20 23:10:57 字数 533 浏览 1 评论 0原文

我正在国际化/i18n-ing 一个 django 项目。我们有一个独立运行并执行后台任务的部分。它是由rabbitmq调用的。我想测试 i18n/l10n 是否适用于该部分。然而,我们的应用程序尚未翻译,并且暂时不会翻译。我想在翻译开始之前编写单元测试。

我想模拟一些翻译,以便 _("anything") 作为常量字符串返回,这样我就可以测试它是否正在尝试翻译内容,而无需我设置所有内容翻译。

我尝试使用 mock,但是 with mock.patch('django.utils .translations.ugettext_lazy'), my_function_that_just_returns_one_string): 不起作用。 _ 导入为 from django.utils.translations import ugettext_lazy as _

I'm internationalizing/i18n-ing a django project. We have one part that runs independently and performs background tasks. It's called by rabbitmq. I want to test that the i18n/l10n works for that part. However our app isn't translated yet, and won't be for a while. I want to write the unittests before translation begins.

I'd like to mock some translations, so that _("anything") is returned as a constant string, so that I can test that it's trying to translate things, without me needing to set up all the translations.

I tried using mock, but with mock.patch('django.utils.translations.ugettext_lazy'), my_function_that_just_returns_one_string): didn't work. The _ is imported as from django.utils.translations import ugettext_lazy as _.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

深居我梦 2024-10-27 23:10:58

看来您没有修补正确的模块。如果您的 foo/models.py 具有 from django.utils.translations import ugettext_lazy as _ 语句,则 _ 位于命名空间中foo.models 模块的,这是你必须修补的地方。

with mock.patch('foo.models._', return_value='MOCKED_TRANSLATION'):
    ...

或者

with mock.patch('foo.models._') as mock_ugettext_lazy:
    mock_ugettext_lazy.side_effect = lambda x: x + ' translated'
    ...
    assert translated_text = 'example_text translated'

如果您有多个使用 ugettext_lazy 的模块,那么您可以这样做:

with mock.patch('foo.models._', side_effect=mock_translator), \
     mock.patch('bar._', side_effect=mock_translator):
    ...

不幸的是,没有单行代码可以为所有使用 ugettext_lazy 的模块模拟​​它,因为一旦函数被导入到模块中,更改 django.utils.translations.ugettext_lazy 就毫无意义了——原始引用将继续指向原始函数。

请参阅 https://docs.python.org/3 /library/unittest.mock.html#where-to-patch 了解更多。

It seems you're not patching the correct module. If it's your foo/models.py which has the from django.utils.translations import ugettext_lazy as _ statement, then _ is in the namespace of the foo.models module, and this is where you have to patch.

with mock.patch('foo.models._', return_value='MOCKED_TRANSLATION'):
    ...

or

with mock.patch('foo.models._') as mock_ugettext_lazy:
    mock_ugettext_lazy.side_effect = lambda x: x + ' translated'
    ...
    assert translated_text = 'example_text translated'

If you have multiple modules using ugettext_lazy, then you can do it like so:

with mock.patch('foo.models._', side_effect=mock_translator), \
     mock.patch('bar._', side_effect=mock_translator):
    ...

Unfortunately, there is no one-liner to mock it for all modules that use ugettext_lazy, because once the function is imported in your modules, it's pointless to change django.utils.translations.ugettext_lazy -- the original references will keep pointing to the original function.

See https://docs.python.org/3/library/unittest.mock.html#where-to-patch for more.

没有伤那来痛 2024-10-27 23:10:57

您可以执行以下操作来替换默认翻译对象上的 ugettext 方法:

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

translation(get_language()).ugettext = mock_ugettext

You can do the following to replace the ugettext method on the default translation object:

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

translation(get_language()).ugettext = mock_ugettext
路还长,别太狂 2024-10-27 23:10:57

我找不到现有的方法来做到这一点。然而,通过阅读 Django 源代码,我想出了一种简单、脆弱的方法来做到这一点:查看 _active DjangoTranslation 对象,然后包装它们的 ugettext 方法。我在这里描述了它: http:// /www.technomancy.org/python/django-i18n-test-translation-by-manually-setting-translations/

I couldn't find an existing way to do this. However from reading the Django source code I came up with a hacky, brittle way to do this by looking at the _active DjangoTranslation objects, then wrapping their ugettext methods. I've described it here: http://www.technomancy.org/python/django-i18n-test-translation-by-manually-setting-translations/

爺獨霸怡葒院 2024-10-27 23:10:57

我看过你的解决方案,我认为当你没有提供翻译字符串时测试 i18n 支持既巧妙又简单。但我担心 translation 包只是一个始终有效的东西,我们认为这是理所当然的,所以在大量注释的测试代码中看到它的内部结构至少会让我在恐惧中逃跑(笑)。

我认为创建一个测试应用程序,添加到测试设置中的 INSTALLED_APPS 中,提供自己的翻译是一种更简洁的方法。您的测试将被简化为 translation.activate('fr'); self.assertEqual('xxx_anything', gettext('anything'), '应该激活 i18n 支持。')

通过简单的测试,其他开发人员可以快速跟进并看到测试应用程序的包包含一个 /locale 目录,该目录应该立即记录您的方法。

I've looked at your solution and I think it's both ingenious and simple for testing i18n support when you have no translation strings provided. But I'm afraid the translation package is just something that always works and which we take for granted, so seeing it's internals in heavily commented test code would, at least, make me run off in fear (chuckle).

I think creating a test application, added to INSTALLED_APPS in test settings, which provides it's own translations is a much cleaner approach. Your tests would be simplified to translation.activate('fr'); self.assertEqual('xxx_anything', gettext('anything'), 'i18n support should be activated.').

With simple tests, other developers could quickly follow-up and see that the test app's package contains a /locale directory, which should immediately document your approach.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文