On Thu, Nov 13, 2025 at 3:08 PM Jacob Champion <[email protected]> wrote: > I'm writing up a patch that combines all of that.
And here's what I have so far. I could use help double-checking the .po result; I'm not entirely sure my usage of update-po is correct. I took this opportunity to address a complaint from Alvaro and Peter E a little while back, that some of the more internal-facing error messages are very difficult to translate (and wouldn't help users even if translation were easy). I can pull that (v2-0002) into its own thread if necessary. - v2-0001: combines Zhijie Hou's patch with the gettext_noop() suggestion from Alvaro and fixes the nls.mk omission - v2-0002: removes translation of multiplexer failures by adding an _internal macro - v2-0003: aligns oauth_json_set_error() with the prior commits - v2-0004: tries to get jsonapi.c translated too Unfortunately v2-0004 doesn't work. It puts the messages into the translation files, but we use the _() macro throughout jsonapi.c, which isn't helpful for libpq because libpq uses its own text domain. This was an oversight in the work done for 0785d1b8b, I think, and it may need its own patchset unless someone has a really quick fix. Please let me know if I forgot to address something already said above. I assume translation changes such as these are generally backportable? Thanks, --Jacob
From 4a7e11a67f44c127bf00446141b9f4e73e9414a4 Mon Sep 17 00:00:00 2001 From: Jacob Champion <[email protected]> Date: Thu, 13 Nov 2025 12:42:00 -0800 Subject: [PATCH v2 1/4] libpq: Add missing OAuth translations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several strings that should have been translated as they passed through libpq_gettext were not actually being pulled into the translation files, because I hadn't directly wrapped them in one of the GETTEXT_TRIGGERS. Move the responsibility for calling libpq_gettext() to the code that sets actx->errctx. Doing the same in report_type_mismatch() would result in double-translation, so mark those strings with gettext_noop() instead. And wrap two ternary operands with gettext_noop(), even though they're already in one of the triggers, since xgettext sees only the first. Finally, fe-auth-oauth.c was missing from nls.mk, so none of that file was being translated at all. Add it now. Original patch by Zhijie Hou, plus suggested tweaks by Álvaro Herrera and small additions by me. Reported-by: Zhijie Hou <[email protected]> Author: Zhijie Hou <[email protected]> Co-authored-by: Álvaro Herrera <[email protected]> Co-authored-by: Jacob Champion <[email protected]> Discussion: https://postgr.es/m/TY4PR01MB1690746DB91991D1E9A47F57E94CDA%40TY4PR01MB16907.jpnprd01.prod.outlook.com Backpatch-through: ? --- src/interfaces/libpq-oauth/oauth-curl.c | 35 +++++++++++++------------ src/interfaces/libpq/nls.mk | 1 + 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/interfaces/libpq-oauth/oauth-curl.c b/src/interfaces/libpq-oauth/oauth-curl.c index 08e300715da..8bd1870cf8a 100644 --- a/src/interfaces/libpq-oauth/oauth-curl.c +++ b/src/interfaces/libpq-oauth/oauth-curl.c @@ -247,7 +247,8 @@ struct async_ctx * our entry point, errors have three parts: * * - errctx: an optional static string, describing the global operation - * currently in progress. It'll be translated for you. + * currently in progress. Should be translated with + * libpq_gettext(). * * - errbuf: contains the actual error message. Generally speaking, use * actx_error[_str] to manipulate this. This must be filled @@ -475,20 +476,20 @@ report_type_mismatch(struct oauth_parse *ctx) switch (ctx->active->type) { case JSON_TOKEN_STRING: - msgfmt = "field \"%s\" must be a string"; + msgfmt = gettext_noop("field \"%s\" must be a string"); break; case JSON_TOKEN_NUMBER: - msgfmt = "field \"%s\" must be a number"; + msgfmt = gettext_noop("field \"%s\" must be a number"); break; case JSON_TOKEN_ARRAY_START: - msgfmt = "field \"%s\" must be an array of strings"; + msgfmt = gettext_noop("field \"%s\" must be an array of strings"); break; default: Assert(false); - msgfmt = "field \"%s\" has unexpected type"; + msgfmt = gettext_noop("field \"%s\" has unexpected type"); } oauth_parse_set_error(ctx, msgfmt, ctx->active->name); @@ -1087,7 +1088,7 @@ parse_token_error(struct async_ctx *actx, struct token_error *err) * override the errctx if parsing explicitly fails. */ if (!result) - actx->errctx = "failed to parse token error response"; + actx->errctx = libpq_gettext("failed to parse token error response"); return result; } @@ -1115,8 +1116,8 @@ record_token_error(struct async_ctx *actx, const struct token_error *err) if (response_code == 401) { actx_error(actx, actx->used_basic_auth - ? "provider rejected the oauth_client_secret" - : "provider requires client authentication, and no oauth_client_secret is set"); + ? gettext_noop("provider rejected the oauth_client_secret") + : gettext_noop("provider requires client authentication, and no oauth_client_secret is set")); actx_error_str(actx, " "); } } @@ -2153,7 +2154,7 @@ finish_discovery(struct async_ctx *actx) /* * Pull the fields we care about from the document. */ - actx->errctx = "failed to parse OpenID discovery document"; + actx->errctx = libpq_gettext("failed to parse OpenID discovery document"); if (!parse_provider(actx, &actx->provider)) return false; /* error message already set */ @@ -2421,7 +2422,7 @@ finish_device_authz(struct async_ctx *actx) */ if (response_code == 200) { - actx->errctx = "failed to parse device authorization"; + actx->errctx = libpq_gettext("failed to parse device authorization"); if (!parse_device_authz(actx, &actx->authz)) return false; /* error message already set */ @@ -2509,7 +2510,7 @@ finish_token_request(struct async_ctx *actx, struct token *tok) */ if (response_code == 200) { - actx->errctx = "failed to parse access token response"; + actx->errctx = libpq_gettext("failed to parse access token response"); if (!parse_access_token(actx, tok)) return false; /* error message already set */ @@ -2888,7 +2889,7 @@ pg_fe_run_oauth_flow_impl(PGconn *conn) switch (actx->step) { case OAUTH_STEP_INIT: - actx->errctx = "failed to fetch OpenID discovery document"; + actx->errctx = libpq_gettext("failed to fetch OpenID discovery document"); if (!start_discovery(actx, conn_oauth_discovery_uri(conn))) goto error_return; @@ -2902,11 +2903,11 @@ pg_fe_run_oauth_flow_impl(PGconn *conn) if (!check_issuer(actx, conn)) goto error_return; - actx->errctx = "cannot run OAuth device authorization"; + actx->errctx = libpq_gettext("cannot run OAuth device authorization"); if (!check_for_device_flow(actx)) goto error_return; - actx->errctx = "failed to obtain device authorization"; + actx->errctx = libpq_gettext("failed to obtain device authorization"); if (!start_device_authz(actx, conn)) goto error_return; @@ -2917,7 +2918,7 @@ pg_fe_run_oauth_flow_impl(PGconn *conn) if (!finish_device_authz(actx)) goto error_return; - actx->errctx = "failed to obtain access token"; + actx->errctx = libpq_gettext("failed to obtain access token"); if (!start_token_request(actx, conn)) goto error_return; @@ -2968,7 +2969,7 @@ pg_fe_run_oauth_flow_impl(PGconn *conn) break; case OAUTH_STEP_WAIT_INTERVAL: - actx->errctx = "failed to obtain access token"; + actx->errctx = libpq_gettext("failed to obtain access token"); if (!start_token_request(actx, conn)) goto error_return; @@ -2994,7 +2995,7 @@ error_return: * also the documentation for struct async_ctx. */ if (actx->errctx) - appendPQExpBuffer(errbuf, "%s: ", libpq_gettext(actx->errctx)); + appendPQExpBuffer(errbuf, "%s: ", actx->errctx); if (PQExpBufferDataBroken(actx->errbuf)) appendPQExpBufferStr(errbuf, libpq_gettext("out of memory")); diff --git a/src/interfaces/libpq/nls.mk b/src/interfaces/libpq/nls.mk index b87df277d93..111e4849ed5 100644 --- a/src/interfaces/libpq/nls.mk +++ b/src/interfaces/libpq/nls.mk @@ -1,6 +1,7 @@ # src/interfaces/libpq/nls.mk CATALOG_NAME = libpq GETTEXT_FILES = fe-auth.c \ + fe-auth-oauth.c \ fe-auth-scram.c \ fe-cancel.c \ fe-connect.c \ -- 2.34.1
v2-0002-libpq-oauth-Don-t-translate-internal-mux-failures.patch
Description: Binary data
v2-0003-libpq-Align-oauth_json_set_error-with-other-NLS-p.patch
Description: Binary data
v2-0004-DO-NOT-MERGE-squash-libpq-Add-missing-OAuth-trans.patch
Description: Binary data
