From cdb956ac2da784f37b110f61da8915819d3ff107 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Thu, 24 May 2018 19:23:40 +0900
Subject: [PATCH 1/3] Make object names more translatable

getObjectDescription() is making description for some object classes
in a fashon that is hard-to-translate into some languages. This patch
changes it easier to translate. This changes "default" for "default
value" along with that.
---
 src/backend/catalog/objectaddress.c    | 74 ++++++++++++++++++++++++++--------
 src/test/regress/expected/sequence.out |  4 +-
 2 files changed, 59 insertions(+), 19 deletions(-)

diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index d371c47842..3b27ed7cf4 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -2829,7 +2829,7 @@ getObjectDescription(const ObjectAddress *object)
 				colobject.objectId = attrdef->adrelid;
 				colobject.objectSubId = attrdef->adnum;
 
-				appendStringInfo(&buffer, _("default for %s"),
+				appendStringInfo(&buffer, _("default value for %s"),
 								 getObjectDescription(&colobject));
 
 				systable_endscan(adscan);
@@ -3016,6 +3016,7 @@ getObjectDescription(const ObjectAddress *object)
 				SysScanDesc rcscan;
 				HeapTuple	tup;
 				Form_pg_rewrite rule;
+				StringInfoData reldesc;
 
 				ruleDesc = heap_open(RewriteRelationId, AccessShareLock);
 
@@ -3035,9 +3036,17 @@ getObjectDescription(const ObjectAddress *object)
 
 				rule = (Form_pg_rewrite) GETSTRUCT(tup);
 
-				appendStringInfo(&buffer, _("rule %s on "),
-								 NameStr(rule->rulename));
-				getRelationDescription(&buffer, rule->ev_class);
+				/*
+				 * You might think this could be written simpler, but we
+				 * should give a chance to reorder the words in translation.
+				 */
+				initStringInfo(&reldesc);
+				getRelationDescription(&reldesc, rule->ev_class);
+
+				appendStringInfo(&buffer, _("rule %s on %s"),
+								 NameStr(rule->rulename),
+								 reldesc.data);
+				pfree(reldesc.data);
 
 				systable_endscan(rcscan);
 				heap_close(ruleDesc, AccessShareLock);
@@ -3051,6 +3060,7 @@ getObjectDescription(const ObjectAddress *object)
 				SysScanDesc tgscan;
 				HeapTuple	tup;
 				Form_pg_trigger trig;
+				StringInfoData reldesc;
 
 				trigDesc = heap_open(TriggerRelationId, AccessShareLock);
 
@@ -3070,9 +3080,17 @@ getObjectDescription(const ObjectAddress *object)
 
 				trig = (Form_pg_trigger) GETSTRUCT(tup);
 
-				appendStringInfo(&buffer, _("trigger %s on "),
-								 NameStr(trig->tgname));
-				getRelationDescription(&buffer, trig->tgrelid);
+				/*
+				 * You might think this could be written simpler, but we
+				 * should give a chance to reorder the words in translation.
+				 */
+				initStringInfo(&reldesc);
+				getRelationDescription(&reldesc, trig->tgrelid);
+
+				appendStringInfo(&buffer, _("trigger %s on %s"),
+								 NameStr(trig->tgname),
+								 reldesc.data);
+				pfree(reldesc.data);
 
 				systable_endscan(tgscan);
 				heap_close(trigDesc, AccessShareLock);
@@ -3256,6 +3274,8 @@ getObjectDescription(const ObjectAddress *object)
 				SysScanDesc rcscan;
 				HeapTuple	tup;
 				Form_pg_default_acl defacl;
+				StringInfo		acldesc = &buffer;
+				StringInfoData	tmpbuf;
 
 				defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);
 
@@ -3275,36 +3295,43 @@ getObjectDescription(const ObjectAddress *object)
 
 				defacl = (Form_pg_default_acl) GETSTRUCT(tup);
 
+				if (OidIsValid(defacl->defaclnamespace))
+				{
+					/* We combine acldesc with schema name later */
+					acldesc = &tmpbuf;
+					initStringInfo(acldesc);
+				}
+
 				switch (defacl->defaclobjtype)
 				{
 					case DEFACLOBJ_RELATION:
-						appendStringInfo(&buffer,
+						appendStringInfo(acldesc,
 										 _("default privileges on new relations belonging to role %s"),
 										 GetUserNameFromId(defacl->defaclrole, false));
 						break;
 					case DEFACLOBJ_SEQUENCE:
-						appendStringInfo(&buffer,
+						appendStringInfo(acldesc,
 										 _("default privileges on new sequences belonging to role %s"),
 										 GetUserNameFromId(defacl->defaclrole, false));
 						break;
 					case DEFACLOBJ_FUNCTION:
-						appendStringInfo(&buffer,
+						appendStringInfo(acldesc,
 										 _("default privileges on new functions belonging to role %s"),
 										 GetUserNameFromId(defacl->defaclrole, false));
 						break;
 					case DEFACLOBJ_TYPE:
-						appendStringInfo(&buffer,
+						appendStringInfo(acldesc,
 										 _("default privileges on new types belonging to role %s"),
 										 GetUserNameFromId(defacl->defaclrole, false));
 						break;
 					case DEFACLOBJ_NAMESPACE:
-						appendStringInfo(&buffer,
+						appendStringInfo(acldesc,
 										 _("default privileges on new schemas belonging to role %s"),
 										 GetUserNameFromId(defacl->defaclrole, false));
 						break;
 					default:
 						/* shouldn't get here */
-						appendStringInfo(&buffer,
+						appendStringInfo(acldesc,
 										 _("default privileges belonging to role %s"),
 										 GetUserNameFromId(defacl->defaclrole, false));
 						break;
@@ -3312,9 +3339,17 @@ getObjectDescription(const ObjectAddress *object)
 
 				if (OidIsValid(defacl->defaclnamespace))
 				{
+					/*
+					 * You might think this could be written simpler, but we
+					 * should give a chance to reorder the words in
+					 * translation.
+					 */
+					Assert(&buffer != acldesc);
 					appendStringInfo(&buffer,
-									 _(" in schema %s"),
+									 _("%s in schema %s"),
+									 acldesc->data,
 									 get_namespace_name(defacl->defaclnamespace));
+					pfree(acldesc->data);
 				}
 
 				systable_endscan(rcscan);
@@ -3356,6 +3391,7 @@ getObjectDescription(const ObjectAddress *object)
 				SysScanDesc sscan;
 				HeapTuple	tuple;
 				Form_pg_policy form_policy;
+				StringInfoData reldesc;
 
 				policy_rel = heap_open(PolicyRelationId, AccessShareLock);
 
@@ -3375,9 +3411,13 @@ getObjectDescription(const ObjectAddress *object)
 
 				form_policy = (Form_pg_policy) GETSTRUCT(tuple);
 
-				appendStringInfo(&buffer, _("policy %s on "),
-								 NameStr(form_policy->polname));
-				getRelationDescription(&buffer, form_policy->polrelid);
+				initStringInfo(&reldesc);
+				getRelationDescription(&reldesc, form_policy->polrelid);
+
+				appendStringInfo(&buffer, _("policy %s on %s"),
+								 NameStr(form_policy->polname),
+								 reldesc.data);
+				pfree(reldesc.data);
 
 				systable_endscan(sscan);
 				heap_close(policy_rel, AccessShareLock);
diff --git a/src/test/regress/expected/sequence.out b/src/test/regress/expected/sequence.out
index ca5ea063fa..f2e20a7e85 100644
--- a/src/test/regress/expected/sequence.out
+++ b/src/test/regress/expected/sequence.out
@@ -293,11 +293,11 @@ CREATE TEMP TABLE t1 (
 -- Both drops should fail, but with different error messages:
 DROP SEQUENCE t1_f1_seq;
 ERROR:  cannot drop sequence t1_f1_seq because other objects depend on it
-DETAIL:  default for table t1 column f1 depends on sequence t1_f1_seq
+DETAIL:  default value for table t1 column f1 depends on sequence t1_f1_seq
 HINT:  Use DROP ... CASCADE to drop the dependent objects too.
 DROP SEQUENCE myseq2;
 ERROR:  cannot drop sequence myseq2 because other objects depend on it
-DETAIL:  default for table t1 column f2 depends on sequence myseq2
+DETAIL:  default value for table t1 column f2 depends on sequence myseq2
 HINT:  Use DROP ... CASCADE to drop the dependent objects too.
 -- This however will work:
 DROP SEQUENCE myseq3;
-- 
2.16.3

