docs: Document requirements on format strings in translated messages

Preserving the order of format strings (%s, ...) when translating
messages may be very hard or even impossible depending on the target
language. On the other hand, reordering them requires understanding the
C-format strings which is not something we should expect from
translators. And even if someone reorders format strings in the right
way (by addressing arguments directly using N$), someone else may use a
translation tool that requires format strings in msgid and msgstr to
match exactly and forces these correct formats to be reverted.

As a result of this, we had several reported crashes in some locales
because integers were formatted as strings. So to make such crashes less
likely to happen and to make translating our messages easier, we now
require all messages that are marked for translation to use format
strings that always refer to the same argument no matter where they
appear in a message (e.g., %1$s, %5$llu).

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Jiri Denemark 2023-03-08 10:58:11 +01:00
parent d19c8096f8
commit d317d1d217

View File

@ -918,24 +918,28 @@ Error messages visible to the user should be short and
descriptive. All error messages are translated using gettext and
thus must be wrapped in ``_()`` macro. To simplify the translation
work, the error message must not be concatenated from various
parts. To simplify searching for the error message in the code the
strings should not be broken even if they result into a line
longer than 80 columns and any formatting modifier should be
enclosed by quotes or other obvious separator. If a string used
with ``%s`` can be NULL the NULLSTR macro must be used.
parts and all format strings must be permutable by directly
addressing each argument using ``%N$...`` syntax. For example,
``%1$s``, ``%2$llu`` or ``%4$s`` to format the first argument as
string, the second argument as unsigned long long, and the fourth
argument as string, respectively. To simplify searching for the error
message in the code the strings should not be broken even if they
result into a line longer than 80 columns and any formatting modifier
should be enclosed by quotes or other obvious separator. If a string
used with ``%N$s`` can be NULL the NULLSTR macro must be used.
::
GOOD: virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to connect to remote host '%s'"), hostname)
_("Failed to connect to remote host '%1$s'"), hostname)
BAD: virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to %s to remote host '%s'"),
_("Failed to %1$s to remote host '%2$s'"),
"connect", hostname);
BAD: virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to connect "
"to remote host '%s'),
"to remote host '%1$s'),
hostname);
Use of goto