From nobody Sun Feb 8 18:13:27 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) client-ip=170.10.129.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1678464631; cv=none; d=zohomail.com; s=zohoarc; b=O7IjKbzvgQhzFNtA935435dkVpcJWJaF11+EaRmOn7sVoE3tjIP8kHTZABlYnht/3jEblsQ2DzRZ83wTLH+CVgN9woYHIST7PA592HzBZYi6QOZOfqH4cPEjGZxm9fN6Y3NIyQ2WbQifQ1uemUy3aomDAx0qWRVh3Nm7qvFlOGc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1678464631; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=+5X2mBfJvw59vsc+mpDttFu796vt28YaqC1tN7KvryU=; b=VIW/uwbsINkLommR1IKPj0+GiTC2OrXcDtH/belW0qgBO4lM9yuJ5bygTxX/6z1OXCRN5E34Na7HOzcj0covfmxJZVExFD+y7DY+5PboGGbObxlVXeWtTdBSRukCIo9c8qZ7UK8qMLBidlbF8NMO/apmF+cV0cmy0WjRg9o37A0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by mx.zohomail.com with SMTPS id 1678464631139972.2049232643142; Fri, 10 Mar 2023 08:10:31 -0800 (PST) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-539-rbkgUOweOz6Iz4iweTq1LA-1; Fri, 10 Mar 2023 11:10:25 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B2EB287A9E6; Fri, 10 Mar 2023 16:10:19 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9774B2166B26; Fri, 10 Mar 2023 16:10:18 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id DABD41946A6F; Fri, 10 Mar 2023 16:10:17 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 2B60E1946587 for ; Fri, 10 Mar 2023 16:10:17 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 1C0B02166B2A; Fri, 10 Mar 2023 16:10:17 +0000 (UTC) Received: from rein.int.mamuti.net (unknown [10.45.226.138]) by smtp.corp.redhat.com (Postfix) with ESMTP id D25272166B26 for ; Fri, 10 Mar 2023 16:10:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1678464630; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=+5X2mBfJvw59vsc+mpDttFu796vt28YaqC1tN7KvryU=; b=Dh4NKcbR4Z3mgUZS57/SkkEhgXdWzWdB3wqv15yjXvXMnCuI20kQazu0PeI3szL0xId9ZP k46OG0VNS/vSEpORDCUIPO6JXDmM47FowSpFh+Fme4/CDYYXCfZLph2COIdypQOtyl5cPM UlLNiuq3UNBcduZTKiqYwzLsuXbuHUo= X-MC-Unique: rbkgUOweOz6Iz4iweTq1LA-1 X-Original-To: libvir-list@listman.corp.redhat.com From: Jiri Denemark To: libvir-list@redhat.com Subject: [libvirt PATCH 01/51] docs: Document requirements on format strings in translated messages Date: Fri, 10 Mar 2023 17:09:17 +0100 Message-Id: <6701b4b04a46fa4129a5ed09c4e3883ff54cd61e.1678463799.git.jdenemar@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1678464632713100005 Content-Type: text/plain; charset="utf-8" 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 --- docs/coding-style.rst | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/docs/coding-style.rst b/docs/coding-style.rst index 02d99330bf..92f6099d82 100644 --- a/docs/coding-style.rst +++ b/docs/coding-style.rst @@ -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. =20 :: =20 GOOD: virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to connect to remote host '%s'"), hostnam= e) + _("Failed to connect to remote host '%1$s'"), hostn= ame) =20 BAD: virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to %s to remote host '%s'"), + _("Failed to %1$s to remote host '%2$s'"), "connect", hostname); =20 BAD: virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to connect " - "to remote host '%s'), + "to remote host '%1$s'), hostname); =20 Use of goto --=20 2.39.2