veyron.io/veyron/veyron2/i18n: Initialize default i18n catalogue from file

This CL introduces an environment variable (VANADIUM_I18N_CATALOGUE) and flag
(-vanadium.i18n_catalogue) to allow the user to specify a comma separated list
of files from which a Vanadium process will read values for the default i18n
catalogue.   These flags are added to veyron.io/veyron/veyron/lib/flags,
alongside -veyron.credentials etc.

The files are read when the runtime is initilized.

It's not clear to me that this is the right place to put the flags, or that the
runtiome initialization is the right place to load the catalogues, but I'm
unsure where else to do it.

The code for writing/parsing catalogue files now always expects the Go format
string "%s %s %q" on each line.  That is, the first two values are never quoted
and the third one (the format string) always is.  This allows escapes in the
format string.

Change-Id: I0ea586b5519e50a9644140ff8c2666eefeaf4bc5
diff --git a/lib/flags/consts/consts.go b/lib/flags/consts/consts.go
index 7ed0112..56af7d8 100644
--- a/lib/flags/consts/consts.go
+++ b/lib/flags/consts/consts.go
@@ -9,4 +9,7 @@
 	// Prefix of all environment variables that point to roots of the
 	// veyron namespace, used to resolve non-rooted object names.
 	NamespaceRootPrefix = "NAMESPACE_ROOT"
+	// Environment variable containing a comma-separated list of i18n
+	// catalogue files to be loaded at startup.
+	I18nCatalogueFiles = "VANADIUM_I18N_CATALOGUE"
 )
diff --git a/lib/flags/flags.go b/lib/flags/flags.go
index d6a4810..b389a13 100644
--- a/lib/flags/flags.go
+++ b/lib/flags/flags.go
@@ -94,10 +94,15 @@
 	// will override the environment.
 	NamespaceRoots []string // TODO(cnicolaou): provide flag.Value impl
 
-	// Credentials may be initialized by the the VEYRON_CREDENTIALS
+	// Credentials may be initialized by the VEYRON_CREDENTIALS
 	// environment variable. The command line will override the environment.
 	Credentials string // TODO(cnicolaou): provide flag.Value impl
 
+	// I18nCatalogue may be initialized by the VANADIUM_I18N_CATALOGUE
+	// environment variable.  The command line will override the
+	// environment.
+	I18nCatalogue string
+
 	// Vtrace flags control various aspects of Vtrace.
 	Vtrace VtraceFlags
 
@@ -185,7 +190,7 @@
 // group with the supplied flag.FlagSet.
 func createAndRegisterRuntimeFlags(fs *flag.FlagSet) *RuntimeFlags {
 	f := &RuntimeFlags{}
-	roots, creds := readEnv()
+	roots, creds, i18nCatalogue := readEnv()
 	if len(roots) == 0 {
 		f.namespaceRootsFlag.roots = []string{defaultNamespaceRoot}
 	} else {
@@ -194,6 +199,7 @@
 
 	fs.Var(&f.namespaceRootsFlag, "veyron.namespace.root", "local namespace root; can be repeated to provided multiple roots")
 	fs.StringVar(&f.Credentials, "veyron.credentials", creds, "directory to use for storing security credentials")
+	fs.StringVar(&f.I18nCatalogue, "vanadium.i18n_catalogue", i18nCatalogue, "18n catalogue files to load, comma separated")
 
 	fs.Float64Var(&f.Vtrace.SampleRate, "veyron.vtrace.sample_rate", 0.0, "Rate (from 0.0 to 1.0) to sample vtrace traces.")
 	fs.BoolVar(&f.Vtrace.DumpOnShutdown, "veyron.vtrace.dump_on_shutdown", false, "If true, dump all stored traces on runtime shutdown.")
@@ -300,8 +306,9 @@
 	return f.FlagSet.Args()
 }
 
-// readEnv reads the legacy NAMESPACE_ROOT? and VEYRON_CREDENTIALS env vars.
-func readEnv() ([]string, string) {
+// readEnv reads the legacy NAMESPACE_ROOT?, VEYRON_CREDENTIALS,
+// and VANADIUM_I18N_CATALOGUE env vars.
+func readEnv() ([]string, string, string) {
 	roots := []string{}
 	for _, ev := range os.Environ() {
 		p := strings.SplitN(ev, "=", 2)
@@ -313,7 +320,7 @@
 			roots = append(roots, v)
 		}
 	}
-	return roots, os.Getenv(consts.VeyronCredentials)
+	return roots, os.Getenv(consts.VeyronCredentials), os.Getenv(consts.I18nCatalogueFiles)
 }
 
 // Parse parses the supplied args, as per flag.Parse.
diff --git a/runtimes/google/rt/rt.go b/runtimes/google/rt/rt.go
index e91f6f8..87b0625 100644
--- a/runtimes/google/rt/rt.go
+++ b/runtimes/google/rt/rt.go
@@ -5,6 +5,7 @@
 	"fmt"
 	"os"
 	"path/filepath"
+	"strings"
 	"sync"
 
 	"veyron.io/veyron/veyron2"
@@ -125,6 +126,16 @@
 		return nil, fmt.Errorf("failed to init sercurity: %s", err)
 	}
 
+	if len(rt.flags.I18nCatalogue) != 0 {
+		cat := i18n.Cat()
+		for _, filename := range strings.Split(rt.flags.I18nCatalogue, ",") {
+			err := cat.MergeFromFile(filename)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "%s: i18n: error reading i18n catalogue file %q: %s\n", os.Args[0], filename, err)
+			}
+		}
+	}
+
 	if rt.client, err = rt.NewClient(); err != nil {
 		return nil, fmt.Errorf("failed to create new client: %s", err)
 	}