What is pgettext_lazy in Django? - django

I was working with an open-source project (made in Django). I couldn't understand what pgettext_lazy is used for. Can you please tell me
What is pgettext_lazy?
Usage of pgettext_lazy?

pgettext_lazy(..) [Django-doc] is a function that is used to translate text. The Django documentation has a section on translation [Django-doc] that discusses this.
pgettext_lazy is a lazy variant of pgettext. This is a function that makes context-aware translations [Django-doc]. Context-aware translations deal with the fact that a word can be translated in multiple ways. For example May can be translated as the name of a month, or a verb.
We can make it clear how to translate it by adding a "context marker", and thus call the translation with:
from django.utils.translation import pgettext
month = pgettext("month name", "May")
In your .po file(s), the files you use to define translations, you can then add the context marker:
msgctxt "month name"
msgid "May"
msgstr ""
You can make translations in the views in the language that is activated, but you can not just define that translation in for example the help_text of a model. Indeed, if you would call pgettext(..) in a models.py file. It would translate the help_text in the language that is active at that time. But if later a user with a different language uses that help_text, it would not be translated in the other language.
By making the translation lazy, the process of translation is postponed until a str(..) is called on the result. That way, if you render the lazy object in a template it will be translated in the language of the user.
You can find more information on this in the Translation section of the documentation.

Related

Symfony forms, labels not to be translated

I have some labels in a form which don't need to be translated (for example, IBAN, PayPal Email, Skype...)
Can i avoid translating them (it would increase the translation files size uselessly), without having the "Missing messages" error?
I'm using a standard Doctrine Entity + FormType class + Twig layout
In your FormType, just set the 'translation_domain' option to false.
http://symfony.com/doc/current/reference/forms/types/form.html#translation-domain
You can also use this option on the children.

Django prefetch related and django hvad

I have the following model and I am using django-hvad for the translations
class FooType(TranslatableModel):
code = models.CharField(max_length=255, unique=True)
translations = TranslatedFields(name=models.CharField(max_length=255))
def __unicode__(self):
return self.lazy_translation_getter('name')
Any time I ask for the list of hotel types;
It makes following query many times
SELECT ••• FROM "foo_footype_translation" WHERE "foo_foo_type_translation"."master_id" = 159 LIMIT 1
I have to apply prefetch_related any time I call for the unicode.
Is there a way for that?
EDIT: From looking at the docs, it looks like you should be using TranslationManager
from hvad.manager import TranslationManager
class FooType(TranslatableModel):
...
objects = TranslationManager()
REF: http://django-hvad.readthedocs.org/en/latest/public/queryset.html#translationqueryset
It's been quite some time since that was asked, but as it's not received a definite answer, some things have changed and others have been refined, I figured I'd add one.
The normal way to work with translatable objects in hvad is to request the translation to be fetched as well. You have a couple of examples in the README page and the documentation as well, but it looks like this:
qs = FooType.objects.language("en").all()
The objects loaded in this way will be fully loaded, including their translation in the given language. Objects with no translation in that language are filtered out.
You may omit the language to use current language (most useful when combined with Django's LocaleMiddleware):
qs = FooType.objects.language().all()
You may also use translated fields transparently, for instance this will return all objects with name foobar in current language:
qs = FooType.objects.language().filter(name__iexact='foobar')
You can also search all languages at once using the 'all' special code. The following line will return all objects with name foobar in any language (objects with such name in several language will be returned once for each matching language):
qs = FooType.objects.language('all').filter(name__iexact='foobar')
If you run Django 1.6 or newer, it is also possible to request an object list in a given language, with a priority-based fallback list, this way:
qs = FooType.objects.language("de").fallbacks("ja", "en")
That would fetch all objects, without filtering any. Objects not translated in German would be loaded in Japanese. If they're not available in Japanese, English is tried next, and if it's not available either, an arbitrary language will be picked (internally, this uses a self-join so only one request is made).
In any case, to use translated fields without incurring a performance penalty you must either go through the language() method or make it implicit (for advanced users only).
The reason this behavior is not default is to keep compatibility with existing codebase: as long as language() is not called, hvad does not touch your query.
Hope it helps.

Make Django first search message files (.mo) for current application

Django searches for messages files (.mo) in the order that is documented here:
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#how-django-discovers-translations
Is it possible to have Django first search for messages files in the locale directory for the app that is currently being used?
I recently discoverd a bug in a project, that was caused by two apps having the same message-id but different translation. All the apps have their own locale directory.
I'm afraid this is not how django works for various reasons:
A single phrase should have a single translation. Django aside, this is a matter of gettext as well (the engine used for translation messages). Besides, it sounds normal to expect from a system to translate a single phrase with consistency in all pages. It still is the same phrase in the original language after all.
What would 'current application' mean? Is current application the one generating the current view? The translation itself might be coming from a module of another application. How to decide which of these two applications is appropriate? Translations can also be lazy which adds additional complexity to such decisions.
I suggest that you reorder your applications in INSTALLED_APPS to match the translation you prefer, or define a new translation messages path using the LOCALE_PATHS setting to provide a translation of your own.
Note: Technically, it is possible to override the default behavior in django.utils.translation.trans_real by providing a custom implementation of this module to change the behavior as you wish (it is the translation() method in this module that implements the selection algorithm). Then you should also override the Trans class originally defined in django.utils.translation.__init__ module to return your custom trans_real module (name this new class MyCustomTrans for example) and explicitly set it as the translation class somewhere in your project's init module, so that it loads early in the code:
from django.utils import translation
translation._trans = MyCustomTrans()
Now your custom algorithm would be used instead, but this would require a lot of work and in my opinion does not worth the hassle.

Django Not Translating Built-in View

I'm using auth.password_reset for a view with my own template. The template has 1 string of text that will not translate. I'm not exactly new to i18n so I'm 99% sure I covered all my bases and that it would translate if it were my own view. Here are the things I made sure not to forget:
-Removed the ;fuzzy tag
-Made sure I had the right translation string
-ran makemessages, translated and compilemessage
-restarted my server
Any idea what is going on?

Good way to provide Rails-way i18n support in Django

There's one thing in (new) Rails I envy: internationalization support (Django has one too, but I prefer Rails' flavour).
The key difference between Rails' and Django's approaches is what kind of string behaves like keys in key-value translation mapping, i.e.
Django version (keys - strings in "main" language, for example english):
msgid "Save and quit"
msgstr "Zapisz i wyjdź"
Rails version equivalent (keys - abstract strings; standalone unusable - one need to provide at least 1 "translation") - actually, Rails uses YAML format, but following example present the idea:
// english translation file
msgid "SAVE_QUIT_MESSAGE"
msgstr "Save and quit"
and
// polish translation file
msgid "SAVE_QUIT_MESSAGE"
msgstr "Zapisz i wyjdź"
Rails' way of supporting i18n is IMHO much better (think of key immutability - resistant to grammar/spelling corrections; language agnosticism etc).
One way to utilize this schema in Django would be to use some abstract language for the sole purpose of being translated (strings in that language would make immutable keys), but Django support only fixed set of languages. Another solution - sacrifice one of the supported (unused) languages to play this role - but this is just bad :P
Any ideas/third-party apps/techniques to solve this issue?
Sidenote: extending i18n support for artibrary languages would give funny opportunities:
// slang translation file
msgid "SAVE_QUIT_MESSAGE"
msgstr "Save shit 'n' quit, bro"
Step back for a minute or two. Your doing triple work here. First you have to come up with a UNIQUE_ID and then you force people to look up either the context from the code or another language file to figure out what would the proper message for AMBIGUOUS_ARGUMENT_PROVIDED would be until you get down to providing the actual translation. And who ever said that creating IDs that can meaningfully convey the context and provide good message hints was ever easy?
What your trying to do is some preposterous shit bro! Jokes aside, the reason gettext is the most prevalent and widely used i18n and l10n API is because each message gets a unique message catalog ID assigned from it's contents and because it's proven you'll have a way better time translating messages than providing translations for IDs, reminiscent of when everyone tried making their own key->value i18n framework because it was the most straightforward to design.
You'll eventually conclude that it was a bad idea to use gettext the way it wasn't meant to and you can save yourself right now by forgetting about the whole idea.
If you insist on doing it this way, then it can be done by generating a .po file that will contain the English translations of the source strings.