diff --git a/AGENTS.md b/AGENTS.md index 78c64f84a7..3a7e4039b2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -336,15 +336,25 @@ auto filesTextProducer = tr::lng_files_selected( - Placeholders use `lt_tag_name, value` pattern - For `{count}`: immediate uses `int`, reactive uses `rpl::producer` with `| tr::to_count()` - Move producers with `std::move` when passing to placeholders -- Rich text projectors — pass as the last argument to produce `TextWithEntities` instead of `QString`. These are smart objects with multiple `operator()` overloads: +- Rich text projectors — these `tr::` helpers serve double duty: as the **last argument** (projector) they set the return type to `TextWithEntities`, and as **placeholder values** they wrap individual substitutions in formatting. Always prefer them over `Ui::Text::Bold()`, `Ui::Text::RichLangValue`, etc. — see REVIEW.md for the full mapping. - `tr::marked` — basic projection, converts `QString` to `TextWithEntities` - `tr::rich` — interprets `**bold**`/`__italic__` markup in the string - `tr::bold`, `tr::italic`, `tr::underline` — wrap text in that formatting - `tr::link` — wrap as a clickable link - `tr::url(u"https://..."_q)` — returns a projection that converts text to a link pointing to the given URL; can be passed to `rpl::map` or directly to a `tr::lng_...` call ```cpp + // As last argument (projector): auto title = tr::lng_export_progress_title(tr::now, tr::bold); auto text = tr::lng_proxy_incorrect_secret(tr::now, tr::rich); + // As placeholder value wrapper + projector: + auto desc = tr::lng_some_key( + tr::now, + lt_name, + tr::bold(userName), + lt_group, + tr::bold(groupName), + tr::rich); + // Nested tr::lng as placeholder: auto linked = tr::lng_settings_birthday_contacts( lt_link, tr::lng_settings_birthday_contacts_link(tr::url(link)), diff --git a/REVIEW.md b/REVIEW.md index e28252d5d4..092dcb124f 100644 --- a/REVIEW.md +++ b/REVIEW.md @@ -114,6 +114,62 @@ bool _expanded = false; SomeType *_pointer = nullptr; ``` +## Prefer tr:: projections over Ui::Text:: in localization calls + +Inside `tr::lng_...()` calls, always use the `tr::` projection helpers instead of their `Ui::Text::` equivalents. The `tr::` helpers are shorter and work uniformly as both placeholder wrappers and final projectors. + +| Instead of | Use | +|---|---| +| `Ui::Text::Bold(x)` | `tr::bold(x)` | +| `Ui::Text::Italic(x)` | `tr::italic(x)` | +| `Ui::Text::RichLangValue` | `tr::rich` | +| `Ui::Text::WithEntities` | `tr::marked` | + +```cpp +// BAD - verbose Ui::Text:: functions: +tr::lng_some_key( + tr::now, + lt_name, + Ui::Text::Bold(name), + lt_group, + Ui::Text::Bold(group), + Ui::Text::RichLangValue) + +// GOOD - concise tr:: helpers: +tr::lng_some_key( + tr::now, + lt_name, + tr::bold(name), + lt_group, + tr::bold(group), + tr::rich) +``` + +## Multi-line calls — one argument per line + +When a function call doesn't fit on one line, put each argument on its own line. Don't group "logical pairs" on the same line — it creates inconsistent line lengths and makes diffs noisier. + +```cpp +// BAD - pairs of arguments sharing lines: +tr::lng_some_key( + tr::now, + lt_name, tr::bold(name), + lt_group, tr::bold(group), + tr::rich) + +// GOOD - one argument per line: +tr::lng_some_key( + tr::now, + lt_name, + tr::bold(name), + lt_group, + tr::bold(group), + tr::rich) + +// Single-line is fine when everything fits: +auto text = tr::lng_settings_title(tr::now); +``` + ## std::optional access — avoid value() Do not call `std::optional::value()` because it throws an exception that is not available on older macOS targets. Use `has_value()`, `value_or()`, `operator bool()`, or `operator*` instead.