> On 24 Oct 2024, at 12:29, Ivan Solovev <ivan.solo...@qt.io> wrote:
> 
> Hi Volker,
> 
>> From my understanding, the idea behind the std::format framework would be
>> to have a “cardinality" type for which we can implement a special formatter,
>> allowing “whatever” to be in the format specification.
> 
> True, but the custom formatter specialization is called when the argument id
> is already parsed.
> In your example:
> 
>  std::format("{0:Cardinality}", Cardinality{42});
> 
> the std implementation parses the "{0:" part, extracting the argument id == 0,
> and then passes the rest of the string to the std::formatter<Cardinality>
> specialization.
> 
> IIUC, Thiago suggested to use 'n' instead of the argument id.


What we need is a way to signal to translators: this placeholder in the string 
represents the value that decides about which plural form to use. We can call 
it whatever we want. Today we do that by putting a `%n` into the translatable 
string; the tr() function replaces that with the number passed, but also 
selects the appropriate plural form from the translation. So in Engineering 
English

tr(“You have %n unread message(s)!”, “”, total);

the translator sees that %n is where the number goes and can position the %n 
appropriately in the target languages, e.g. in German

Null: Du hast keine ungelesenen Nachrichten!
Singular: Du hast eine ungelesene Nachricht!
Plural: Du hast %n ungelesenen Nachrichten!

If we want to make that information available to the translator, then we need 
to be able to do something in the source string. A very liberal formatter would 
allow anything to appear between the `:` and the closing brace, e.g.:

std::format(“You have {:number of messages goes here} unread message(s)”);

is possible (updated my godbolt sandbox to do that).


Btw, where does the “tr” go? Is it going to be tr(std::format(…)) or 
std::vformat(tr(…))?

In the former, we’d have to pass the value twice (once for std::format to 
substitute, once for tr() to pick the right translation; the benefit is compile 
time checks.

With the latter, we get no compile time services from std::format, but don’t 
have to pass the value twice. Use tr()’s plural functionality and %n for it as 
before. Otherwise, both sources and translations can muck around with 
std::format-features as much as they like (it’s equivalent to tr(…).arg()).


Volker

-- 
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development

Reply via email to