1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-18 05:01:01 +03:00

Avoid requiring Spanish locale to test NLS infrastructure.

I had supposed that the majority of machines with gettext installed
would have most language locales installed, but at least in the
buildfarm it turns out less than half have es_ES installed.  So
depending on that to run the test now seems like a bad idea.  But it
turns out that gettext can be persuaded to "translate" even in the C
locale, as long as you fake out its short-circuit logic by spelling
the locale name like "C.UTF-8" or similar.  (Many thanks to Bryan
Green for correcting my misconceptions about that.)  Quick testing
suggests that that spelling is accepted by most platforms, though
again the buildfarm may show that "most" isn't "all".

Hence, remove the es_ES dependency and instead create a "C" message
catalog.  I've made the test unconditionally set lc_messages to
'C.UTF-8'.  That approach might need adjustment depending on what
the buildfarm shows, but let's keep it simple until proven wrong.

While at it, tweak the test so that we run the various ereport's
even when !ENABLE_NLS.  This is useful to verify that the macros
provided by <inttypes.h> are compatible with snprintf.c, as we
now know is worth questioning.

Discussion: https://postgr.es/m/1991599.1765818338@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2025-12-15 15:16:26 -05:00
parent 95a19fefdc
commit 7db6809ced
8 changed files with 254 additions and 331 deletions

View File

@@ -6,50 +6,29 @@ CREATE FUNCTION test_translation()
RETURNS void
AS :'regresslib'
LANGUAGE C;
-- There's less standardization in locale name spellings than one could wish.
-- While some platforms insist on having a codeset name in lc_messages,
-- fortunately it seems that it need not match the actual database encoding.
-- However, if no es_ES locale is installed at all, this'll fail.
SET lc_messages = 'C';
do $$
declare locale text; ok bool;
begin
for locale in values('es_ES'), ('es_ES.UTF-8'), ('es_ES.utf8')
loop
ok = true;
begin
execute format('set lc_messages = %L', locale);
exception when invalid_parameter_value then
ok = false;
end;
exit when ok;
end loop;
-- Don't clutter the expected results with this info, just log it
raise log 'NLS regression test: lc_messages = %',
current_setting('lc_messages');
end $$;
SELECT current_setting('lc_messages') = 'C' AS failed \gset
\if :failed
\echo Could not find an acceptable spelling of es_ES locale
\quit
\endif
-- We don't want to assume that the platform has any particular language
-- installed, so we use a "translation" for the C locale. However, gettext
-- will short-circuit translation if lc_messages is just 'C'. Fake it out
-- by appending a codeset name. Fortunately it seems that that need not
-- match the actual database encoding.
SET lc_messages = 'C.UTF-8';
SELECT test_translation();
NOTICE: traducido PRId64 = 424242424242
NOTICE: traducido PRId32 = -1234
NOTICE: traducido PRIdMAX = -5678
NOTICE: traducido PRIdPTR = 9999
NOTICE: traducido PRIu64 = 424242424242
NOTICE: traducido PRIu32 = 1234
NOTICE: traducido PRIuMAX = 5678
NOTICE: traducido PRIuPTR = 9999
NOTICE: traducido PRIx64 = 62c6d1a9b2
NOTICE: traducido PRIx32 = 4d2
NOTICE: traducido PRIxMAX = 162e
NOTICE: traducido PRIxPTR = 270f
NOTICE: traducido PRIX64 = 62C6D1A9B2
NOTICE: traducido PRIX32 = 4D2
NOTICE: traducido PRIXMAX = 162E
NOTICE: traducido PRIXPTR = 270F
NOTICE: translated PRId64 = 424242424242
NOTICE: translated PRId32 = -1234
NOTICE: translated PRIdMAX = -123456789012
NOTICE: translated PRIdPTR = -9999
NOTICE: translated PRIu64 = 424242424242
NOTICE: translated PRIu32 = 4294966062
NOTICE: translated PRIuMAX = 123456789012
NOTICE: translated PRIuPTR = 9999
NOTICE: translated PRIx64 = 62c6d1a9b2
NOTICE: translated PRIx32 = fffffb2e
NOTICE: translated PRIxMAX = 1cbe991a14
NOTICE: translated PRIxPTR = 270f
NOTICE: translated PRIX64 = 62C6D1A9B2
NOTICE: translated PRIX32 = FFFFFB2E
NOTICE: translated PRIXMAX = 1CBE991A14
NOTICE: translated PRIXPTR = 270F
test_translation
------------------

View File

@@ -6,35 +6,30 @@ CREATE FUNCTION test_translation()
RETURNS void
AS :'regresslib'
LANGUAGE C;
-- There's less standardization in locale name spellings than one could wish.
-- While some platforms insist on having a codeset name in lc_messages,
-- fortunately it seems that it need not match the actual database encoding.
-- However, if no es_ES locale is installed at all, this'll fail.
SET lc_messages = 'C';
do $$
declare locale text; ok bool;
begin
for locale in values('es_ES'), ('es_ES.UTF-8'), ('es_ES.utf8')
loop
ok = true;
begin
execute format('set lc_messages = %L', locale);
exception when invalid_parameter_value then
ok = false;
end;
exit when ok;
end loop;
-- Don't clutter the expected results with this info, just log it
raise log 'NLS regression test: lc_messages = %',
current_setting('lc_messages');
end $$;
SELECT current_setting('lc_messages') = 'C' AS failed \gset
\if :failed
\echo Could not find an acceptable spelling of es_ES locale
\quit
\endif
-- We don't want to assume that the platform has any particular language
-- installed, so we use a "translation" for the C locale. However, gettext
-- will short-circuit translation if lc_messages is just 'C'. Fake it out
-- by appending a codeset name. Fortunately it seems that that need not
-- match the actual database encoding.
SET lc_messages = 'C.UTF-8';
SELECT test_translation();
NOTICE: NLS is not enabled
NOTICE: untranslated PRId64 = 424242424242
NOTICE: untranslated PRId32 = -1234
NOTICE: untranslated PRIdMAX = -123456789012
NOTICE: untranslated PRIdPTR = -9999
NOTICE: untranslated PRIu64 = 424242424242
NOTICE: untranslated PRIu32 = 4294966062
NOTICE: untranslated PRIuMAX = 123456789012
NOTICE: untranslated PRIuPTR = 9999
NOTICE: untranslated PRIx64 = 62c6d1a9b2
NOTICE: untranslated PRIx32 = fffffb2e
NOTICE: untranslated PRIxMAX = 1cbe991a14
NOTICE: untranslated PRIxPTR = 270f
NOTICE: untranslated PRIX64 = 62C6D1A9B2
NOTICE: untranslated PRIX32 = FFFFFB2E
NOTICE: untranslated PRIXMAX = 1CBE991A14
NOTICE: untranslated PRIXPTR = 270F
test_translation
------------------

View File

@@ -1,35 +0,0 @@
-- directory paths and dlsuffix are passed to us in environment variables
\getenv libdir PG_LIBDIR
\getenv dlsuffix PG_DLSUFFIX
\set regresslib :libdir '/regress' :dlsuffix
CREATE FUNCTION test_translation()
RETURNS void
AS :'regresslib'
LANGUAGE C;
-- There's less standardization in locale name spellings than one could wish.
-- While some platforms insist on having a codeset name in lc_messages,
-- fortunately it seems that it need not match the actual database encoding.
-- However, if no es_ES locale is installed at all, this'll fail.
SET lc_messages = 'C';
do $$
declare locale text; ok bool;
begin
for locale in values('es_ES'), ('es_ES.UTF-8'), ('es_ES.utf8')
loop
ok = true;
begin
execute format('set lc_messages = %L', locale);
exception when invalid_parameter_value then
ok = false;
end;
exit when ok;
end loop;
-- Don't clutter the expected results with this info, just log it
raise log 'NLS regression test: lc_messages = %',
current_setting('lc_messages');
end $$;
SELECT current_setting('lc_messages') = 'C' AS failed \gset
\if :failed
\echo Could not find an acceptable spelling of es_ES locale
Could not find an acceptable spelling of es_ES locale
\quit

161
src/test/regress/po/C.po Normal file
View File

@@ -0,0 +1,161 @@
# C message translation file for regress test library
#
# Note that we don't need translation of this library into non-English.
#
# Copyright (C) 2025 PostgreSQL Global Development Group
# This file is distributed under the same license as the regress (PostgreSQL) package.
#
# Tom Lane <tgl@sss.pgh.pa.us>, 2025.
#
msgid ""
msgstr ""
"Project-Id-Version: regress (PostgreSQL) 19\n"
"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
"POT-Creation-Date: 2025-12-15 14:28-0500\n"
"PO-Revision-Date: 2025-12-15 14:28-0500\n"
"Last-Translator: Tom Lane <tgl@sss.pgh.pa.us>\n"
"Language-Team: PG Hackers <pgsql-hackers@lists.postgresql.org>\n"
"Language: C\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: regress.c:202
#, c-format
msgid "invalid input syntax for type %s: \"%s\""
msgstr ""
#: regress.c:839
#, c-format
msgid "test_inline_in_from_support_func called with %d args but expected 3"
msgstr ""
#: regress.c:847 regress.c:863
#, c-format
msgid "test_inline_in_from_support_func called with non-Const parameters"
msgstr ""
#: regress.c:854 regress.c:870
#, c-format
msgid "test_inline_in_from_support_func called with non-TEXT parameters"
msgstr ""
#: regress.c:903
#, c-format
msgid "test_inline_in_from_support_func parsed to more than one node"
msgstr ""
#: regress.c:914
#, c-format
msgid "test_inline_in_from_support_func rewrote to more than one node"
msgstr ""
#: regress.c:921
#, c-format
msgid "test_inline_in_from_support_func didn't parse to a Query"
msgstr ""
#: regress.c:1028
#, c-format
msgid "invalid source encoding name \"%s\""
msgstr ""
#: regress.c:1033
#, c-format
msgid "invalid destination encoding name \"%s\""
msgstr ""
#: regress.c:1078
#, c-format
msgid "default conversion function for encoding \"%s\" to \"%s\" does not exist"
msgstr ""
#: regress.c:1085
#, c-format
msgid "out of memory"
msgstr ""
#: regress.c:1086
#, c-format
msgid "String of %d bytes is too long for encoding conversion."
msgstr ""
#: regress.c:1197
#, c-format
msgid "untranslated PRId64 = %<PRId64>"
msgstr "translated PRId64 = %<PRId64>"
#: regress.c:1199
#, c-format
msgid "untranslated PRId32 = %<PRId32>"
msgstr "translated PRId32 = %<PRId32>"
#: regress.c:1201
#, c-format
msgid "untranslated PRIdMAX = %<PRIdMAX>"
msgstr "translated PRIdMAX = %<PRIdMAX>"
#: regress.c:1203
#, c-format
msgid "untranslated PRIdPTR = %<PRIdPTR>"
msgstr "translated PRIdPTR = %<PRIdPTR>"
#: regress.c:1206
#, c-format
msgid "untranslated PRIu64 = %<PRIu64>"
msgstr "translated PRIu64 = %<PRIu64>"
#: regress.c:1208
#, c-format
msgid "untranslated PRIu32 = %<PRIu32>"
msgstr "translated PRIu32 = %<PRIu32>"
#: regress.c:1210
#, c-format
msgid "untranslated PRIuMAX = %<PRIuMAX>"
msgstr "translated PRIuMAX = %<PRIuMAX>"
#: regress.c:1212
#, c-format
msgid "untranslated PRIuPTR = %<PRIuPTR>"
msgstr "translated PRIuPTR = %<PRIuPTR>"
#: regress.c:1215
#, c-format
msgid "untranslated PRIx64 = %<PRIx64>"
msgstr "translated PRIx64 = %<PRIx64>"
#: regress.c:1217
#, c-format
msgid "untranslated PRIx32 = %<PRIx32>"
msgstr "translated PRIx32 = %<PRIx32>"
#: regress.c:1219
#, c-format
msgid "untranslated PRIxMAX = %<PRIxMAX>"
msgstr "translated PRIxMAX = %<PRIxMAX>"
#: regress.c:1221
#, c-format
msgid "untranslated PRIxPTR = %<PRIxPTR>"
msgstr "translated PRIxPTR = %<PRIxPTR>"
#: regress.c:1224
#, c-format
msgid "untranslated PRIX64 = %<PRIX64>"
msgstr "translated PRIX64 = %<PRIX64>"
#: regress.c:1226
#, c-format
msgid "untranslated PRIX32 = %<PRIX32>"
msgstr "translated PRIX32 = %<PRIX32>"
#: regress.c:1228
#, c-format
msgid "untranslated PRIXMAX = %<PRIXMAX>"
msgstr "translated PRIXMAX = %<PRIXMAX>"
#: regress.c:1230
#, c-format
msgid "untranslated PRIXPTR = %<PRIXPTR>"
msgstr "translated PRIXPTR = %<PRIXPTR>"

View File

@@ -1 +1 @@
es
C

View File

@@ -1,159 +0,0 @@
# Spanish message translation file for regress test library
#
# Copyright (C) 2025 PostgreSQL Global Development Group
# This file is distributed under the same license as the regress (PostgreSQL) package.
#
# Tom Lane <tgl@sss.pgh.pa.us>, 2025.
#
msgid ""
msgstr ""
"Project-Id-Version: regress (PostgreSQL) 19\n"
"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
"POT-Creation-Date: 2025-12-08 13:57-0500\n"
"PO-Revision-Date: 2025-11-19 19:01-0500\n"
"Last-Translator: Tom Lane <tgl@sss.pgh.pa.us>\n"
"Language-Team: PgSQL-es-Ayuda <pgsql-es-ayuda@lists.postgresql.org>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: regress.c:202
#, c-format
msgid "invalid input syntax for type %s: \"%s\""
msgstr "la sintaxis de entrada no es válida para tipo %s: «%s»"
#: regress.c:839
#, c-format
msgid "test_inline_in_from_support_func called with %d args but expected 3"
msgstr ""
#: regress.c:847 regress.c:863
#, c-format
msgid "test_inline_in_from_support_func called with non-Const parameters"
msgstr ""
#: regress.c:854 regress.c:870
#, c-format
msgid "test_inline_in_from_support_func called with non-TEXT parameters"
msgstr ""
#: regress.c:903
#, c-format
msgid "test_inline_in_from_support_func parsed to more than one node"
msgstr ""
#: regress.c:914
#, c-format
msgid "test_inline_in_from_support_func rewrote to more than one node"
msgstr ""
#: regress.c:921
#, c-format
msgid "test_inline_in_from_support_func didn't parse to a Query"
msgstr ""
#: regress.c:1028
#, c-format
msgid "invalid source encoding name \"%s\""
msgstr "la codificación de origen «%s» no es válida"
#: regress.c:1033
#, c-format
msgid "invalid destination encoding name \"%s\""
msgstr "la codificación de destino «%s» no es válida"
#: regress.c:1078
#, c-format
msgid "default conversion function for encoding \"%s\" to \"%s\" does not exist"
msgstr "no existe el procedimiento por omisión de conversión desde la codificación «%s» a «%s»"
#: regress.c:1085
#, c-format
msgid "out of memory"
msgstr "memoria agotada"
#: regress.c:1086
#, c-format
msgid "String of %d bytes is too long for encoding conversion."
msgstr "La cadena de %d bytes es demasiado larga para la recodificación."
#: regress.c:1175
#, c-format
msgid "translated PRId64 = %<PRId64>"
msgstr "traducido PRId64 = %<PRId64>"
#: regress.c:1177
#, c-format
msgid "translated PRId32 = %<PRId32>"
msgstr "traducido PRId32 = %<PRId32>"
#: regress.c:1179
#, c-format
msgid "translated PRIdMAX = %<PRIdMAX>"
msgstr "traducido PRIdMAX = %<PRIdMAX>"
#: regress.c:1181
#, c-format
msgid "translated PRIdPTR = %<PRIdPTR>"
msgstr "traducido PRIdPTR = %<PRIdPTR>"
#: regress.c:1184
#, c-format
msgid "translated PRIu64 = %<PRIu64>"
msgstr "traducido PRIu64 = %<PRIu64>"
#: regress.c:1186
#, c-format
msgid "translated PRIu32 = %<PRIu32>"
msgstr "traducido PRIu32 = %<PRIu32>"
#: regress.c:1188
#, c-format
msgid "translated PRIuMAX = %<PRIuMAX>"
msgstr "traducido PRIuMAX = %<PRIuMAX>"
#: regress.c:1190
#, c-format
msgid "translated PRIuPTR = %<PRIuPTR>"
msgstr "traducido PRIuPTR = %<PRIuPTR>"
#: regress.c:1193
#, c-format
msgid "translated PRIx64 = %<PRIx64>"
msgstr "traducido PRIx64 = %<PRIx64>"
#: regress.c:1195
#, c-format
msgid "translated PRIx32 = %<PRIx32>"
msgstr "traducido PRIx32 = %<PRIx32>"
#: regress.c:1197
#, c-format
msgid "translated PRIxMAX = %<PRIxMAX>"
msgstr "traducido PRIxMAX = %<PRIxMAX>"
#: regress.c:1199
#, c-format
msgid "translated PRIxPTR = %<PRIxPTR>"
msgstr "traducido PRIxPTR = %<PRIxPTR>"
#: regress.c:1202
#, c-format
msgid "translated PRIX64 = %<PRIX64>"
msgstr "traducido PRIX64 = %<PRIX64>"
#: regress.c:1204
#, c-format
msgid "translated PRIX32 = %<PRIX32>"
msgstr "traducido PRIX32 = %<PRIX32>"
#: regress.c:1206
#, c-format
msgid "translated PRIXMAX = %<PRIXMAX>"
msgstr "traducido PRIXMAX = %<PRIXMAX>"
#: regress.c:1208
#, c-format
msgid "translated PRIXPTR = %<PRIXPTR>"
msgstr "traducido PRIXPTR = %<PRIXPTR>"

View File

@@ -1179,50 +1179,55 @@ test_translation(PG_FUNCTION_ARGS)
* ensure that the nls.sql regression test will work.
*/
#if defined(__sun__)
setenv("LANGUAGE", "es_ES.UTF-8:es", 1);
setenv("LANGUAGE", "C.UTF-8:C", 1);
#endif
pg_bindtextdomain(TEXTDOMAIN);
inited = true;
}
ereport(NOTICE,
errmsg("translated PRId64 = %" PRId64, (int64) 424242424242));
ereport(NOTICE,
errmsg("translated PRId32 = %" PRId32, (int32) -1234));
ereport(NOTICE,
errmsg("translated PRIdMAX = %" PRIdMAX, (intmax_t) -5678));
ereport(NOTICE,
errmsg("translated PRIdPTR = %" PRIdPTR, (intptr_t) 9999));
ereport(NOTICE,
errmsg("translated PRIu64 = %" PRIu64, (uint64) 424242424242));
ereport(NOTICE,
errmsg("translated PRIu32 = %" PRIu32, (uint32) 1234));
ereport(NOTICE,
errmsg("translated PRIuMAX = %" PRIuMAX, (uintmax_t) 5678));
ereport(NOTICE,
errmsg("translated PRIuPTR = %" PRIuPTR, (uintptr_t) 9999));
ereport(NOTICE,
errmsg("translated PRIx64 = %" PRIx64, (uint64) 424242424242));
ereport(NOTICE,
errmsg("translated PRIx32 = %" PRIx32, (uint32) 1234));
ereport(NOTICE,
errmsg("translated PRIxMAX = %" PRIxMAX, (uintmax_t) 5678));
ereport(NOTICE,
errmsg("translated PRIxPTR = %" PRIxPTR, (uintptr_t) 9999));
ereport(NOTICE,
errmsg("translated PRIX64 = %" PRIX64, (uint64) 424242424242));
ereport(NOTICE,
errmsg("translated PRIX32 = %" PRIX32, (uint32) 1234));
ereport(NOTICE,
errmsg("translated PRIXMAX = %" PRIXMAX, (uintmax_t) 5678));
ereport(NOTICE,
errmsg("translated PRIXPTR = %" PRIXPTR, (uintptr_t) 9999));
#else
elog(NOTICE, "NLS is not enabled");
/*
* In non-NLS builds, we still run the ereport calls, to verify that the
* platform's PRI* macros are compatible with snprintf.c.
*/
#endif
ereport(NOTICE,
errmsg("untranslated PRId64 = %" PRId64, (int64) 424242424242));
ereport(NOTICE,
errmsg("untranslated PRId32 = %" PRId32, (int32) -1234));
ereport(NOTICE,
errmsg("untranslated PRIdMAX = %" PRIdMAX, (intmax_t) -123456789012));
ereport(NOTICE,
errmsg("untranslated PRIdPTR = %" PRIdPTR, (intptr_t) -9999));
ereport(NOTICE,
errmsg("untranslated PRIu64 = %" PRIu64, (uint64) 424242424242));
ereport(NOTICE,
errmsg("untranslated PRIu32 = %" PRIu32, (uint32) -1234));
ereport(NOTICE,
errmsg("untranslated PRIuMAX = %" PRIuMAX, (uintmax_t) 123456789012));
ereport(NOTICE,
errmsg("untranslated PRIuPTR = %" PRIuPTR, (uintptr_t) 9999));
ereport(NOTICE,
errmsg("untranslated PRIx64 = %" PRIx64, (uint64) 424242424242));
ereport(NOTICE,
errmsg("untranslated PRIx32 = %" PRIx32, (uint32) -1234));
ereport(NOTICE,
errmsg("untranslated PRIxMAX = %" PRIxMAX, (uintmax_t) 123456789012));
ereport(NOTICE,
errmsg("untranslated PRIxPTR = %" PRIxPTR, (uintptr_t) 9999));
ereport(NOTICE,
errmsg("untranslated PRIX64 = %" PRIX64, (uint64) 424242424242));
ereport(NOTICE,
errmsg("untranslated PRIX32 = %" PRIX32, (uint32) -1234));
ereport(NOTICE,
errmsg("untranslated PRIXMAX = %" PRIXMAX, (uintmax_t) 123456789012));
ereport(NOTICE,
errmsg("untranslated PRIXPTR = %" PRIXPTR, (uintptr_t) 9999));
PG_RETURN_VOID();
}

View File

@@ -9,35 +9,12 @@ CREATE FUNCTION test_translation()
AS :'regresslib'
LANGUAGE C;
-- There's less standardization in locale name spellings than one could wish.
-- While some platforms insist on having a codeset name in lc_messages,
-- fortunately it seems that it need not match the actual database encoding.
-- However, if no es_ES locale is installed at all, this'll fail.
SET lc_messages = 'C';
do $$
declare locale text; ok bool;
begin
for locale in values('es_ES'), ('es_ES.UTF-8'), ('es_ES.utf8')
loop
ok = true;
begin
execute format('set lc_messages = %L', locale);
exception when invalid_parameter_value then
ok = false;
end;
exit when ok;
end loop;
-- Don't clutter the expected results with this info, just log it
raise log 'NLS regression test: lc_messages = %',
current_setting('lc_messages');
end $$;
SELECT current_setting('lc_messages') = 'C' AS failed \gset
\if :failed
\echo Could not find an acceptable spelling of es_ES locale
\quit
\endif
-- We don't want to assume that the platform has any particular language
-- installed, so we use a "translation" for the C locale. However, gettext
-- will short-circuit translation if lc_messages is just 'C'. Fake it out
-- by appending a codeset name. Fortunately it seems that that need not
-- match the actual database encoding.
SET lc_messages = 'C.UTF-8';
SELECT test_translation();