diff options
| author | Martin Trigaux <mat@odoo.com> | 2020-05-29 10:41:36 +0200 |
|---|---|---|
| committer | Martin Trigaux <mat@odoo.com> | 2020-06-18 13:03:34 +0200 |
| commit | 3c3b88f6768e31417263b3828a874ca204e29514 (patch) | |
| tree | 75cc876da6234374e0a0dab68606536a24acb616 /doc/reference | |
| parent | 5af661da7d62605127566124bf5f0e2ee84432db (diff) | |
[IMP] tools: add placeholder support to _
Mimic the syntax of logging to use placeholders in translatable
message.
The main advantage is to be able to fallback on the source term if the
translation can not be formatted properly.
It is very common to have errors in translations with missing
placeholders or badly translated (ie. the source
"%(subject)s" -> "%(sujet)s").
Instead of blocking the execution of the code, fallback on source
string.
Task-id: 1853119
Diffstat (limited to 'doc/reference')
| -rw-r--r-- | doc/reference/guidelines.rst | 32 | ||||
| -rw-r--r-- | doc/reference/translations.rst | 11 |
2 files changed, 24 insertions, 19 deletions
diff --git a/doc/reference/guidelines.rst b/doc/reference/guidelines.rst index 2b6dc4a0a23..6ffd19f5c78 100644 --- a/doc/reference/guidelines.rst +++ b/doc/reference/guidelines.rst @@ -837,6 +837,7 @@ in the code, it will not work to translate field values, such as Product names, etc. This must be done instead using the translate flag on the corresponding field. +The method accepts optional positional or named parameter The rule is very simple: calls to the underscore method should always be in the form ``_('literal string')`` and nothing else: @@ -846,19 +847,23 @@ the form ``_('literal string')`` and nothing else: error = _('This record is locked!') # good: strings with formatting patterns included - error = _('Record %s cannot be modified!') % record + error = _('Record %s cannot be modified!', record) # ok too: multi-line literal strings error = _("""This is a bad multiline example - about record %s!""") % record + about record %s!""", record) error = _('Record %s cannot be modified' \ - 'after being validated!') % record + 'after being validated!', record) # bad: tries to translate after string formatting # (pay attention to brackets!) # This does NOT work and messes up the translations! error = _('Record %s cannot be modified!' % record) + # bad: formatting outside of translation + # This won't benefit from fallback mechanism in case of bad translation + error = _('Record %s cannot be modified!') % record + # bad: dynamic string, string concatenation, etc are forbidden! # This does NOT work and messes up the translations! error = _("'" + que_rec['question'] + "' \n") @@ -869,32 +874,31 @@ the form ``_('literal string')`` and nothing else: # and the following will of course not work as already explained: error = _("Product %s is out of stock!" % product.name) - # bad: field values are automatically translated by the framework - # This is useless and will not work the way you think: - error = _("Product %s is not available!") % _(product.name) - # and the following will of course not work as already explained: - error = _("Product %s is not available!" % product.name) - # Instead you can do the following and everything will be translated, # including the product name if its field definition has the # translate flag properly set: - error = _("Product %s is not available!") % product.name + error = _("Product %s is not available!", product.name) Also, keep in mind that translators will have to work with the literal values that are passed to the underscore function, so please try to make them easy to understand and keep spurious characters and formatting to a minimum. Translators -must be aware that formatting patterns such as %s or %d, newlines, etc. need -to be preserved, but it's important to use these in a sensible and obvious manner: +must be aware that formatting patterns such as ``%s`` or ``%d``, newlines, etc. +need to be preserved, but it's important to use these in a sensible and obvious +manner: .. code-block:: python # Bad: makes the translations hard to work with error = "'" + question + _("' \nPlease enter an integer value ") - # Better (pay attention to position of the brackets too!) + # Ok (pay attention to position of the brackets too!) error = _("Answer to question %s is not valid.\n" \ - "Please enter an integer value.") % question + "Please enter an integer value.", question) + + # Better + error = _("Answer to question %(title)s is not valid.\n" \ + "Please enter an integer value.", title=question) In general in Odoo, when manipulating strings, prefer ``%`` over ``.format()`` (when only one variable to replace in a string), and prefer ``%(varname)`` instead diff --git a/doc/reference/translations.rst b/doc/reference/translations.rst index c7997e1e966..cc6c92cbb5d 100644 --- a/doc/reference/translations.rst +++ b/doc/reference/translations.rst @@ -104,9 +104,10 @@ Variables _("Scheduled meeting with %s" % invitee.name) -**Do** set the dynamic variables outside of the translation lookup:: +**Do** set the dynamic variables as a parameter of the translation lookup (this +will fallback on source in case of missing placeholder in the translation):: - _("Scheduled meeting with %s") % invitee.name + _("Scheduled meeting with %s", invitee.name) Blocks @@ -135,16 +136,16 @@ Plural ^^^^^^ **Don't** pluralize terms the English-way:: - msg = _("You have %s invoice") % invoice_count + msg = _("You have %(count)s invoice", count=invoice_count) if invoice_count > 1: msg += _("s") **Do** keep in mind every language has different plural forms:: if invoice_count > 1: - msg = _("You have %s invoices") % invoice_count + msg = _("You have %(count)s invoices", count=invoice_count) else: - msg = _("You have %s invoice") % invoice_count + msg = _("You have one invoice") Read vs Run Time ^^^^^^^^^^^^^^^^ |
