Redundant/mis-use of _(x) gettext macro?

First seen: 2026-04-01 03:48:08+00:00 · Messages: 14 · Participants: 5

Latest Update

2026-05-18 · claude-opus-4-6

Technical Analysis: Redundant/Mis-use of _(x) gettext Macro

Core Problem

This thread begins with what appears to be a simple cleanup — removing seemingly unnecessary _() gettext macro wrappings around format strings that contain only "%s" — but evolves into a deeper discussion about internationalization (i18n) correctness in PostgreSQL's publication name list construction.

Initial Misunderstanding

The original report identified two instances where _() wraps a format string containing nothing but a quoted format specifier (e.g., _("\"%s\"")). The assumption was that since there's "nothing to translate," the _() macro is superfluous. This is incorrect.

Why the _() Macro is Necessary on Quote-Only Strings

The _() macro marks strings for extraction into .po translation files. Even a string like "\"%s\"" — which appears to be "just quoting" — is legitimately translatable because:

  1. Quotation marks are locale-dependent. Different languages use different quoting conventions:

    • German: »%s« (guillemets, reversed)
    • Spanish: «%s» (guillemets)
    • French: « %s » (guillemets with spaces)
    • English: "%s" (double quotes)
  2. Translators need control over punctuation surrounding interpolated values. This is documented in PostgreSQL's Error Style Guide.

The Real Bug: GetPublicationsStr Function

Once the initial misunderstanding was resolved, Peter Smith identified a genuine i18n defect in the GetPublicationsStr function (introduced in commit 8f2e2bb, ~4 years prior). This function builds comma-separated lists of publication names for two purposes:

  1. SQL construction (quote_literal=true): Commas and quoting must be literal — no translation needed.
  2. Error messages (quote_literal=false): Commas and quoting SHOULD be translatable but were hardcoded.

This means for 4 years, error messages containing publication name lists have been un-translatable in their punctuation — a silent i18n regression.

Proposed Solutions

Patch v1

Separates the two code paths more clearly and wraps both the comma separator and the quotes in _() for the error-message path.

Patch v2

Removes translation of the comma separator alone (based on a separate discussion), keeping only quote translation.

Álvaro's Counter-Proposal

Álvaro Herrera argues that commas ARE translatable (Japanese uses instead of ,; French adds spaces around separators). His approach combines the comma with the quoted item into a single translatable unit: _(", \"%s\"") — giving translators a single string that includes both the separator and the quoting, allowing them to adjust all punctuation holistically.

Design Debate: Leading vs. Trailing Comma

The remaining bikeshed is whether the translatable format should be:

Peter Smith advocates for leading-comma with a first boolean because:

David Rowley suggests trailing comma with foreach_current_index(lc) > 0 check.

Álvaro initially used "last" logic but expressed no strong preference.

Architectural Implications

This is a microcosm of a broader i18n principle in PostgreSQL: any string that reaches the user through ereport/elog must have ALL its visible characters under translator control. This includes:

The fix is small but sets a precedent for how list-building helper functions should handle i18n — by bundling separator punctuation into the translatable format string rather than concatenating it separately.

Current Status

As of the final message (2026-05-18), the patch is stalled. All participants agree on the need for the fix; the only open question is the cosmetic choice of leading vs. trailing comma in the format string. No committer has picked it up for commit.