]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add a regression test to verify that NLS translation works.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 14 Dec 2025 16:55:18 +0000 (11:55 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 14 Dec 2025 16:55:18 +0000 (11:55 -0500)
We've never actually had a formal test for this facility.
It seems worth adding one now, mainly because we are starting
to depend on gettext() being able to handle the PRI* macros
from <inttypes.h>, and it's not all that certain that that
works everywhere.  So the test goes to a bit of effort to
check all the PRI* macros we are likely to use.

(This effort has indeed found one problem already, now fixed
in commit f8715ec86.)

Discussion: https://postgr.es/m/3098752.1765221796@sss.pgh.pa.us
Discussion: https://postgr.es/m/292844.1765315339@sss.pgh.pa.us

src/test/regress/expected/nls.out [new file with mode: 0644]
src/test/regress/expected/nls_1.out [new file with mode: 0644]
src/test/regress/meson.build
src/test/regress/nls.mk [new file with mode: 0644]
src/test/regress/parallel_schedule
src/test/regress/po/LINGUAS [new file with mode: 0644]
src/test/regress/po/es.po [new file with mode: 0644]
src/test/regress/po/meson.build [new file with mode: 0644]
src/test/regress/regress.c
src/test/regress/sql/nls.sql [new file with mode: 0644]

diff --git a/src/test/regress/expected/nls.out b/src/test/regress/expected/nls.out
new file mode 100644 (file)
index 0000000..5a65029
--- /dev/null
@@ -0,0 +1,35 @@
+-- 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;
+-- Some BSDen are sticky about wanting a codeset name in lc_messages,
+-- but it seems that at least on common platforms it doesn't have
+-- to match the actual database encoding.
+SET lc_messages = 'es_ES.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
+ test_translation 
+------------------
+(1 row)
+
+RESET lc_messages;
diff --git a/src/test/regress/expected/nls_1.out b/src/test/regress/expected/nls_1.out
new file mode 100644 (file)
index 0000000..9f1a277
--- /dev/null
@@ -0,0 +1,20 @@
+-- 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;
+-- Some BSDen are sticky about wanting a codeset name in lc_messages,
+-- but it seems that at least on common platforms it doesn't have
+-- to match the actual database encoding.
+SET lc_messages = 'es_ES.UTF-8';
+SELECT test_translation();
+NOTICE:  NLS is not enabled
+ test_translation 
+------------------
+(1 row)
+
+RESET lc_messages;
index 1da9e9462a9afe75f390ca8c95f8e92043c9c101..4001a81ffe52f14698a5b8a0fe3fb936a655efa2 100644 (file)
@@ -57,3 +57,5 @@ tests += {
     'dbname': 'regression',
   },
 }
+
+subdir('po', if_found: libintl)
diff --git a/src/test/regress/nls.mk b/src/test/regress/nls.mk
new file mode 100644 (file)
index 0000000..43227c6
--- /dev/null
@@ -0,0 +1,5 @@
+# src/test/regress/nls.mk
+CATALOG_NAME     = regress
+GETTEXT_FILES    = regress.c
+GETTEXT_TRIGGERS = $(BACKEND_COMMON_GETTEXT_TRIGGERS)
+GETTEXT_FLAGS    = $(BACKEND_COMMON_GETTEXT_FLAGS)
index 89bde9a28506e3bd2fa7d4d44fd9fb116961d8bd..905f9bca95987fa93fbf361b9684c38188dceba3 100644 (file)
@@ -76,7 +76,7 @@ test: brin_bloom brin_multi
 # ----------
 # Another group of parallel tests
 # ----------
-test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual
+test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual
 
 # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other
 # psql depends on create_am
diff --git a/src/test/regress/po/LINGUAS b/src/test/regress/po/LINGUAS
new file mode 100644 (file)
index 0000000..8357fca
--- /dev/null
@@ -0,0 +1 @@
+es
diff --git a/src/test/regress/po/es.po b/src/test/regress/po/es.po
new file mode 100644 (file)
index 0000000..b3021d5
--- /dev/null
@@ -0,0 +1,159 @@
+# 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>"
diff --git a/src/test/regress/po/meson.build b/src/test/regress/po/meson.build
new file mode 100644 (file)
index 0000000..e9bd964
--- /dev/null
@@ -0,0 +1,3 @@
+# Copyright (c) 2022-2025, PostgreSQL Global Development Group
+
+nls_targets += [i18n.gettext('regress-' + pg_version_major.to_string())]
index c27305cf10bef5bc7974988bb566ba2b8139d12d..26ae0a6c78785d48aa5ca7e6dbbd47e48e71ef88 100644 (file)
 #include "utils/rel.h"
 #include "utils/typcache.h"
 
+/* define our text domain for translations */
+#undef TEXTDOMAIN
+#define TEXTDOMAIN PG_TEXTDOMAIN("regress")
+
 #define EXPECT_TRUE(expr)      \
        do { \
                if (!(expr)) \
@@ -1149,3 +1153,76 @@ test_relpath(PG_FUNCTION_ARGS)
 
        PG_RETURN_VOID();
 }
+
+/*
+ * Simple test to verify NLS support, particularly that the PRI* macros work.
+ */
+PG_FUNCTION_INFO_V1(test_translation);
+Datum
+test_translation(PG_FUNCTION_ARGS)
+{
+#ifdef ENABLE_NLS
+       static bool inited = false;
+
+       /*
+        * Ideally we'd do this bit in a _PG_init() hook.  However, it seems best
+        * that the Solaris hack only get applied in the nls.sql test, so it
+        * doesn't risk affecting other tests that load this module.
+        */
+       if (!inited)
+       {
+               /*
+                * Solaris' built-in gettext is not bright about associating locales
+                * with message catalogs that are named after just the language.
+                * Apparently the customary workaround is for users to set the
+                * LANGUAGE environment variable to provide a mapping.  Do so here to
+                * ensure that the nls.sql regression test will work.
+                */
+#if defined(__sun__)
+               setenv("LANGUAGE", "es_ES.UTF-8:es", 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");
+#endif
+
+       PG_RETURN_VOID();
+}
diff --git a/src/test/regress/sql/nls.sql b/src/test/regress/sql/nls.sql
new file mode 100644 (file)
index 0000000..efeda8c
--- /dev/null
@@ -0,0 +1,19 @@
+-- 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;
+
+-- Some BSDen are sticky about wanting a codeset name in lc_messages,
+-- but it seems that at least on common platforms it doesn't have
+-- to match the actual database encoding.
+SET lc_messages = 'es_ES.UTF-8';
+
+SELECT test_translation();
+
+RESET lc_messages;