message/pipeline: trim whitespace for messages

it is added back when rendering, but makes it hard
for the translator to forget about it.

Change-Id: Ic775e0707a9ec4fc0cdcf5351933ae9b05872d81
Reviewed-on: https://go-review.googlesource.com/83816
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/cmd/gotext/common.go b/cmd/gotext/common.go
index 1036592..51322db 100644
--- a/cmd/gotext/common.go
+++ b/cmd/gotext/common.go
@@ -21,6 +21,9 @@
 // NOTE: The command line tool already prefixes with "gotext:".
 var (
 	wrap = func(err error, msg string) error {
+		if err == nil {
+			return nil
+		}
 		return fmt.Errorf("%s: %v", msg, err)
 	}
 	errorf = fmt.Errorf
diff --git a/cmd/gotext/examples/extract/catalog.go b/cmd/gotext/examples/extract/catalog.go
index c9e8495..1a0d6d0 100644
--- a/cmd/gotext/examples/extract/catalog.go
+++ b/cmd/gotext/examples/extract/catalog.go
@@ -47,24 +47,26 @@
 }
 
 var deIndex = []uint32{ // 8 elements
-	0x00000000, 0x0000000d, 0x0000001b, 0x00000031,
-	0x00000047, 0x00000066, 0x00000066, 0x00000066,
+	0x00000000, 0x00000011, 0x00000023, 0x0000003d,
+	0x00000057, 0x00000076, 0x00000076, 0x00000076,
 } // Size: 56 bytes
 
-const deData string = "" + // Size: 102 bytes
-	"\x02Hallo Welt!\x0a\x02Hallo %[1]s!\x0a\x02%[1]s besucht %[2]s!\x0a\x02%" +
-	"[1]s besucht %[3]s!\x0a\x02Noch %[1]d Bestände zu gehen!"
+const deData string = "" + // Size: 118 bytes
+	"\x04\x00\x01\x0a\x0c\x02Hallo Welt!\x04\x00\x01\x0a\x0d\x02Hallo %[1]s!" +
+	"\x04\x00\x01\x0a\x15\x02%[1]s besucht %[2]s!\x04\x00\x01\x0a\x15\x02%[1]" +
+	"s besucht %[3]s!\x02Noch %[1]d Bestände zu gehen!"
 
 var en_USIndex = []uint32{ // 8 elements
-	0x00000000, 0x0000000e, 0x0000001c, 0x00000036,
-	0x00000050, 0x00000093, 0x000000aa, 0x000000c9,
+	0x00000000, 0x00000012, 0x00000024, 0x00000042,
+	0x00000060, 0x000000a3, 0x000000ba, 0x000000d9,
 } // Size: 56 bytes
 
-const en_USData string = "" + // Size: 201 bytes
-	"\x02Hello world!\x0a\x02Hello %[1]s!\x0a\x02%[1]s is visiting %[2]s!\x0a" +
-	"\x02%[1]s is visiting %[3]s!\x0a\x14\x01\x81\x01\x00\x02\x14\x02One file" +
-	" remaining!\x00&\x02There are %[1]d more files remaining!\x02%[1]s is ou" +
-	"t of order!\x02%.2[1]f miles traveled (%[1]f)"
+const en_USData string = "" + // Size: 217 bytes
+	"\x04\x00\x01\x0a\x0d\x02Hello world!\x04\x00\x01\x0a\x0d\x02Hello %[1]s!" +
+	"\x04\x00\x01\x0a\x19\x02%[1]s is visiting %[2]s!\x04\x00\x01\x0a\x19\x02" +
+	"%[1]s is visiting %[3]s!\x14\x01\x81\x01\x00\x02\x14\x02One file remaini" +
+	"ng!\x00&\x02There are %[1]d more files remaining!\x02%[1]s is out of ord" +
+	"er!\x02%.2[1]f miles traveled (%[1]f)"
 
 var zhIndex = []uint32{ // 8 elements
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -73,4 +75,4 @@
 
 const zhData string = ""
 
-// Total table size 471 bytes (0KiB); checksum: 2452D1C5
+// Total table size 503 bytes (0KiB); checksum: A968BD6
diff --git a/cmd/gotext/examples/extract/locales/de/messages.gotext.json b/cmd/gotext/examples/extract/locales/de/messages.gotext.json
index 221990f..5e1d3b3 100755
--- a/cmd/gotext/examples/extract/locales/de/messages.gotext.json
+++ b/cmd/gotext/examples/extract/locales/de/messages.gotext.json
@@ -2,17 +2,17 @@
     "language": "de",
     "messages": [
         {
-            "id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
-            "translation": "Hallo Welt!\n",
+            "message": "Hello world!",
+            "translation": "Hallo Welt!",
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:27:10"
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
-            "translation": "Hallo {City}!\n",
+            "message": "Hello {City}!",
+            "translation": "Hallo {City}!",
             "placeholders": [
                 {
                     "id": "City",
@@ -26,10 +26,10 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:31:10"
         },
         {
-            "id": "Hello {Town}!\n",
+            "id": "Hello {Town}!",
             "key": "Hello %s!\n",
-            "message": "Hello {Town}!\n",
-            "translation": "Hallo {Town}!\n",
+            "message": "Hello {Town}!",
+            "translation": "Hallo {Town}!",
             "placeholders": [
                 {
                     "id": "Town",
@@ -44,10 +44,10 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:35:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
-            "translation": "{Person} besucht {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
+            "translation": "{Person} besucht {Place}!",
             "placeholders": [
                 {
                     "id": "Person",
@@ -71,10 +71,10 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:40:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
-            "translation": "{Person} besucht {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
+            "translation": "{Person} besucht {Place}!",
             "comment": "Person visiting a place.",
             "placeholders": [
                 {
@@ -123,9 +123,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:67:10"
         },
         {
-            "id": "Use the following code for your discount: {ReferralCode}\n",
+            "id": "Use the following code for your discount: {ReferralCode}",
             "key": "Use the following code for your discount: %d\n",
-            "message": "Use the following code for your discount: {ReferralCode}\n",
+            "message": "Use the following code for your discount: {ReferralCode}",
             "translation": "",
             "placeholders": [
                 {
diff --git a/cmd/gotext/examples/extract/locales/de/out.gotext.json b/cmd/gotext/examples/extract/locales/de/out.gotext.json
index 2ab70e1..05b9330 100755
--- a/cmd/gotext/examples/extract/locales/de/out.gotext.json
+++ b/cmd/gotext/examples/extract/locales/de/out.gotext.json
@@ -2,16 +2,16 @@
     "language": "de",
     "messages": [
         {
-            "id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
+            "message": "Hello world!",
             "translation": "",
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:28:10"
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
+            "message": "Hello {City}!",
             "translation": "",
             "placeholders": [
                 {
@@ -26,9 +26,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:32:10"
         },
         {
-            "id": "Hello {Town}!\n",
+            "id": "Hello {Town}!",
             "key": "Hello %s!\n",
-            "message": "Hello {Town}!\n",
+            "message": "Hello {Town}!",
             "translation": "",
             "placeholders": [
                 {
@@ -44,9 +44,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:36:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "placeholders": [
                 {
@@ -71,9 +71,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:41:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "comment": "Person visiting a place.",
             "placeholders": [
@@ -140,9 +140,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:68:10"
         },
         {
-            "id": "Use the following code for your discount: {ReferralCode}\n",
+            "id": "Use the following code for your discount: {ReferralCode}",
             "key": "Use the following code for your discount: %d\n",
-            "message": "Use the following code for your discount: {ReferralCode}\n",
+            "message": "Use the following code for your discount: {ReferralCode}",
             "translation": "",
             "placeholders": [
                 {
diff --git a/cmd/gotext/examples/extract/locales/en-US/messages.gotext.json b/cmd/gotext/examples/extract/locales/en-US/messages.gotext.json
index 37d691b..5f6f8b0 100755
--- a/cmd/gotext/examples/extract/locales/en-US/messages.gotext.json
+++ b/cmd/gotext/examples/extract/locales/en-US/messages.gotext.json
@@ -2,23 +2,23 @@
     "language": "en-US",
     "messages": [
         {
-"id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
-            "translation":  "Hello world!\n",
+            "message": "Hello world!",
+            "translation":  "Hello world!",
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:27:10"
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
-            "translation": "Hello {City}!\n"
+            "message": "Hello {City}!",
+            "translation": "Hello {City}n"
         },
         {
-            "id": "Hello {Town}!\n",
+            "id": "Hello {Town}!",
             "key": "Hello %s!\n",
-            "message": "Hello {Town}!\n",
-            "translation": "Hello {Town}!\n",
+            "message": "Hello {Town}!",
+            "translation": "Hello {Town}!",
             "placeholders": [
                 {
                     "id": "Town",
@@ -32,16 +32,16 @@
             ]
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "{Person} is visiting {Place}!\n"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
-            "translation": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
+            "translation": "{Person} is visiting {Place}!",
             "comment": "Person visiting a place."
         },
         {
@@ -60,9 +60,9 @@
             }
         },
         {
-            "id": "Use the following code for your discount: {ReferralCode}\n",
+            "id": "Use the following code for your discount: {ReferralCode}",
             "key": "Use the following code for your discount: %d\n",
-            "message": "Use the following code for your discount: {ReferralCode}\n",
+            "message": "Use the following code for your discount: {ReferralCode}",
             "translation": ""
         },
         {
diff --git a/cmd/gotext/examples/extract/locales/en-US/out.gotext.json b/cmd/gotext/examples/extract/locales/en-US/out.gotext.json
index 27d8b56..69e8157 100755
--- a/cmd/gotext/examples/extract/locales/en-US/out.gotext.json
+++ b/cmd/gotext/examples/extract/locales/en-US/out.gotext.json
@@ -2,16 +2,16 @@
     "language": "en-US",
     "messages": [
         {
-            "id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
+            "message": "Hello world!",
             "translation": "",
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:28:10"
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
+            "message": "Hello {City}!",
             "translation": "",
             "placeholders": [
                 {
@@ -26,9 +26,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:32:10"
         },
         {
-            "id": "Hello {Town}!\n",
+            "id": "Hello {Town}!",
             "key": "Hello %s!\n",
-            "message": "Hello {Town}!\n",
+            "message": "Hello {Town}!",
             "translation": "",
             "placeholders": [
                 {
@@ -44,9 +44,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:36:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "placeholders": [
                 {
@@ -71,9 +71,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:41:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "comment": "Person visiting a place.",
             "placeholders": [
@@ -140,9 +140,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:68:10"
         },
         {
-            "id": "Use the following code for your discount: {ReferralCode}\n",
+            "id": "Use the following code for your discount: {ReferralCode}",
             "key": "Use the following code for your discount: %d\n",
-            "message": "Use the following code for your discount: {ReferralCode}\n",
+            "message": "Use the following code for your discount: {ReferralCode}",
             "translation": "",
             "placeholders": [
                 {
diff --git a/cmd/gotext/examples/extract/locales/zh/messages.gotext.json b/cmd/gotext/examples/extract/locales/zh/messages.gotext.json
index 8530740..9913f83 100755
--- a/cmd/gotext/examples/extract/locales/zh/messages.gotext.json
+++ b/cmd/gotext/examples/extract/locales/zh/messages.gotext.json
@@ -2,16 +2,16 @@
     "language": "zh",
     "messages": [
         {
-"id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
+            "message": "Hello world!",
             "translation": "",
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:27:10"
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
+            "message": "Hello {City}!",
             "translation": "",
             "placeholders": [
                 {
@@ -26,9 +26,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:31:10"
         },
         {
-            "id": "Hello {Town}!\n",
+            "id": "Hello {Town}!",
             "key": "Hello %s!\n",
-            "message": "Hello {Town}!\n",
+            "message": "Hello {Town}!",
             "translation": "",
             "placeholders": [
                 {
@@ -44,9 +44,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:35:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "placeholders": [
                 {
@@ -71,9 +71,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:40:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "comment": "Person visiting a place.",
             "placeholders": [
diff --git a/cmd/gotext/examples/extract/locales/zh/out.gotext.json b/cmd/gotext/examples/extract/locales/zh/out.gotext.json
index 067af28..6b53a34 100755
--- a/cmd/gotext/examples/extract/locales/zh/out.gotext.json
+++ b/cmd/gotext/examples/extract/locales/zh/out.gotext.json
@@ -2,16 +2,16 @@
     "language": "zh",
     "messages": [
         {
-            "id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
+            "message": "Hello world!",
             "translation": "",
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:28:10"
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
+            "message": "Hello {City}!",
             "translation": "",
             "placeholders": [
                 {
@@ -26,9 +26,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:32:10"
         },
         {
-            "id": "Hello {Town}!\n",
+            "id": "Hello {Town}!",
             "key": "Hello %s!\n",
-            "message": "Hello {Town}!\n",
+            "message": "Hello {Town}!",
             "translation": "",
             "placeholders": [
                 {
@@ -44,9 +44,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:36:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "placeholders": [
                 {
@@ -71,9 +71,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:41:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "comment": "Person visiting a place.",
             "placeholders": [
@@ -140,9 +140,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract/main.go:68:10"
         },
         {
-            "id": "Use the following code for your discount: {ReferralCode}\n",
+            "id": "Use the following code for your discount: {ReferralCode}",
             "key": "Use the following code for your discount: %d\n",
-            "message": "Use the following code for your discount: {ReferralCode}\n",
+            "message": "Use the following code for your discount: {ReferralCode}",
             "translation": "",
             "placeholders": [
                 {
diff --git a/cmd/gotext/examples/extract_http/locales/de/out.gotext.json b/cmd/gotext/examples/extract_http/locales/de/out.gotext.json
index bd71590..d8437c0 100755
--- a/cmd/gotext/examples/extract_http/locales/de/out.gotext.json
+++ b/cmd/gotext/examples/extract_http/locales/de/out.gotext.json
@@ -2,9 +2,9 @@
     "language": "de",
     "messages": [
         {
-            "id": "Hello {From}!\n",
+            "id": "Hello {From}!",
             "key": "Hello %s!\n",
-            "message": "Hello {From}!\n",
+            "message": "Hello {From}!",
             "translation": "",
             "placeholders": [
                 {
@@ -19,9 +19,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract_http/pkg/pkg.go:22:11"
         },
         {
-            "id": "Do you like your browser ({User_Agent})?\n",
+            "id": "Do you like your browser ({User_Agent})?",
             "key": "Do you like your browser (%s)?\n",
-            "message": "Do you like your browser ({User_Agent})?\n",
+            "message": "Do you like your browser ({User_Agent})?",
             "translation": "",
             "placeholders": [
                 {
diff --git a/cmd/gotext/examples/extract_http/locales/en-US/out.gotext.json b/cmd/gotext/examples/extract_http/locales/en-US/out.gotext.json
index d0c4684..de59eca 100755
--- a/cmd/gotext/examples/extract_http/locales/en-US/out.gotext.json
+++ b/cmd/gotext/examples/extract_http/locales/en-US/out.gotext.json
@@ -2,9 +2,9 @@
     "language": "en-US",
     "messages": [
         {
-            "id": "Hello {From}!\n",
+            "id": "Hello {From}!",
             "key": "Hello %s!\n",
-            "message": "Hello {From}!\n",
+            "message": "Hello {From}!",
             "translation": "",
             "placeholders": [
                 {
@@ -19,9 +19,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract_http/pkg/pkg.go:22:11"
         },
         {
-            "id": "Do you like your browser ({User_Agent})?\n",
+            "id": "Do you like your browser ({User_Agent})?",
             "key": "Do you like your browser (%s)?\n",
-            "message": "Do you like your browser ({User_Agent})?\n",
+            "message": "Do you like your browser ({User_Agent})?",
             "translation": "",
             "placeholders": [
                 {
diff --git a/cmd/gotext/examples/extract_http/locales/zh/out.gotext.json b/cmd/gotext/examples/extract_http/locales/zh/out.gotext.json
index cad0ff0..0bab4a7 100755
--- a/cmd/gotext/examples/extract_http/locales/zh/out.gotext.json
+++ b/cmd/gotext/examples/extract_http/locales/zh/out.gotext.json
@@ -2,9 +2,9 @@
     "language": "zh",
     "messages": [
         {
-            "id": "Hello {From}!\n",
+            "id": "Hello {From}!",
             "key": "Hello %s!\n",
-            "message": "Hello {From}!\n",
+            "message": "Hello {From}!",
             "translation": "",
             "placeholders": [
                 {
@@ -19,9 +19,9 @@
             "position": "golang.org/x/text/cmd/gotext/examples/extract_http/pkg/pkg.go:22:11"
         },
         {
-            "id": "Do you like your browser ({User_Agent})?\n",
+            "id": "Do you like your browser ({User_Agent})?",
             "key": "Do you like your browser (%s)?\n",
-            "message": "Do you like your browser ({User_Agent})?\n",
+            "message": "Do you like your browser ({User_Agent})?",
             "translation": "",
             "placeholders": [
                 {
diff --git a/message/pipeline/extract.go b/message/pipeline/extract.go
index 406d7b9..379cc6d 100644
--- a/message/pipeline/extract.go
+++ b/message/pipeline/extract.go
@@ -145,9 +145,11 @@
 
 				ph := placeholders{index: map[string]string{}}
 
+				trimmed, _, _ := trimWS(fmtMsg)
+
 				p := fmtparser.Parser{}
 				p.Reset(simArgs)
-				for p.SetFormat(fmtMsg); p.Scan(); {
+				for p.SetFormat(trimmed); p.Scan(); {
 					switch p.Status {
 					case fmtparser.StatusText:
 						msg += p.Text()
diff --git a/message/pipeline/generate.go b/message/pipeline/generate.go
index f21568d..8d6f07b 100644
--- a/message/pipeline/generate.go
+++ b/message/pipeline/generate.go
@@ -162,6 +162,14 @@
 					if err != nil {
 						return nil, wrap(err, "error")
 					}
+					_, leadWS, trailWS := trimWS(msg.Key)
+					if leadWS != "" || trailWS != "" {
+						m = catmsg.Affix{
+							Message: m,
+							Prefix:  leadWS,
+							Suffix:  trailWS,
+						}
+					}
 					// TODO: support macros.
 					data, err := catmsg.Compile(tag, nil, m)
 					if err != nil {
diff --git a/message/pipeline/pipeline.go b/message/pipeline/pipeline.go
index 876e470..8087bf6 100644
--- a/message/pipeline/pipeline.go
+++ b/message/pipeline/pipeline.go
@@ -19,8 +19,10 @@
 	"regexp"
 	"strings"
 	"text/template"
+	"unicode"
 
 	"golang.org/x/text/language"
+	"golang.org/x/text/runes"
 	"golang.org/x/tools/go/loader"
 )
 
@@ -250,6 +252,21 @@
 	return nil
 }
 
+var (
+	ws    = runes.In(unicode.White_Space).Contains
+	notWS = runes.NotIn(unicode.White_Space).Contains
+)
+
+func trimWS(s string) (trimmed, leadWS, trailWS string) {
+	trimmed = strings.TrimRightFunc(s, ws)
+	trailWS = s[len(trimmed):]
+	if i := strings.IndexFunc(trimmed, notWS); i > 0 {
+		leadWS = trimmed[:i]
+		trimmed = trimmed[i:]
+	}
+	return trimmed, leadWS, trailWS
+}
+
 // NOTE: The command line tool already prefixes with "gotext:".
 var (
 	wrap = func(err error, msg string) error {
diff --git a/message/pipeline/testdata/test1/catalog_gen.go b/message/pipeline/testdata/test1/catalog_gen.go
index 62f8686..08ab3b8 100644
--- a/message/pipeline/testdata/test1/catalog_gen.go
+++ b/message/pipeline/testdata/test1/catalog_gen.go
@@ -48,27 +48,29 @@
 }
 
 var deIndex = []uint32{ // 9 elements
-	0x00000000, 0x0000000d, 0x0000001b, 0x00000031,
-	0x00000047, 0x00000065, 0x00000084, 0x00000084,
-	0x00000084,
+	0x00000000, 0x00000011, 0x00000023, 0x0000003d,
+	0x00000057, 0x00000075, 0x00000094, 0x00000094,
+	0x00000094,
 } // Size: 60 bytes
 
-const deData string = "" + // Size: 132 bytes
-	"\x02Hallo Welt!\x0a\x02Hallo %[1]s!\x0a\x02%[1]s besucht %[2]s!\x0a\x02%" +
-	"[1]s besucht %[3]s!\x0a\x02Noch zwei Bestände zu gehen!\x02Noch %[1]d Be" +
-	"stände zu gehen!"
+const deData string = "" + // Size: 148 bytes
+	"\x04\x00\x01\x0a\x0c\x02Hallo Welt!\x04\x00\x01\x0a\x0d\x02Hallo %[1]s!" +
+	"\x04\x00\x01\x0a\x15\x02%[1]s besucht %[2]s!\x04\x00\x01\x0a\x15\x02%[1]" +
+	"s besucht %[3]s!\x02Noch zwei Bestände zu gehen!\x02Noch %[1]d Bestände " +
+	"zu gehen!"
 
 var en_USIndex = []uint32{ // 9 elements
-	0x00000000, 0x0000000e, 0x0000001c, 0x00000036,
-	0x00000050, 0x00000050, 0x00000093, 0x000000aa,
-	0x000000c9,
+	0x00000000, 0x00000012, 0x00000024, 0x00000042,
+	0x00000060, 0x00000060, 0x000000a3, 0x000000ba,
+	0x000000d9,
 } // Size: 60 bytes
 
-const en_USData string = "" + // Size: 201 bytes
-	"\x02Hello world!\x0a\x02Hello %[1]s!\x0a\x02%[1]s is visiting %[2]s!\x0a" +
-	"\x02%[1]s is visiting %[3]s!\x0a\x14\x01\x81\x01\x00\x02\x14\x02One file" +
-	" remaining!\x00&\x02There are %[1]d more files remaining!\x02%[1]s is ou" +
-	"t of order!\x02%.2[1]f miles traveled (%[1]f)"
+const en_USData string = "" + // Size: 217 bytes
+	"\x04\x00\x01\x0a\x0d\x02Hello world!\x04\x00\x01\x0a\x0d\x02Hello %[1]s!" +
+	"\x04\x00\x01\x0a\x19\x02%[1]s is visiting %[2]s!\x04\x00\x01\x0a\x19\x02" +
+	"%[1]s is visiting %[3]s!\x14\x01\x81\x01\x00\x02\x14\x02One file remaini" +
+	"ng!\x00&\x02There are %[1]d more files remaining!\x02%[1]s is out of ord" +
+	"er!\x02%.2[1]f miles traveled (%[1]f)"
 
 var zhIndex = []uint32{ // 9 elements
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -78,4 +80,4 @@
 
 const zhData string = ""
 
-// Total table size 513 bytes (0KiB); checksum: 41415C53
+// Total table size 545 bytes (0KiB); checksum: 343E0210
diff --git a/message/pipeline/testdata/test1/extracted.gotext.json b/message/pipeline/testdata/test1/extracted.gotext.json
index dfb9153..e109c32 100644
--- a/message/pipeline/testdata/test1/extracted.gotext.json
+++ b/message/pipeline/testdata/test1/extracted.gotext.json
@@ -2,16 +2,16 @@
     "language": "und",
     "messages": [
         {
-            "id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
+            "message": "Hello world!",
             "translation": "",
             "position": "testdata/test1/test1.go:19:10"
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
+            "message": "Hello {City}!",
             "translation": "",
             "placeholders": [
                 {
@@ -26,9 +26,9 @@
             "position": "testdata/test1/test1.go:24:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "placeholders": [
                 {
@@ -53,9 +53,9 @@
             "position": "testdata/test1/test1.go:30:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "comment": "Field names are placeholders.",
             "placeholders": [
@@ -122,9 +122,9 @@
             "position": "testdata/test1/test1.go:56:10"
         },
         {
-            "id": "Use the following code for your discount: {ReferralCode}\n",
+            "id": "Use the following code for your discount: {ReferralCode}",
             "key": "Use the following code for your discount: %d\n",
-            "message": "Use the following code for your discount: {ReferralCode}\n",
+            "message": "Use the following code for your discount: {ReferralCode}",
             "translation": "",
             "placeholders": [
                 {
diff --git a/message/pipeline/testdata/test1/extracted.gotext.json.want b/message/pipeline/testdata/test1/extracted.gotext.json.want
index dfb9153..e109c32 100644
--- a/message/pipeline/testdata/test1/extracted.gotext.json.want
+++ b/message/pipeline/testdata/test1/extracted.gotext.json.want
@@ -2,16 +2,16 @@
     "language": "und",
     "messages": [
         {
-            "id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
+            "message": "Hello world!",
             "translation": "",
             "position": "testdata/test1/test1.go:19:10"
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
+            "message": "Hello {City}!",
             "translation": "",
             "placeholders": [
                 {
@@ -26,9 +26,9 @@
             "position": "testdata/test1/test1.go:24:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "placeholders": [
                 {
@@ -53,9 +53,9 @@
             "position": "testdata/test1/test1.go:30:10"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "comment": "Field names are placeholders.",
             "placeholders": [
@@ -122,9 +122,9 @@
             "position": "testdata/test1/test1.go:56:10"
         },
         {
-            "id": "Use the following code for your discount: {ReferralCode}\n",
+            "id": "Use the following code for your discount: {ReferralCode}",
             "key": "Use the following code for your discount: %d\n",
-            "message": "Use the following code for your discount: {ReferralCode}\n",
+            "message": "Use the following code for your discount: {ReferralCode}",
             "translation": "",
             "placeholders": [
                 {
diff --git a/message/pipeline/testdata/test1/locales/de/messages.gotext.json b/message/pipeline/testdata/test1/locales/de/messages.gotext.json
index a4a46ed..f92e4a1 100755
--- a/message/pipeline/testdata/test1/locales/de/messages.gotext.json
+++ b/message/pipeline/testdata/test1/locales/de/messages.gotext.json
@@ -2,16 +2,16 @@
     "language": "de",
     "messages": [
         {
-            "id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
-            "translation": "Hallo Welt!\n"
+            "message": "Hello world!",
+            "translation": "Hallo Welt!"
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
-            "translation": "Hallo {City}!\n",
+            "message": "Hello {City}!",
+            "translation": "Hallo {City}!",
             "placeholders": [
                 {
                     "id": "City",
@@ -20,10 +20,10 @@
             ]
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
-            "translation": "{Person} besucht {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
+            "translation": "{Person} besucht {Place}!",
             "placeholders": [
                 {
                     "id": "Person",
@@ -36,10 +36,10 @@
             ]
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
-            "translation": "{Person} besucht {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
+            "translation": "{Person} besucht {Place}!",
             "placeholders": [
                 {
                     "id": "Person",
@@ -80,9 +80,9 @@
             ]
         },
         {
-            "id": "Use the following code for your discount: {ReferralCode}\n",
+            "id": "Use the following code for your discount: {ReferralCode}",
             "key": "Use the following code for your discount: %d\n",
-            "message": "Use the following code for your discount: {ReferralCode}\n",
+            "message": "Use the following code for your discount: {ReferralCode}",
             "translation": "",
             "placeholders": [
                 {
diff --git a/message/pipeline/testdata/test1/locales/en-US/messages.gotext.json b/message/pipeline/testdata/test1/locales/en-US/messages.gotext.json
index bf97577..b984242 100755
--- a/message/pipeline/testdata/test1/locales/en-US/messages.gotext.json
+++ b/message/pipeline/testdata/test1/locales/en-US/messages.gotext.json
@@ -2,22 +2,22 @@
     "language": "en-US",
     "messages": [
         {
-"id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
-            "translation":  "Hello world!\n"
+            "message": "Hello world!",
+            "translation":  "Hello world!"
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
-            "translation": "Hello {City}!\n"
+            "message": "Hello {City}!",
+            "translation": "Hello {City}!"
         },
         {
-            "id": "Hello {Town}!\n",
+            "id": "Hello {Town}!",
             "key": "Hello %s!\n",
-            "message": "Hello {Town}!\n",
-            "translation": "Hello {Town}!\n",
+            "message": "Hello {Town}!",
+            "translation": "Hello {Town}!",
             "placeholders": [
                 {
                     "id": "Town",
@@ -31,16 +31,16 @@
             ]
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
-            "translation": "{Person} is visiting {Place}!\n"
+            "message": "{Person} is visiting {Place}!",
+            "translation": "{Person} is visiting {Place}!"
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
-            "translation": "{Person} is visiting {Place}!\n"
+            "message": "{Person} is visiting {Place}!",
+            "translation": "{Person} is visiting {Place}!"
         },
         {
             "id": "{2} files remaining!",
@@ -70,9 +70,9 @@
             }
         },
         {
-            "id": "Use the following code for your discount: {ReferralCode}\n",
+            "id": "Use the following code for your discount: {ReferralCode}",
             "key": "Use the following code for your discount: %d\n",
-            "message": "Use the following code for your discount: {ReferralCode}\n",
+            "message": "Use the following code for your discount: {ReferralCode}",
             "translation": ""
         },
         {
diff --git a/message/pipeline/testdata/test1/locales/zh/messages.gotext.json b/message/pipeline/testdata/test1/locales/zh/messages.gotext.json
index 557a3d2..c80d1d2 100755
--- a/message/pipeline/testdata/test1/locales/zh/messages.gotext.json
+++ b/message/pipeline/testdata/test1/locales/zh/messages.gotext.json
@@ -2,15 +2,15 @@
     "language": "zh",
     "messages": [
         {
-            "id": "Hello world!\n",
+            "id": "Hello world!",
             "key": "Hello world!\n",
-            "message": "Hello world!\n",
+            "message": "Hello world!",
             "translation": ""
         },
         {
-            "id": "Hello {City}!\n",
+            "id": "Hello {City}!",
             "key": "Hello %s!\n",
-            "message": "Hello {City}!\n",
+            "message": "Hello {City}!",
             "translation": "",
             "placeholders": [
                 {
@@ -20,9 +20,9 @@
             ]
         },
         {
-            "id": "Hello {Town}!\n",
+            "id": "Hello {Town}!",
             "key": "Hello %s!\n",
-            "message": "Hello {Town}!\n",
+            "message": "Hello {Town}!",
             "translation": "",
             "placeholders": [
                 {
@@ -32,9 +32,9 @@
             ]
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%s is visiting %s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "placeholders": [
                 {
@@ -48,9 +48,9 @@
             ]
         },
         {
-            "id": "{Person} is visiting {Place}!\n",
+            "id": "{Person} is visiting {Place}!",
             "key": "%[1]s is visiting %[3]s!\n",
-            "message": "{Person} is visiting {Place}!\n",
+            "message": "{Person} is visiting {Place}!",
             "translation": "",
             "placeholders": [
                 {
@@ -92,9 +92,9 @@
             ]
         },
         {
-            "id": "Use the following code for your discount: {ReferralCode}\n",
+            "id": "Use the following code for your discount: {ReferralCode}",
             "key": "Use the following code for your discount: %d\n",
-            "message": "Use the following code for your discount: {ReferralCode}\n",
+            "message": "Use the following code for your discount: {ReferralCode}",
             "translation": "",
             "placeholders": [
                 {