diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index d2315fb1f6b43fcba1fca249a742510a35fc911f..178c55ad5969567586e37791c7771f497427e44e 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -42,7 +42,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.206 2008/09/01 20:42:45 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.207 2008/10/09 17:24:05 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -160,7 +160,7 @@ static void write_csvlog(ErrorData *edata);
  */
 bool
 errstart(int elevel, const char *filename, int lineno,
-		 const char *funcname)
+		 const char *funcname, const char *domain)
 {
 	ErrorData  *edata;
 	bool		output_to_server;
@@ -290,6 +290,8 @@ errstart(int elevel, const char *filename, int lineno,
 	edata->filename = filename;
 	edata->lineno = lineno;
 	edata->funcname = funcname;
+	/* the default text domain is the backend's */
+	edata->domain = domain ? domain : "postgres";
 	/* Select default errcode based on elevel */
 	if (elevel >= ERROR)
 		edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
@@ -611,7 +613,7 @@ errcode_for_socket_access(void)
 		char		   *fmtbuf; \
 		StringInfoData	buf; \
 		/* Internationalize the error format string */ \
-		fmt = _(fmt); \
+		fmt = dgettext(edata->domain, fmt); \
 		/* Expand %m in format string */ \
 		fmtbuf = expand_fmt_string(fmt, edata); \
 		initStringInfo(&buf); \
@@ -982,7 +984,7 @@ elog_finish(int elevel, const char *fmt,...)
 	 */
 	errordata_stack_depth--;
 	errno = edata->saved_errno;
-	if (!errstart(elevel, edata->filename, edata->lineno, edata->funcname))
+	if (!errstart(elevel, edata->filename, edata->lineno, edata->funcname, NULL))
 		return;					/* nothing to do */
 
 	/*
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 5369da439b6a8a270e07ce6771d0f476be0d1775..c3b26698e2a70558b657d69cf141edbab47b6004 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.167 2008/03/27 17:24:16 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.168 2008/10/09 17:24:05 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1212,3 +1212,17 @@ process_local_preload_libraries(void)
 				   "local_preload_libraries",
 				   true);
 }
+
+void
+set_text_domain(const char *domain)
+{
+#ifdef ENABLE_NLS
+	if (my_exec_path[0] != '\0')
+	{
+		char	locale_path[MAXPGPATH];
+
+		get_locale_path(my_exec_path, locale_path);
+		bindtextdomain(domain, locale_path);
+	}
+#endif
+}
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 3d1511e58a525a585fc567f7544c766c1a89308a..98e28e0d10bd7558c9a7ed659103a0d465d95382 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.202 2008/04/23 13:44:59 mha Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.203 2008/10/09 17:24:05 alvherre Exp $
  *
  * NOTES
  *	  some of the information in this file should be moved to other files.
@@ -329,6 +329,7 @@ extern void RecordSharedMemoryInLockFile(unsigned long id1,
 extern void ValidatePgVersion(const char *path);
 extern void process_shared_preload_libraries(void);
 extern void process_local_preload_libraries(void);
+extern void set_text_domain(const char *domain);
 
 /* in access/transam/xlog.c */
 extern bool BackupInProgress(void);
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 034fd420b51466556497a57c11727f28af10d04d..982e3b2c6551f240f21217d34c9bc6324b7dca72 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.94 2008/09/01 20:42:45 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.95 2008/10/09 17:24:05 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -92,14 +92,26 @@
  * ERRCODE_INTERNAL_ERROR if elevel is ERROR or more, ERRCODE_WARNING
  * if elevel is WARNING, or ERRCODE_SUCCESSFUL_COMPLETION if elevel is
  * NOTICE or below.
+ *
+ * ereport_domain() allows a message domain to be specified, for modules that
+ * wish to use a different message catalog from the backend's.	To avoid having
+ * one copy of the default text domain per .o file, we define it as NULL here
+ * and have errstart insert the default text domain.  Modules can either use
+ * ereport_domain() directly, or preferrably they can override the TEXTDOMAIN
+ * macro.
  *----------
  */
-#define ereport(elevel, rest)  \
-	(errstart(elevel, __FILE__, __LINE__, PG_FUNCNAME_MACRO) ? \
+#define ereport_domain(elevel, domain, rest)	\
+	(errstart(elevel, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain) ? \
 	 (errfinish rest) : (void) 0)
 
+#define ereport(level, rest)	\
+	ereport_domain(level, TEXTDOMAIN, rest)
+
+#define TEXTDOMAIN NULL
+
 extern bool errstart(int elevel, const char *filename, int lineno,
-		 const char *funcname);
+		 const char *funcname, const char *domain);
 extern void errfinish(int dummy,...);
 
 extern int	errcode(int sqlerrcode);
@@ -269,6 +281,7 @@ typedef struct ErrorData
 	const char *filename;		/* __FILE__ of ereport() call */
 	int			lineno;			/* __LINE__ of ereport() call */
 	const char *funcname;		/* __func__ of ereport() call */
+	const char *domain;			/* message domain, NULL if default */
 	int			sqlerrcode;		/* encoded ERRSTATE */
 	char	   *message;		/* primary error message */
 	char	   *detail;			/* detail error message */
diff --git a/src/pl/plperl/nls.mk b/src/pl/plperl/nls.mk
new file mode 100644
index 0000000000000000000000000000000000000000..a17dc4ac9ee019d32813727ca05cfba27e953f46
--- /dev/null
+++ b/src/pl/plperl/nls.mk
@@ -0,0 +1,5 @@
+# $PostgreSQL: pgsql/src/pl/plperl/nls.mk,v 1.1 2008/10/09 17:24:05 alvherre Exp $
+CATALOG_NAME	:= plperl
+AVAIL_LANGUAGES	:=
+GETTEXT_FILES	:= plperl.c SPI.xs
+GETTEXT_TRIGGERS:= _ errmsg errdetail errdetail_log errhint errcontext write_stderr croak Perl_croak
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 1bf95d96059bfe20c8e0198fc2ed93cd60e76673..073e41d4006c4ad99d2acc7e60edcd15157c4063 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1,7 +1,7 @@
 /**********************************************************************
  * plperl.c - perl as a procedural language for PostgreSQL
  *
- *	  $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.139 2008/03/28 00:21:56 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.140 2008/10/09 17:24:05 alvherre Exp $
  *
  **********************************************************************/
 
@@ -30,6 +30,10 @@
 #include "utils/typcache.h"
 #include "utils/hsearch.h"
 
+/* define our text domain for translations */
+#undef TEXTDOMAIN
+#define TEXTDOMAIN "plperl"
+
 /* perl stuff */
 #include "plperl.h"
 
@@ -186,8 +190,10 @@ _PG_init(void)
 	if (inited)
 		return;
 
+	set_text_domain(TEXTDOMAIN);
+
 	DefineCustomBoolVariable("plperl.use_strict",
-	  "If true, will compile trusted and untrusted perl code in strict mode",
+	  gettext_noop("If true, will compile trusted and untrusted perl code in strict mode"),
 							 NULL,
 							 &plperl_use_strict,
 							 PGC_USERSET,
diff --git a/src/pl/plpgsql/src/nls.mk b/src/pl/plpgsql/src/nls.mk
new file mode 100644
index 0000000000000000000000000000000000000000..ddc585fc8d67af0bcf7810842eb6f5ce9ceac34e
--- /dev/null
+++ b/src/pl/plpgsql/src/nls.mk
@@ -0,0 +1,8 @@
+# $PostgreSQL: pgsql/src/pl/plpgsql/src/nls.mk,v 1.1 2008/10/09 17:24:05 alvherre Exp $
+CATALOG_NAME	:= plpgsql
+AVAIL_LANGUAGES	:=
+GETTEXT_FILES	:= pl_comp.c pl_exec.c pl_gram.c pl_funcs.c pl_handler.c pl_scan.c
+GETTEXT_TRIGGERS:= _ errmsg errdetail errdetail_log errhint errcontext write_stderr yyerror
+
+.PHONY: gettext-files
+gettext-files: distprep
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index 818690501b0334192438cdca4a8ae8ea55e42cf0..223d06f7b6f615e727a4df7eaefb8994f988fffa 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.40 2008/08/29 13:02:33 petere Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.41 2008/10/09 17:24:05 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,6 +42,8 @@ _PG_init(void)
 	if (inited)
 		return;
 
+	set_text_domain(TEXTDOMAIN);
+
 	plpgsql_HashTableInit();
 	RegisterXactCallback(plpgsql_xact_cb, NULL);
 	RegisterSubXactCallback(plpgsql_subxact_cb, NULL);
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 8cc050773fbb1f2ce3e708fc98f9573c23b64246..95e69465638c75f4cc9c441263154d65055d9749 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.101 2008/10/09 16:35:07 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.102 2008/10/09 17:24:05 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,6 +28,10 @@
  * Definitions
  **********************************************************************/
 
+/* define our text domain for translations */
+#undef TEXTDOMAIN
+#define TEXTDOMAIN "plpgsql"
+
 /* ----------
  * Compiler's namestack item types
  * ----------
diff --git a/src/pl/plpython/nls.mk b/src/pl/plpython/nls.mk
new file mode 100644
index 0000000000000000000000000000000000000000..72b9ca525d45d9d5dad72bcd4a255415db439928
--- /dev/null
+++ b/src/pl/plpython/nls.mk
@@ -0,0 +1,5 @@
+# $PostgreSQL: pgsql/src/pl/plpython/nls.mk,v 1.1 2008/10/09 17:24:05 alvherre Exp $
+CATALOG_NAME	:= plpython
+AVAIL_LANGUAGES	:=
+GETTEXT_FILES	:= plpython.c
+GETTEXT_TRIGGERS:= _ errmsg errdetail errdetail_log errhint errcontext write_stderr yyerror
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index c4d6803fcf407a027560bb4c8a081333f9cce1f0..ae17289cd263ef2cd663517e7dfc382cff8c8ff7 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -1,7 +1,7 @@
 /**********************************************************************
  * plpython.c - python as a procedural language for PostgreSQL
  *
- *	$PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.112 2008/07/18 03:32:53 tgl Exp $
+ *	$PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.113 2008/10/09 17:24:05 alvherre Exp $
  *
  *********************************************************************
  */
@@ -63,6 +63,10 @@ typedef int Py_ssize_t;
 #include "utils/syscache.h"
 #include "utils/typcache.h"
 
+/* define our text domain for translations */
+#undef TEXTDOMAIN
+#define TEXTDOMAIN "plpython"
+
 #include <compile.h>
 #include <eval.h>
 
@@ -2745,6 +2749,8 @@ _PG_init(void)
 	if (inited)
 		return;
 
+	set_text_domain(TEXTDOMAIN);
+
 	Py_Initialize();
 	PLy_init_interp();
 	PLy_init_plpy();
diff --git a/src/pl/tcl/nls.mk b/src/pl/tcl/nls.mk
new file mode 100644
index 0000000000000000000000000000000000000000..1630b6c1e44d06c857c91da6ceafb73a914be912
--- /dev/null
+++ b/src/pl/tcl/nls.mk
@@ -0,0 +1,5 @@
+# $PostgreSQL: pgsql/src/pl/tcl/nls.mk,v 1.1 2008/10/09 17:24:05 alvherre Exp $
+CATALOG_NAME	:= pltcl
+AVAIL_LANGUAGES	:=
+GETTEXT_FILES	:= pltcl.c
+GETTEXT_TRIGGERS:= _ errmsg errdetail errdetail_log errhint errcontext write_stderr yyerror
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index e9fdf9fc38f0bdd7a70f339714814bbe38c5edaf..1bbab485d1cfd9ea3e4f8b27187dca584b5efb29 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -2,7 +2,7 @@
  * pltcl.c		- PostgreSQL support for Tcl as
  *				  procedural language (PL)
  *
- *	  $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.121 2008/06/17 00:52:43 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.122 2008/10/09 17:24:05 alvherre Exp $
  *
  **********************************************************************/
 
@@ -41,6 +41,10 @@
 #define Tcl_GetStringResult(interp)  ((interp)->result)
 #endif
 
+/* define our text domain for translations */
+#undef TEXTDOMAIN
+#define TEXTDOMAIN "pltcl"
+
 #if defined(UNICODE_CONVERSION) && HAVE_TCL_VERSION(8,1)
 
 #include "mb/pg_wchar.h"
@@ -263,6 +267,8 @@ _PG_init(void)
 	if (pltcl_pm_init_done)
 		return;
 
+	set_text_domain(TEXTDOMAIN);
+
 #ifdef WIN32
 	/* Required on win32 to prevent error loading init.tcl */
 	Tcl_FindExecutable("");