First round of i18n in acs-engine based on gettext. Subsequent change… (#627)

* First round of i18n in acs-engine based on gettext. Subsequent changes will replace and extract resource strings in acs-engine and make acsengine/api package's i18n used by other go program.

* Update acs-engine go source to use translation functions. Generate translation resource files.

* Vendor github.com/leonelquinteros/gotext package using glide

* Rebase and update translation for update and deploy command

* Move test translation files so that translations directory is used for go-bindata

* Use go-bindata to add resource strings to acs-engine binary

* Fix reading bindata and unit test

* Update translation files

* More fix/refactor after rebase and add README

* Update resource files

* Add LCG files converted from PO files.

* Update translation bindata

* Remove go generated translation bindata
This commit is contained in:
Jiangtian Li 2017-07-31 16:24:16 -07:00 коммит произвёл GitHub
Родитель 2b09dca8f9
Коммит b41df8f90a
716 изменённых файлов: 18087 добавлений и 131 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -15,3 +15,4 @@ test/acs-engine-test/acs-engine-test.exe
pkg/operations/junit.xml
pkg/operations/kubernetesupgrade/junit.xml
pkg/acsengine/templates.go
pkg/i18n/translations.go

Просмотреть файл

@ -2,7 +2,7 @@ FROM buildpack-deps:xenial
RUN apt-get update \
&& apt-get -y upgrade \
&& apt-get -y install python-pip make build-essential curl openssl vim jq \
&& apt-get -y install python-pip make build-essential curl openssl vim jq gettext \
&& rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8
@ -34,6 +34,10 @@ RUN git clone https://github.com/akesterson/cmdarg.git /tmp/cmdarg \
RUN git clone https://github.com/akesterson/shunit.git /tmp/shunit \
&& cd /tmp/shunit && make install && rm -rf /tmp/shunit
# Go tool for internationalization and localization
RUN go get github.com/JiangtianLi/gettext/... \
&& go install github.com/JiangtianLi/gettext/...
# Used by some CI jobs
ADD ./test/bootstrap/checkout-pr.sh /tmp/checkout-pr.sh

Просмотреть файл

@ -9,6 +9,7 @@ import (
"time"
log "github.com/Sirupsen/logrus"
"github.com/leonelquinteros/gotext"
"github.com/spf13/cobra"
"encoding/json"
@ -16,6 +17,7 @@ import (
"github.com/Azure/acs-engine/pkg/acsengine"
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/armhelpers"
"github.com/Azure/acs-engine/pkg/i18n"
)
const (
@ -40,6 +42,7 @@ type deployCmd struct {
// derived
containerService *api.ContainerService
apiVersion string
locale *gotext.Locale
client armhelpers.ACSEngineClient
resourceGroup string
@ -78,6 +81,11 @@ func newDeployCmd() *cobra.Command {
func (dc *deployCmd) validate(cmd *cobra.Command, args []string) {
var err error
dc.locale, err = i18n.LoadTranslations()
if err != nil {
log.Fatalf("error loading translation files: %s", err.Error())
}
if dc.apimodelPath == "" {
if len(args) > 0 {
dc.apimodelPath = args[0]
@ -94,8 +102,13 @@ func (dc *deployCmd) validate(cmd *cobra.Command, args []string) {
log.Fatalf("specified api model does not exist (%s)", dc.apimodelPath)
}
apiloader := &api.Apiloader{
Translator: &i18n.Translator{
Locale: dc.locale,
},
}
// skip validating the model fields for now
dc.containerService, dc.apiVersion, err = api.LoadContainerServiceFromFile(dc.apimodelPath, false)
dc.containerService, dc.apiVersion, err = apiloader.LoadContainerServiceFromFile(dc.apimodelPath, false)
if err != nil {
log.Fatalf("error parsing the api model: %s", err.Error())
}
@ -112,7 +125,7 @@ func (dc *deployCmd) validate(cmd *cobra.Command, args []string) {
// autofillApimodel calls log.Fatal() directly and does not return errors
autofillApimodel(dc)
_, _, err = revalidateApimodel(dc.containerService, dc.apiVersion)
_, _, err = revalidateApimodel(apiloader, dc.containerService, dc.apiVersion)
if err != nil {
log.Fatalf("Failed to validate the apimodel after populating values: %s", err)
}
@ -162,7 +175,12 @@ func autofillApimodel(dc *deployCmd) {
if dc.containerService.Properties.LinuxProfile.SSH.PublicKeys == nil ||
len(dc.containerService.Properties.LinuxProfile.SSH.PublicKeys) == 0 ||
dc.containerService.Properties.LinuxProfile.SSH.PublicKeys[0].KeyData == "" {
_, publicKey, err := acsengine.CreateSaveSSH(dc.containerService.Properties.LinuxProfile.AdminUsername, dc.outputDirectory)
creator := &acsengine.SSHCreator{
Translator: &i18n.Translator{
Locale: dc.locale,
},
}
_, publicKey, err := creator.CreateSaveSSH(dc.containerService.Properties.LinuxProfile.AdminUsername, dc.outputDirectory)
if err != nil {
log.Fatal("Failed to generate SSH Key")
}
@ -211,17 +229,23 @@ func autofillApimodel(dc *deployCmd) {
}
}
func revalidateApimodel(containerService *api.ContainerService, apiVersion string) (*api.ContainerService, string, error) {
func revalidateApimodel(apiloader *api.Apiloader, containerService *api.ContainerService, apiVersion string) (*api.ContainerService, string, error) {
// This isn't terribly elegant, but it's the easiest way to go for now w/o duplicating a bunch of code
rawVersionedAPIModel, err := api.SerializeContainerService(containerService, apiVersion)
rawVersionedAPIModel, err := apiloader.SerializeContainerService(containerService, apiVersion)
if err != nil {
return nil, "", err
}
return api.DeserializeContainerService(rawVersionedAPIModel, true)
return apiloader.DeserializeContainerService(rawVersionedAPIModel, true)
}
func (dc *deployCmd) run() error {
templateGenerator, err := acsengine.InitializeTemplateGenerator(dc.classicMode)
ctx := acsengine.Context{
Translator: &i18n.Translator{
Locale: dc.locale,
},
}
templateGenerator, err := acsengine.InitializeTemplateGenerator(ctx, dc.classicMode)
if err != nil {
log.Fatalln("failed to initialize template generator: %s", err.Error())
}
@ -240,7 +264,12 @@ func (dc *deployCmd) run() error {
log.Fatalf("error pretty printing template parameters: %s \n", err.Error())
}
if err = acsengine.WriteTLSArtifacts(dc.containerService, dc.apiVersion, template, parametersFile, dc.outputDirectory, certsgenerated, dc.parametersOnly); err != nil {
writer := &acsengine.ArtifactWriter{
Translator: &i18n.Translator{
Locale: dc.locale,
},
}
if err = writer.WriteTLSArtifacts(dc.containerService, dc.apiVersion, template, parametersFile, dc.outputDirectory, certsgenerated, dc.parametersOnly); err != nil {
log.Fatalf("error writing artifacts: %s \n", err.Error())
}

Просмотреть файл

@ -47,8 +47,12 @@ func TestAutofillApimodelAllowsPrespecifiedCreds(t *testing.T) {
}
func testAutodeployCredentialHandling(t *testing.T, useManagedIdentity bool, clientID, clientSecret string) {
apiloader := &api.Apiloader{
Translator: nil,
}
apimodel := getExampleAPIModel(useManagedIdentity, clientID, clientSecret)
cs, ver, err := api.DeserializeContainerService([]byte(apimodel), false)
cs, ver, err := apiloader.DeserializeContainerService([]byte(apimodel), false)
if err != nil {
t.Fatalf("unexpected error deserializing the example apimodel: %s", err)
}
@ -73,7 +77,7 @@ func testAutodeployCredentialHandling(t *testing.T, useManagedIdentity bool, cli
// cleanup, since auto-populations creates dirs and saves the SSH private key that it might create
defer os.RemoveAll(deployCmd.outputDirectory)
cs, _, err = revalidateApimodel(cs, ver)
cs, _, err = revalidateApimodel(apiloader, cs, ver)
if err != nil {
log.Fatalf("unexpected error validating apimodel after populating defaults: %s", err)
}

Просмотреть файл

@ -7,7 +7,9 @@ import (
"github.com/Azure/acs-engine/pkg/acsengine"
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/i18n"
log "github.com/Sirupsen/logrus"
"github.com/leonelquinteros/gotext"
"github.com/spf13/cobra"
)
@ -29,6 +31,7 @@ type generateCmd struct {
// derived
containerService *api.ContainerService
apiVersion string
locale *gotext.Locale
}
func newGenerateCmd() *cobra.Command {
@ -61,6 +64,11 @@ func (gc *generateCmd) validate(cmd *cobra.Command, args []string) {
var caKeyBytes []byte
var err error
gc.locale, err = i18n.LoadTranslations()
if err != nil {
log.Fatalf("error loading translation files: %s", err.Error())
}
if gc.apimodelPath == "" {
if len(args) > 0 {
gc.apimodelPath = args[0]
@ -77,7 +85,12 @@ func (gc *generateCmd) validate(cmd *cobra.Command, args []string) {
log.Fatalf("specified api model does not exist (%s)", gc.apimodelPath)
}
gc.containerService, gc.apiVersion, err = api.LoadContainerServiceFromFile(gc.apimodelPath, true)
apiloader := &api.Apiloader{
Translator: &i18n.Translator{
Locale: gc.locale,
},
}
gc.containerService, gc.apiVersion, err = apiloader.LoadContainerServiceFromFile(gc.apimodelPath, true)
if err != nil {
log.Fatalf("error parsing the api model: %s", err.Error())
}
@ -111,7 +124,12 @@ func (gc *generateCmd) validate(cmd *cobra.Command, args []string) {
func (gc *generateCmd) run() error {
log.Infoln("Generating assets...")
templateGenerator, err := acsengine.InitializeTemplateGenerator(gc.classicMode)
ctx := acsengine.Context{
Translator: &i18n.Translator{
Locale: gc.locale,
},
}
templateGenerator, err := acsengine.InitializeTemplateGenerator(ctx, gc.classicMode)
if err != nil {
log.Fatalln("failed to initialize template generator: %s", err.Error())
}
@ -131,7 +149,12 @@ func (gc *generateCmd) run() error {
}
}
if err = acsengine.WriteTLSArtifacts(gc.containerService, gc.apiVersion, template, parameters, gc.outputDirectory, certsGenerated, gc.parametersOnly); err != nil {
writer := &acsengine.ArtifactWriter{
Translator: &i18n.Translator{
Locale: gc.locale,
},
}
if err = writer.WriteTLSArtifacts(gc.containerService, gc.apiVersion, template, parameters, gc.outputDirectory, certsGenerated, gc.parametersOnly); err != nil {
log.Fatalf("error writing artifacts: %s \n", err.Error())
}

Просмотреть файл

@ -9,7 +9,9 @@ import (
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/armhelpers"
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/Azure/acs-engine/pkg/operations/kubernetesupgrade"
"github.com/leonelquinteros/gotext"
log "github.com/Sirupsen/logrus"
"github.com/spf13/cobra"
@ -35,6 +37,7 @@ type upgradeCmd struct {
upgradeContainerService *api.UpgradeContainerService
upgradeAPIVersion string
client armhelpers.ACSEngineClient
locale *gotext.Locale
nameSuffix string
}
@ -65,6 +68,11 @@ func (uc *upgradeCmd) validate(cmd *cobra.Command, args []string) {
var err error
uc.locale, err = i18n.LoadTranslations()
if err != nil {
log.Fatalf("error loading translation files: %s", err.Error())
}
if uc.resourceGroupName == "" {
cmd.Usage()
log.Fatal("--resource-group must be specified")
@ -92,7 +100,12 @@ func (uc *upgradeCmd) validate(cmd *cobra.Command, args []string) {
log.Fatalf("specified api model does not exist (%s)", apiModelPath)
}
uc.containerService, uc.apiVersion, err = api.LoadContainerServiceFromFile(apiModelPath, true)
apiloader := &api.Apiloader{
Translator: &i18n.Translator{
Locale: uc.locale,
},
}
uc.containerService, uc.apiVersion, err = apiloader.LoadContainerServiceFromFile(apiModelPath, true)
if err != nil {
log.Fatalf("error parsing the api model: %s", err.Error())
}
@ -101,7 +114,12 @@ func (uc *upgradeCmd) validate(cmd *cobra.Command, args []string) {
log.Fatalf("specified upgrade model file does not exist (%s)", uc.upgradeModelFile)
}
uc.upgradeContainerService, uc.upgradeAPIVersion, err = api.LoadUpgradeContainerServiceFromFile(uc.upgradeModelFile)
upgradeapiloader := &api.UpgradeApiloader{
Translator: &i18n.Translator{
Locale: uc.locale,
},
}
uc.upgradeContainerService, uc.upgradeAPIVersion, err = upgradeapiloader.LoadUpgradeContainerServiceFromFile(uc.upgradeModelFile)
if err != nil {
log.Fatalf("error parsing the upgrade api model: %s", err.Error())
}
@ -134,6 +152,9 @@ func (uc *upgradeCmd) run(cmd *cobra.Command, args []string) error {
uc.validate(cmd, args)
upgradeCluster := kubernetesupgrade.UpgradeCluster{
Translator: &i18n.Translator{
Locale: uc.locale,
},
Client: uc.client,
}

8
glide.lock сгенерированный
Просмотреть файл

@ -36,6 +36,14 @@ imports:
version: b32fa301c9fe55953584134cb6853a13c87ec0a1
- name: github.com/inconshreveable/mousetrap
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
- name: github.com/leonelquinteros/gotext
version: a735812a72672008b3902f8b2bc1302166a9a8ea
- name: github.com/mattn/anko
version: a8c68fa2983e7dd5d3472992b1fbe2f7c44261f0
subpackages:
- ast
- parser
- vm
- name: github.com/mitchellh/go-homedir
version: b8bc1bf767474819792c23f32d8286a45736f1c6
- name: github.com/prometheus/common

Просмотреть файл

@ -32,6 +32,8 @@ import:
- package: github.com/spf13/cobra
version: 4cdb38c072b86bf795d2c81de50784d9fdd6eb77
- package: github.com/spf13/pflag
- package: github.com/leonelquinteros/gotext
version: v1.1.1
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66
- package: gopkg.in/go-playground/validator.v9
version: v9.4.0

Просмотреть файл

@ -16,6 +16,7 @@ import (
"text/template"
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/ghodss/yaml"
)
@ -193,7 +194,7 @@ func (t *TemplateGenerator) verifyFiles() error {
allFiles = append(allFiles, swarmTemplateFiles...)
for _, file := range allFiles {
if _, err := Asset(file); err != nil {
return fmt.Errorf("template file %s does not exist", file)
return t.Translator.Errorf("template file %s does not exist", file)
}
}
return nil
@ -202,12 +203,14 @@ func (t *TemplateGenerator) verifyFiles() error {
// TemplateGenerator represents the object that performs the template generation.
type TemplateGenerator struct {
ClassicMode bool
Translator *i18n.Translator
}
// InitializeTemplateGenerator creates a new template generator object
func InitializeTemplateGenerator(classicMode bool) (*TemplateGenerator, error) {
func InitializeTemplateGenerator(ctx Context, classicMode bool) (*TemplateGenerator, error) {
t := &TemplateGenerator{
ClassicMode: classicMode,
Translator: ctx.Translator,
}
if err := t.verifyFiles(); err != nil {
@ -234,7 +237,7 @@ func (t *TemplateGenerator) GenerateTemplate(containerService *api.ContainerServ
templ = template.New("acs template").Funcs(t.getTemplateFuncMap(containerService))
files, baseFile, e := prepareTemplateFiles(properties)
files, baseFile, e := t.prepareTemplateFiles(properties)
if e != nil {
return "", "", false, e
}
@ -242,7 +245,7 @@ func (t *TemplateGenerator) GenerateTemplate(containerService *api.ContainerServ
for _, file := range files {
bytes, e := Asset(file)
if e != nil {
err = fmt.Errorf("Error reading file %s, Error: %s", file, e.Error())
err = t.Translator.Errorf("Error reading file %s, Error: %s", file, e.Error())
return templateRaw, parametersRaw, certsGenerated, err
}
if _, err = templ.New(file).Parse(string(bytes)); err != nil {
@ -309,7 +312,7 @@ func GenerateKubeConfig(properties *api.Properties, location string) (string, er
return kubeconfig, nil
}
func prepareTemplateFiles(properties *api.Properties) ([]string, string, error) {
func (t *TemplateGenerator) prepareTemplateFiles(properties *api.Properties) ([]string, string, error) {
var files []string
var baseFile string
if properties.OrchestratorProfile.OrchestratorType == api.DCOS {
@ -325,7 +328,7 @@ func prepareTemplateFiles(properties *api.Properties) ([]string, string, error)
files = append(commonTemplateFiles, swarmModeTemplateFiles...)
baseFile = swarmBaseFile
} else {
return nil, "", fmt.Errorf("orchestrator '%s' is unsupported", properties.OrchestratorProfile.OrchestratorType)
return nil, "", t.Translator.Errorf("orchestrator '%s' is unsupported", properties.OrchestratorProfile.OrchestratorType)
}
return files, baseFile, nil
@ -1209,18 +1212,18 @@ func getSecurityRules(ports []int) string {
func (t *TemplateGenerator) getSingleLineForTemplate(textFilename string, cs *api.ContainerService, profile interface{}) (string, error) {
b, err := Asset(textFilename)
if err != nil {
return "", fmt.Errorf("yaml file %s does not exist", textFilename)
return "", t.Translator.Errorf("yaml file %s does not exist", textFilename)
}
// use go templates to process the text filename
templ := template.New("customdata template").Funcs(t.getTemplateFuncMap(cs))
if _, err = templ.New(textFilename).Parse(string(b)); err != nil {
return "", fmt.Errorf("error parsing file %s: %v", textFilename, err)
return "", t.Translator.Errorf("error parsing file %s: %v", textFilename, err)
}
var buffer bytes.Buffer
if err = templ.ExecuteTemplate(&buffer, textFilename, profile); err != nil {
return "", fmt.Errorf("error executing template for file %s: %v", textFilename, err)
return "", t.Translator.Errorf("error executing template for file %s: %v", textFilename, err)
}
expandedTemplate := buffer.String()

Просмотреть файл

@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"io/ioutil"
"path"
"path/filepath"
"strings"
"testing"
@ -11,6 +12,8 @@ import (
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/api/v20160330"
"github.com/Azure/acs-engine/pkg/api/vlabs"
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/leonelquinteros/gotext"
. "github.com/onsi/gomega"
)
@ -19,6 +22,15 @@ const (
)
func TestExpected(t *testing.T) {
// Initialize locale for translation
locale := gotext.NewLocale(path.Join("..", "..", "translations"), "en_US")
i18n.Initialize(locale)
apiloader := &api.Apiloader{
Translator: &i18n.Translator{
Locale: locale,
},
}
// iterate the test data directory
apiModelTestFiles := &[]APIModelTestFile{}
if e := IterateTestFilesDirectory(TestDataDir, apiModelTestFiles); e != nil {
@ -27,7 +39,7 @@ func TestExpected(t *testing.T) {
}
for _, tuple := range *apiModelTestFiles {
containerService, version, err := api.LoadContainerServiceFromFile(tuple.APIModelFilename, true)
containerService, version, err := apiloader.LoadContainerServiceFromFile(tuple.APIModelFilename, true)
if err != nil {
t.Errorf("Loading file %s got error: %s", tuple.APIModelFilename, err.Error())
continue
@ -51,7 +63,12 @@ func TestExpected(t *testing.T) {
// 1. first time tests loaded containerService
// 2. second time tests generated containerService
// 3. third time tests the generated containerService from the generated containerService
templateGenerator, e3 := InitializeTemplateGenerator(isClassicMode)
ctx := Context{
Translator: &i18n.Translator{
Locale: locale,
},
}
templateGenerator, e3 := InitializeTemplateGenerator(ctx, isClassicMode)
if e3 != nil {
t.Error(e3.Error())
continue
@ -118,11 +135,11 @@ func TestExpected(t *testing.T) {
t.Errorf("generated parameters different from expected for model %s: '%s'", tuple.APIModelFilename, diffstr)
}
b, err := api.SerializeContainerService(containerService, version)
b, err := apiloader.SerializeContainerService(containerService, version)
if err != nil {
t.Error(err)
}
containerService, version, err = api.DeserializeContainerService(b, true)
containerService, version, err = apiloader.DeserializeContainerService(b, true)
if err != nil {
t.Error(err)
}

Просмотреть файл

@ -0,0 +1,38 @@
package acsengine
import (
"io/ioutil"
"os"
"path"
"github.com/Azure/acs-engine/pkg/i18n"
log "github.com/Sirupsen/logrus"
)
// FileSaver represents the object that save string or byte data to file
type FileSaver struct {
Translator *i18n.Translator
}
// SaveFileString saves string to file
func (f *FileSaver) SaveFileString(dir string, file string, data string) error {
return f.SaveFile(dir, file, []byte(data))
}
// SaveFile saves binary data to file
func (f *FileSaver) SaveFile(dir string, file string, data []byte) error {
if _, err := os.Stat(dir); os.IsNotExist(err) {
if e := os.MkdirAll(dir, 0700); e != nil {
return f.Translator.Errorf("error creating directory '%s': %s", dir, e.Error())
}
}
path := path.Join(dir, file)
if err := ioutil.WriteFile(path, []byte(data), 0600); err != nil {
return err
}
log.Debugf("output: wrote %s", path)
return nil
}

Просмотреть файл

@ -2,41 +2,51 @@ package acsengine
import (
"fmt"
"io/ioutil"
"os"
"path"
"github.com/Azure/acs-engine/pkg/api"
log "github.com/Sirupsen/logrus"
"github.com/Azure/acs-engine/pkg/i18n"
)
// ArtifactWriter represents the object that writes artifacts
type ArtifactWriter struct {
Translator *i18n.Translator
}
// WriteTLSArtifacts saves TLS certificates and keys to the server filesystem
func WriteTLSArtifacts(containerService *api.ContainerService, apiVersion, template, parameters, artifactsDir string, certsGenerated bool, parametersOnly bool) error {
func (w *ArtifactWriter) WriteTLSArtifacts(containerService *api.ContainerService, apiVersion, template, parameters, artifactsDir string, certsGenerated bool, parametersOnly bool) error {
if len(artifactsDir) == 0 {
artifactsDir = fmt.Sprintf("%s-%s", containerService.Properties.OrchestratorProfile.OrchestratorType, GenerateClusterID(containerService.Properties))
artifactsDir = path.Join("_output", artifactsDir)
}
f := &FileSaver{
Translator: w.Translator,
}
// convert back the API object, and write it
var b []byte
var err error
if !parametersOnly {
b, err = api.SerializeContainerService(containerService, apiVersion)
apiloader := &api.Apiloader{
Translator: w.Translator,
}
b, err = apiloader.SerializeContainerService(containerService, apiVersion)
if err != nil {
return err
}
if e := saveFile(artifactsDir, "apimodel.json", b); e != nil {
if e := f.SaveFile(artifactsDir, "apimodel.json", b); e != nil {
return e
}
if e := saveFileString(artifactsDir, "azuredeploy.json", template); e != nil {
if e := f.SaveFileString(artifactsDir, "azuredeploy.json", template); e != nil {
return e
}
}
if e := saveFileString(artifactsDir, "azuredeploy.parameters.json", parameters); e != nil {
if e := f.SaveFileString(artifactsDir, "azuredeploy.parameters.json", parameters); e != nil {
return e
}
@ -56,59 +66,38 @@ func WriteTLSArtifacts(containerService *api.ContainerService, apiVersion, templ
if gkcerr != nil {
return gkcerr
}
if e := saveFileString(directory, fmt.Sprintf("kubeconfig.%s.json", location), b); e != nil {
if e := f.SaveFileString(directory, fmt.Sprintf("kubeconfig.%s.json", location), b); e != nil {
return e
}
}
}
if e := saveFileString(artifactsDir, "ca.key", properties.CertificateProfile.CaPrivateKey); e != nil {
if e := f.SaveFileString(artifactsDir, "ca.key", properties.CertificateProfile.CaPrivateKey); e != nil {
return e
}
if e := saveFileString(artifactsDir, "ca.crt", properties.CertificateProfile.CaCertificate); e != nil {
if e := f.SaveFileString(artifactsDir, "ca.crt", properties.CertificateProfile.CaCertificate); e != nil {
return e
}
if e := saveFileString(artifactsDir, "apiserver.key", properties.CertificateProfile.APIServerPrivateKey); e != nil {
if e := f.SaveFileString(artifactsDir, "apiserver.key", properties.CertificateProfile.APIServerPrivateKey); e != nil {
return e
}
if e := saveFileString(artifactsDir, "apiserver.crt", properties.CertificateProfile.APIServerCertificate); e != nil {
if e := f.SaveFileString(artifactsDir, "apiserver.crt", properties.CertificateProfile.APIServerCertificate); e != nil {
return e
}
if e := saveFileString(artifactsDir, "client.key", properties.CertificateProfile.ClientPrivateKey); e != nil {
if e := f.SaveFileString(artifactsDir, "client.key", properties.CertificateProfile.ClientPrivateKey); e != nil {
return e
}
if e := saveFileString(artifactsDir, "client.crt", properties.CertificateProfile.ClientCertificate); e != nil {
if e := f.SaveFileString(artifactsDir, "client.crt", properties.CertificateProfile.ClientCertificate); e != nil {
return e
}
if e := saveFileString(artifactsDir, "kubectlClient.key", properties.CertificateProfile.KubeConfigPrivateKey); e != nil {
if e := f.SaveFileString(artifactsDir, "kubectlClient.key", properties.CertificateProfile.KubeConfigPrivateKey); e != nil {
return e
}
if e := saveFileString(artifactsDir, "kubectlClient.crt", properties.CertificateProfile.KubeConfigCertificate); e != nil {
if e := f.SaveFileString(artifactsDir, "kubectlClient.crt", properties.CertificateProfile.KubeConfigCertificate); e != nil {
return e
}
}
return nil
}
func saveFileString(dir string, file string, data string) error {
return saveFile(dir, file, []byte(data))
}
func saveFile(dir string, file string, data []byte) error {
if _, err := os.Stat(dir); os.IsNotExist(err) {
if e := os.MkdirAll(dir, 0700); e != nil {
return fmt.Errorf("error creating directory '%s': %s", dir, e.Error())
}
}
path := path.Join(dir, file)
if err := ioutil.WriteFile(path, []byte(data), 0600); err != nil {
return err
}
log.Debugf("output: wrote %s", path)
return nil
}

Просмотреть файл

@ -6,25 +6,35 @@ import (
"fmt"
"io"
"github.com/Azure/acs-engine/pkg/i18n"
log "github.com/Sirupsen/logrus"
"golang.org/x/crypto/ssh"
)
// SSHCreator represents the object that creates SSH key pair
type SSHCreator struct {
Translator *i18n.Translator
}
const (
// SSHKeySize is the size (in bytes) of SSH key to create
SSHKeySize = 4096
)
// CreateSaveSSH generates and stashes an SSH key pair.
func CreateSaveSSH(username, outputDirectory string) (privateKey *rsa.PrivateKey, publicKeyString string, err error) {
privateKey, publicKeyString, err = CreateSSH(rand.Reader)
func (s *SSHCreator) CreateSaveSSH(username, outputDirectory string) (privateKey *rsa.PrivateKey, publicKeyString string, err error) {
privateKey, publicKeyString, err = s.CreateSSH(rand.Reader)
if err != nil {
return nil, "", err
}
privateKeyPem := privateKeyToPem(privateKey)
err = saveFile(outputDirectory, fmt.Sprintf("%s_rsa", username), privateKeyPem)
f := &FileSaver{
Translator: s.Translator,
}
err = f.SaveFile(outputDirectory, fmt.Sprintf("%s_rsa", username), privateKeyPem)
if err != nil {
return nil, "", err
}
@ -33,17 +43,17 @@ func CreateSaveSSH(username, outputDirectory string) (privateKey *rsa.PrivateKey
}
// CreateSSH creates an SSH key pair.
func CreateSSH(rg io.Reader) (privateKey *rsa.PrivateKey, publicKeyString string, err error) {
func (s *SSHCreator) CreateSSH(rg io.Reader) (privateKey *rsa.PrivateKey, publicKeyString string, err error) {
log.Debugf("ssh: generating %dbit rsa key", SSHKeySize)
privateKey, err = rsa.GenerateKey(rg, SSHKeySize)
if err != nil {
return nil, "", fmt.Errorf("failed to generate private key for ssh: %q", err)
return nil, "", s.Translator.Errorf("failed to generate private key for ssh: %q", err)
}
publicKey := privateKey.PublicKey
sshPublicKey, err := ssh.NewPublicKey(&publicKey)
if err != nil {
return nil, "", fmt.Errorf("failed to create openssh public key string: %q", err)
return nil, "", s.Translator.Errorf("failed to create openssh public key string: %q", err)
}
authorizedKeyBytes := ssh.MarshalAuthorizedKey(sshPublicKey)
authorizedKey := string(authorizedKeyBytes)

Просмотреть файл

@ -63,7 +63,11 @@ EPDesL0rH+3s1CKpgkhYdbJ675GFoGoq+X21QaqsdvoXmmuJF9qq9Tq+JaWloUNq
-----END RSA PRIVATE KEY-----
`
privateKey, publicKey, err := CreateSSH(rg)
creator := &SSHCreator{
Translator: nil,
}
privateKey, publicKey, err := creator.CreateSSH(rg)
if err != nil {
t.Fatalf("failed to generate SSH: %s", err)
}

Просмотреть файл

@ -5,6 +5,7 @@ import (
"log"
"strings"
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/Azure/azure-sdk-for-go/arm/compute"
"github.com/Sirupsen/logrus"
)
@ -35,9 +36,14 @@ const (
vmExtensionType = "Microsoft.Compute/virtualMachines/extensions"
)
// Transformer represents the object that transforms template
type Transformer struct {
Translator *i18n.Translator
}
// NormalizeForVMSSScaling takes a template and removes elements that are unwanted in a VMSS scale up/down case
func NormalizeForVMSSScaling(logger *logrus.Entry, templateMap map[string]interface{}) error {
if err := NormalizeMasterResourcesForScaling(logger, templateMap); err != nil {
func (t *Transformer) NormalizeForVMSSScaling(logger *logrus.Entry, templateMap map[string]interface{}) error {
if err := t.NormalizeMasterResourcesForScaling(logger, templateMap); err != nil {
return err
}
@ -66,7 +72,7 @@ func NormalizeForVMSSScaling(logger *logrus.Entry, templateMap map[string]interf
continue
}
if !removeCustomData(logger, virtualMachineProfile) || !removeImageReference(logger, virtualMachineProfile) {
if !t.removeCustomData(logger, virtualMachineProfile) || !t.removeImageReference(logger, virtualMachineProfile) {
continue
}
}
@ -74,8 +80,8 @@ func NormalizeForVMSSScaling(logger *logrus.Entry, templateMap map[string]interf
}
// NormalizeForK8sVMASScalingUp takes a template and removes elements that are unwanted in a K8s VMAS scale up/down case
func NormalizeForK8sVMASScalingUp(logger *logrus.Entry, templateMap map[string]interface{}) error {
if err := NormalizeMasterResourcesForScaling(logger, templateMap); err != nil {
func (t *Transformer) NormalizeForK8sVMASScalingUp(logger *logrus.Entry, templateMap map[string]interface{}) error {
if err := t.NormalizeMasterResourcesForScaling(logger, templateMap); err != nil {
return err
}
nsgIndex := -1
@ -90,7 +96,7 @@ func NormalizeForK8sVMASScalingUp(logger *logrus.Entry, templateMap map[string]i
resourceType, ok := resourceMap[typeFieldName].(string)
if ok && resourceType == nsgResourceType {
if nsgIndex != -1 {
err := fmt.Errorf("Found 2 resources with type %s in the template. There should only be 1", nsgResourceType)
err := t.Translator.Errorf("Found 2 resources with type %s in the template. There should only be 1", nsgResourceType)
logger.Errorf(err.Error())
return err
}
@ -113,7 +119,7 @@ func NormalizeForK8sVMASScalingUp(logger *logrus.Entry, templateMap map[string]i
resourceMap[dependsOnFieldName] = dependencies
}
if nsgIndex == -1 {
err := fmt.Errorf("Found no resources with type %s in the template. There should have been 1", nsgResourceType)
err := t.Translator.Errorf("Found no resources with type %s in the template. There should have been 1", nsgResourceType)
logger.Errorf(err.Error())
return err
}
@ -124,7 +130,7 @@ func NormalizeForK8sVMASScalingUp(logger *logrus.Entry, templateMap map[string]i
}
// NormalizeMasterResourcesForScaling takes a template and removes elements that are unwanted in any scale up/down case
func NormalizeMasterResourcesForScaling(logger *logrus.Entry, templateMap map[string]interface{}) error {
func (t *Transformer) NormalizeMasterResourcesForScaling(logger *logrus.Entry, templateMap map[string]interface{}) error {
resources := templateMap[resourcesFieldName].([]interface{})
//update master nodes resources
for _, resource := range resources {
@ -166,7 +172,7 @@ func NormalizeMasterResourcesForScaling(logger *logrus.Entry, templateMap map[st
delete(hardwareProfile, vmSizeFieldName)
}
if !removeCustomData(logger, resourceProperties) || !removeImageReference(logger, resourceProperties) {
if !t.removeCustomData(logger, resourceProperties) || !t.removeImageReference(logger, resourceProperties) {
continue
}
}
@ -174,7 +180,7 @@ func NormalizeMasterResourcesForScaling(logger *logrus.Entry, templateMap map[st
return nil
}
func removeCustomData(logger *logrus.Entry, resourceProperties map[string]interface{}) bool {
func (t *Transformer) removeCustomData(logger *logrus.Entry, resourceProperties map[string]interface{}) bool {
osProfile, ok := resourceProperties[osProfileFieldName].(map[string]interface{})
if !ok {
logger.Warnf("Template improperly formatted")
@ -187,7 +193,7 @@ func removeCustomData(logger *logrus.Entry, resourceProperties map[string]interf
return ok
}
func removeImageReference(logger *logrus.Entry, resourceProperties map[string]interface{}) bool {
func (t *Transformer) removeImageReference(logger *logrus.Entry, resourceProperties map[string]interface{}) bool {
storageProfile, ok := resourceProperties[storageProfileFieldName].(map[string]interface{})
if !ok {
logger.Warnf("Template improperly formatted. Could not find: %s", storageProfileFieldName)
@ -201,7 +207,7 @@ func removeImageReference(logger *logrus.Entry, resourceProperties map[string]in
}
// NormalizeResourcesForK8sMasterUpgrade takes a template and removes elements that are unwanted in any scale up/down case
func NormalizeResourcesForK8sMasterUpgrade(logger *logrus.Entry, templateMap map[string]interface{}, isMasterManagedDisk bool, agentPoolsToPreserve map[string]bool) error {
func (t *Transformer) NormalizeResourcesForK8sMasterUpgrade(logger *logrus.Entry, templateMap map[string]interface{}, isMasterManagedDisk bool, agentPoolsToPreserve map[string]bool) error {
resources := templateMap[resourcesFieldName].([]interface{})
logger.Infoln(fmt.Sprintf("Resource count before running NormalizeResourcesForK8sMasterUpgrade: %d", len(resources)))
@ -309,15 +315,15 @@ func NormalizeResourcesForK8sMasterUpgrade(logger *logrus.Entry, templateMap map
}
// NormalizeResourcesForK8sAgentUpgrade takes a template and removes elements that are unwanted in any scale up/down case
func NormalizeResourcesForK8sAgentUpgrade(logger *logrus.Entry, templateMap map[string]interface{}, isMasterManagedDisk bool, agentPoolsToPreserve map[string]bool) error {
func (t *Transformer) NormalizeResourcesForK8sAgentUpgrade(logger *logrus.Entry, templateMap map[string]interface{}, isMasterManagedDisk bool, agentPoolsToPreserve map[string]bool) error {
logger.Infoln(fmt.Sprintf("Running NormalizeResourcesForK8sMasterUpgrade...."))
if err := NormalizeResourcesForK8sMasterUpgrade(logger, templateMap, isMasterManagedDisk, agentPoolsToPreserve); err != nil {
if err := t.NormalizeResourcesForK8sMasterUpgrade(logger, templateMap, isMasterManagedDisk, agentPoolsToPreserve); err != nil {
log.Fatalln(err)
return err
}
logger.Infoln(fmt.Sprintf("Running NormalizeForK8sVMASScalingUp...."))
if err := NormalizeForK8sVMASScalingUp(logger, templateMap); err != nil {
if err := t.NormalizeForK8sVMASScalingUp(logger, templateMap); err != nil {
log.Fatalln(err)
return err
}

Просмотреть файл

@ -6,8 +6,10 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"testing"
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/Sirupsen/logrus"
. "github.com/onsi/gomega"
)
@ -55,9 +57,17 @@ func TestNormalizeResourcesForK8sMasterUpgrade(t *testing.T) {
var template interface{}
json.Unmarshal([]byte(templateJSON), &template)
templateMap := template.(map[string]interface{})
e = NormalizeResourcesForK8sMasterUpgrade(logger, templateMap)
locale, _ := i18n.LoadTranslations()
transformer := &Transformer{
Translator: i18n.Translator{
Locale: locale,
},
}
e = transformer.NormalizeResourcesForK8sMasterUpgrade(logger, templateMap)
Expect(e).To(BeNil())
ValidateTemplate(templateMap, expectedFileContents, "k8sVMASTemplate")
// Clean up
os.RemoveAll("./translations")
}
func TestNormalizeResourcesForK8sAgentUpgrade(t *testing.T) {
@ -71,9 +81,17 @@ func TestNormalizeResourcesForK8sAgentUpgrade(t *testing.T) {
var template interface{}
json.Unmarshal([]byte(templateJSON), &template)
templateMap := template.(map[string]interface{})
e = NormalizeResourcesForK8sAgentUpgrade(logger, templateMap)
locale, _ := i18n.LoadTranslations()
transformer := &Transformer{
Translator: i18n.Translator{
Locale: locale,
},
}
e = transformer.NormalizeResourcesForK8sAgentUpgrade(logger, templateMap)
Expect(e).To(BeNil())
ValidateTemplate(templateMap, expectedFileContents, "k8sVMASTemplate")
// Clean up
os.RemoveAll("./translations")
}
func ValidateTemplate(templateMap map[string]interface{}, expectedFileContents []byte, testFileName string) {

Просмотреть файл

@ -4,6 +4,7 @@ import (
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/api/v20160330"
"github.com/Azure/acs-engine/pkg/api/vlabs"
"github.com/Azure/acs-engine/pkg/i18n"
)
// DCOSNodeType represents the type of DCOS Node
@ -52,3 +53,8 @@ type AzureEnvironmentSpecConfig struct {
KubernetesSpecConfig KubernetesSpecConfig
DCOSSpecConfig DCOSSpecConfig
}
// Context represents the object that is passed to the package
type Context struct {
Translator *i18n.Translator
}

Просмотреть файл

@ -2,7 +2,6 @@ package api
import (
"encoding/json"
"fmt"
"io/ioutil"
"github.com/Azure/acs-engine/pkg/api/v20160330"
@ -10,31 +9,37 @@ import (
"github.com/Azure/acs-engine/pkg/api/v20170131"
"github.com/Azure/acs-engine/pkg/api/v20170701"
"github.com/Azure/acs-engine/pkg/api/vlabs"
"github.com/Azure/acs-engine/pkg/i18n"
)
// Apiloader represents the object that loads api model
type Apiloader struct {
Translator *i18n.Translator
}
// LoadContainerServiceFromFile loads an ACS Cluster API Model from a JSON file
func LoadContainerServiceFromFile(jsonFile string, validate bool) (*ContainerService, string, error) {
func (a *Apiloader) LoadContainerServiceFromFile(jsonFile string, validate bool) (*ContainerService, string, error) {
contents, e := ioutil.ReadFile(jsonFile)
if e != nil {
return nil, "", fmt.Errorf("error reading file %s: %s", jsonFile, e.Error())
return nil, "", a.Translator.Errorf("error reading file %s: %s", jsonFile, e.Error())
}
return DeserializeContainerService(contents, validate)
return a.DeserializeContainerService(contents, validate)
}
// DeserializeContainerService loads an ACS Cluster API Model, validates it, and returns the unversioned representation
func DeserializeContainerService(contents []byte, validate bool) (*ContainerService, string, error) {
func (a *Apiloader) DeserializeContainerService(contents []byte, validate bool) (*ContainerService, string, error) {
m := &TypeMeta{}
if err := json.Unmarshal(contents, &m); err != nil {
return nil, "", err
}
version := m.APIVersion
service, err := LoadContainerService(contents, version, validate)
service, err := a.LoadContainerService(contents, version, validate)
return service, version, err
}
// LoadContainerService loads an ACS Cluster API Model, validates it, and returns the unversioned representation
func LoadContainerService(contents []byte, version string, validate bool) (*ContainerService, error) {
func (a *Apiloader) LoadContainerService(contents []byte, version string, validate bool) (*ContainerService, error) {
switch version {
case v20160930.APIVersion:
containerService := &v20160930.ContainerService{}
@ -90,12 +95,12 @@ func LoadContainerService(contents []byte, version string, validate bool) (*Cont
return ConvertVLabsContainerService(containerService), nil
default:
return nil, fmt.Errorf("unrecognized APIVersion '%s'", version)
return nil, a.Translator.Errorf("unrecognized APIVersion '%s'", version)
}
}
// SerializeContainerService takes an unversioned container service and returns the bytes
func SerializeContainerService(containerService *ContainerService, version string) ([]byte, error) {
func (a *Apiloader) SerializeContainerService(containerService *ContainerService, version string) ([]byte, error) {
switch version {
case v20160930.APIVersion:
v20160930ContainerService := ConvertContainerServiceToV20160930(containerService)
@ -153,7 +158,7 @@ func SerializeContainerService(containerService *ContainerService, version strin
return b, nil
default:
return nil, fmt.Errorf("invalid version %s for conversion back from unversioned object", version)
return nil, a.Translator.Errorf("invalid version %s for conversion back from unversioned object", version)
}
}

Просмотреть файл

@ -45,7 +45,10 @@ func TestIsDCOS(t *testing.T) {
func TestCustomHyperkubeImageField(t *testing.T) {
log.Println(exampleAPIModel)
apimodel, _, err := DeserializeContainerService([]byte(exampleAPIModel), false)
apiloader := &Apiloader{
Translator: nil,
}
apimodel, _, err := apiloader.DeserializeContainerService([]byte(exampleAPIModel), false)
if err != nil {
t.Fatalf("unexpectedly error deserializing the example apimodel: %s", err)
}

Просмотреть файл

@ -2,35 +2,40 @@ package api
import (
"encoding/json"
"fmt"
"io/ioutil"
"github.com/Azure/acs-engine/pkg/api/vlabs"
"github.com/Azure/acs-engine/pkg/i18n"
)
// UpgradeApiloader represents the object that loads api model
type UpgradeApiloader struct {
Translator *i18n.Translator
}
// LoadUpgradeContainerServiceFromFile loads an ACS Cluster API Model from a JSON file
func LoadUpgradeContainerServiceFromFile(jsonFile string) (*UpgradeContainerService, string, error) {
func (ua *UpgradeApiloader) LoadUpgradeContainerServiceFromFile(jsonFile string) (*UpgradeContainerService, string, error) {
contents, e := ioutil.ReadFile(jsonFile)
if e != nil {
return nil, "", fmt.Errorf("error reading file %s: %s", jsonFile, e.Error())
return nil, "", ua.Translator.Errorf("error reading file %s: %s", jsonFile, e.Error())
}
return DeserializeUpgradeContainerService(contents)
return ua.DeserializeUpgradeContainerService(contents)
}
// DeserializeUpgradeContainerService loads an ACS Cluster API Model, validates it, and returns the unversioned representation
func DeserializeUpgradeContainerService(contents []byte) (*UpgradeContainerService, string, error) {
func (ua *UpgradeApiloader) DeserializeUpgradeContainerService(contents []byte) (*UpgradeContainerService, string, error) {
m := &TypeMeta{}
if err := json.Unmarshal(contents, &m); err != nil {
return nil, "", err
}
version := m.APIVersion
upgradecontainerservice, err := LoadUpgradeContainerService(contents, version)
upgradecontainerservice, err := ua.LoadUpgradeContainerService(contents, version)
return upgradecontainerservice, version, err
}
// LoadUpgradeContainerService loads an ACS Cluster API Model, validates it, and returns the unversioned representation
func LoadUpgradeContainerService(contents []byte, version string) (*UpgradeContainerService, error) {
func (ua *UpgradeApiloader) LoadUpgradeContainerService(contents []byte, version string) (*UpgradeContainerService, error) {
switch version {
case vlabs.APIVersion:
upgradecontainerService := &vlabs.UpgradeContainerService{}
@ -43,12 +48,12 @@ func LoadUpgradeContainerService(contents []byte, version string) (*UpgradeConta
return ConvertVLabsUpgradeContainerService(upgradecontainerService), nil
default:
return nil, fmt.Errorf("unrecognized APIVersion '%s'", version)
return nil, ua.Translator.Errorf("unrecognized APIVersion '%s'", version)
}
}
// SerializeUpgradeContainerService takes an unversioned container service and returns the bytes
func SerializeUpgradeContainerService(upgradeContainerService *UpgradeContainerService, version string) ([]byte, error) {
func (ua *UpgradeApiloader) SerializeUpgradeContainerService(upgradeContainerService *UpgradeContainerService, version string) ([]byte, error) {
switch version {
case vlabs.APIVersion:
vlabsUpgradeContainerService := ConvertUpgradeContainerServiceToVLabs(upgradeContainerService)
@ -62,6 +67,6 @@ func SerializeUpgradeContainerService(upgradeContainerService *UpgradeContainerS
return b, nil
default:
return nil, fmt.Errorf("invalid version %s for conversion back from unversioned object", version)
return nil, ua.Translator.Errorf("invalid version %s for conversion back from unversioned object", version)
}
}

25
pkg/i18n/README.md Normal file
Просмотреть файл

@ -0,0 +1,25 @@
# Translation and Internationalization in acs-engine
The translation process in acs-engine borrows some approach from [Kubernetes translation](https://github.com/kubernetes/kubernetes/tree/master/translations).
The strings to be localized are mainly the error message strings under `pkg` directory. Those error message strings are also consumed by other components such as ACS RP.
The localization in acs-engine depends on github.com/leonelquinteros/gotext, a GNU gettext utility for Go. The package supports concurrency in translating strings in multiple goroutines, e.g., the same acs-engine API called from multiple requests at the same time.
The translation files containing resource strings are packaged into acs-engine binary using go-bindata. At runtime, the translation files are recreated on disk in the same directory as acs-engine binary, for gotext to load.
## How to add new string to be localized
When a new error string needs to be localized, it needs to use translation function Errorf in `pkg/i18n/i18n.go`. The locale is passed to acs-engine API from acs-engine command or any other component calls it. If the locale is nil, then it falls back to en-us as in the Go source file.
Once the Go source file is modified, `scripts/update-translation.sh` needs to be run to extract the resource strings. The script generates PO file according to the locale specified. An example of running the script is:
```
scripts/update-translation.sh -l en_US -p
```
`poedit` is a common tool for translation. After the PO files are translated, MO files can be generated by either `poedit` or tool such as `msgfmt`. Both PO file and MO file need to be placed under `translations/<locale>/LC_MESSAGES/`.
## How to add a new language
When the resource strings need to be translated into a new language, the following steps are needed:
```
1. Use scripts/update-translation.sh with the language to genreate PO file
2. Translate the PO file and generate MO file.
3. Place PO file and MO file under `translations/<language>/LC_MESSAGES/` and commit
```

136
pkg/i18n/i18n.go Normal file
Просмотреть файл

@ -0,0 +1,136 @@
package i18n
import (
"errors"
"fmt"
"io/ioutil"
"os"
"strings"
"path"
"github.com/leonelquinteros/gotext"
)
const (
defaultLanguage = "default"
defaultDomain = "acsengine"
defaultLocalDir = "translations"
defaultMessageDir = "LC_MESSAGES"
)
var supportedTranslations = map[string]bool{
defaultLanguage: true,
"en_US": true,
"zh_CN": true,
}
func loadSystemLanguage() string {
language := os.Getenv("LANG")
if language == "" {
return defaultLanguage
}
// Posix locale name usually has the ll_CC.encoding syntax.
parts := strings.Split(language, ".")
if len(parts) == 0 {
return defaultLanguage
}
if _, ok := supportedTranslations[parts[0]]; ok {
return parts[0]
}
return defaultLanguage
}
// LoadTranslations loads translation files and sets the locale to
// the system locale. It should be called by the main program.
func LoadTranslations() (*gotext.Locale, error) {
lang := loadSystemLanguage()
SetLanguage(lang)
dir := path.Join(defaultLocalDir, lang, defaultMessageDir)
translationFiles := []string{
path.Join(dir, fmt.Sprintf("%s.mo", defaultDomain)),
path.Join(dir, fmt.Sprintf("%s.po", defaultDomain)),
}
if _, err := os.Stat(dir); os.IsNotExist(err) {
if err := os.MkdirAll(dir, 0700); err != nil {
return nil, err
}
}
for _, file := range translationFiles {
if _, err := os.Stat(file); os.IsNotExist(err) {
data, err := Asset(file)
if err != nil {
return nil, err
}
err = ioutil.WriteFile(file, data, 0600)
if err != nil {
return nil, err
}
}
}
locale := gotext.NewLocale(defaultLocalDir, lang)
Initialize(locale)
return locale, nil
}
// Initialize is the translation initialization function shared by the main program and package.
func Initialize(locale *gotext.Locale) error {
if locale == nil {
return fmt.Errorf("Initialize expected locale but got nil")
}
locale.AddDomain(defaultDomain)
return nil
}
// SetLanguage sets the program's current locale. If the language is not
// supported, then the default locale is used.
func SetLanguage(language string) {
if _, ok := supportedTranslations[language]; ok {
gotext.SetLanguage(language)
return
}
gotext.SetLanguage(defaultLanguage)
}
// GetLanguage queries the program's current locale.
func GetLanguage() string {
return gotext.GetLanguage()
}
// Translator is a wrapper over gotext's Locale and provides interface to
// translate text string and produce translated error
type Translator struct {
Locale *gotext.Locale
}
// T translates a text string, based on GNU's gettext library.
func (t *Translator) T(msgid string, vars ...interface{}) string {
if t.Locale == nil {
return fmt.Sprintf(msgid, vars...)
}
return t.Locale.GetD(defaultDomain, msgid, vars...)
}
// NT translates a text string into the appropriate plural form, based on GNU's gettext library.
func (t *Translator) NT(msgid, msgidPlural string, n int, vars ...interface{}) string {
if t.Locale == nil {
return fmt.Sprintf(msgidPlural, vars...)
}
return t.Locale.GetND(defaultDomain, msgid, msgidPlural, n, vars...)
}
// Errorf produces an error with a translated error string.
func (t *Translator) Errorf(msgid string, vars ...interface{}) error {
return errors.New(t.T(msgid, vars...))
}
// NErrorf produces an error with a translated error string in the appropriate plural form.
func (t *Translator) NErrorf(msgid, msgidPlural string, n int, vars ...interface{}) error {
return errors.New(t.NT(msgid, msgidPlural, n, vars...))
}

119
pkg/i18n/i18n_test.go Normal file
Просмотреть файл

@ -0,0 +1,119 @@
package i18n
import (
"os"
"strings"
"testing"
. "github.com/onsi/gomega"
)
func TestLoadTranslations(t *testing.T) {
RegisterTestingT(t)
origLang := os.Getenv("LANG")
if origLang != "" && !strings.HasPrefix(origLang, "en_US") {
// The unit test has only en_US translation files
return
}
_, err := LoadTranslations()
Expect(err).Should(BeNil())
}
func TestTranslationLanguage(t *testing.T) {
RegisterTestingT(t)
origLang := os.Getenv("LANG")
os.Setenv("LANG", "en_US.UTF-8")
_, err := LoadTranslations()
Expect(err).Should(BeNil())
lang := GetLanguage()
Expect(lang).Should(Equal("en_US"))
os.Setenv("LANG", origLang)
}
func TestTranslationLanguageDefault(t *testing.T) {
RegisterTestingT(t)
origLang := os.Getenv("LANG")
os.Setenv("LANG", "ll_CC.UTF-8")
_, err := LoadTranslations()
Expect(err).Should(BeNil())
lang := GetLanguage()
Expect(lang).Should(Equal("default"))
os.Setenv("LANG", origLang)
}
func TestTranslations(t *testing.T) {
RegisterTestingT(t)
origLang := os.Getenv("LANG")
if origLang != "" && !strings.HasPrefix(origLang, "en_US") {
// The unit test has only en_US translation files
return
}
l, err := LoadTranslations()
Expect(err).Should(BeNil())
translator := &Translator{
Locale: l,
}
msg := translator.T("Aloha")
Expect(msg).Should(Equal("Aloha"))
msg = translator.T("Hello %s", "World")
Expect(msg).Should(Equal("Hello World"))
}
func TestTranslationsPlural(t *testing.T) {
RegisterTestingT(t)
origLang := os.Getenv("LANG")
if origLang != "" && !strings.HasPrefix(origLang, "en_US") {
// The unit test has only en_US translation files
return
}
l, err := LoadTranslations()
Expect(err).Should(BeNil())
translator := &Translator{
Locale: l,
}
msg := translator.NT("There is %d parameter in resource %s", "There are %d parameters in resource %s", 1, 1, "Foo")
Expect(msg).Should(Equal("There is 1 parameter in resource Foo"))
msg = translator.NT("There is %d parameter in resource %s", "There are %d parameters in resource %s", 9, 9, "Foo")
Expect(msg).Should(Equal("There are 9 parameters in resource Foo"))
}
func TestTranslationsError(t *testing.T) {
RegisterTestingT(t)
origLang := os.Getenv("LANG")
if origLang != "" && !strings.HasPrefix(origLang, "en_US") {
// The unit test has only en_US translation files
return
}
l, err := LoadTranslations()
Expect(err).Should(BeNil())
translator := &Translator{
Locale: l,
}
e := translator.Errorf("File not exists")
Expect(e.Error()).Should(Equal("File not exists"))
e = translator.NErrorf("There is %d error in the api model", "There are %d errors in the api model", 3, 3)
Expect(e.Error()).Should(Equal("There are 3 errors in the api model"))
}

Просмотреть файл

@ -0,0 +1,6 @@
package i18n
//go:generate go-bindata -nometadata -pkg $GOPACKAGE -prefix ../../ -o translations.go ../../translations/...
//go:generate gofmt -s -l -w translations.go
// resourceloader use go-bindata (https://github.com/jteeuwen/go-bindata)
// go-bindata is the way we handle embedded files, like binary, template, etc.

Двоичные данные
pkg/i18n/translations/default/LC_MESSAGES/acsengine.mo Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,45 @@
# Test translations for acsengine package.
# Copyright (C) 2017
# Jiangtian Li <jiangtianli@hotmail.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: acsengine\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-18 00:31+0000\n"
"PO-Revision-Date: 2017-05-17 17:35-0700\n"
"Last-Translator: Jiangtian Li <jiangtianli@hotmail.com>\n"
"Language-Team: English\n"
"Language: en_US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.2\n"
#: test/i18n/i18ntestinput.go:28
msgid "Aloha"
msgstr "Aloha"
#: test/i18n/i18ntestinput.go:32
#, c-format
msgid "Hello %s"
msgstr "Hello %s"
#: test/i18n/i18ntestinput.go:36
#, c-format
msgid "There is %d parameter in resource %s"
msgid_plural "There are %d parameters in resource %s"
msgstr[0] "There is %d parameter in resource %s"
msgstr[1] "There are %d parameters in resource %s"
#: test/i18n/i18ntestinput.go:40
msgid "File not exists"
msgstr "File not exists"
#: test/i18n/i18ntestinput.go:44
#, c-format
msgid "There is %d error in the api model"
msgid_plural "There are %d errors in the api model"
msgstr[0] "There is %d error in the api model"
msgstr[1] "There are %d errors in the api model"

Двоичные данные
pkg/i18n/translations/en_US/LC_MESSAGES/acsengine.mo Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,45 @@
# Test translations for acsengine package.
# Copyright (C) 2017
# Jiangtian Li <jiangtianli@hotmail.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: acsengine\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-18 00:31+0000\n"
"PO-Revision-Date: 2017-05-17 17:35-0700\n"
"Last-Translator: Jiangtian Li <jiangtianli@hotmail.com>\n"
"Language-Team: English\n"
"Language: en_US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.2\n"
#: test/i18n/i18ntestinput.go:28
msgid "Aloha"
msgstr "Aloha"
#: test/i18n/i18ntestinput.go:32
#, c-format
msgid "Hello %s"
msgstr "Hello %s"
#: test/i18n/i18ntestinput.go:36
#, c-format
msgid "There is %d parameter in resource %s"
msgid_plural "There are %d parameters in resource %s"
msgstr[0] "There is %d parameter in resource %s"
msgstr[1] "There are %d parameters in resource %s"
#: test/i18n/i18ntestinput.go:40
msgid "File not exists"
msgstr "File not exists"
#: test/i18n/i18ntestinput.go:44
#, c-format
msgid "There is %d error in the api model"
msgid_plural "There are %d errors in the api model"
msgstr[0] "There is %d error in the api model"
msgstr[1] "There are %d errors in the api model"

Просмотреть файл

@ -11,6 +11,7 @@ import (
"github.com/Azure/acs-engine/pkg/acsengine"
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/armhelpers"
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/Azure/azure-sdk-for-go/arm/compute"
log "github.com/Sirupsen/logrus"
"github.com/satori/go.uuid"
@ -41,6 +42,7 @@ type AgentPoolTopology struct {
// (or X.X or X.X.X) to version y (or Y.Y or X.X.X). RIght now
// upgrades are supported for Kubernetes cluster only.
type UpgradeCluster struct {
Translator *i18n.Translator
ClusterTopology
Client armhelpers.ACSEngineClient
@ -66,20 +68,22 @@ func (uc *UpgradeCluster) UpgradeCluster(subscriptionID uuid.UUID, resourceGroup
uc.UpgradeModel = ucs
if err := uc.getClusterNodeStatus(subscriptionID, resourceGroup); err != nil {
return fmt.Errorf("Error while querying ARM for resources: %+v", err)
return uc.Translator.Errorf("Error while querying ARM for resources: %+v", err)
}
switch ucs.OrchestratorProfile.OrchestratorVersion {
case api.Kubernetes162:
log.Infoln(fmt.Sprintf("Upgrading to Kubernetes 1.6.2"))
upgrader := Kubernetes162upgrader{}
upgrader := Kubernetes162upgrader{
Translator: uc.Translator,
}
upgrader.ClusterTopology = uc.ClusterTopology
upgrader.Client = uc.Client
if err := upgrader.RunUpgrade(); err != nil {
return err
}
default:
return fmt.Errorf("Upgrade to Kubernetes version: %s is not supported from version: %s",
return uc.Translator.Errorf("Upgrade to Kubernetes version: %s is not supported from version: %s",
ucs.OrchestratorProfile.OrchestratorVersion,
uc.DataModel.Properties.OrchestratorProfile.OrchestratorVersion)
}
@ -182,7 +186,9 @@ func (uc *UpgradeCluster) addVMToAgentPool(vm compute.VirtualMachine, isUpgradab
}
// WriteTemplate writes upgrade template to a folder
func WriteTemplate(upgradeContainerService *api.ContainerService,
func WriteTemplate(
translator *i18n.Translator,
upgradeContainerService *api.ContainerService,
templateMap map[string]interface{}, parametersMap map[string]interface{}) {
updatedTemplateJSON, _ := json.Marshal(templateMap)
parametersJSON, _ := json.Marshal(parametersMap)
@ -196,7 +202,10 @@ func WriteTemplate(upgradeContainerService *api.ContainerService,
log.Fatalf("error pretty printing template parameters: %s \n", e.Error())
}
outputDirectory := path.Join("_output", upgradeContainerService.Properties.MasterProfile.DNSPrefix, "Upgrade")
if err := acsengine.WriteTLSArtifacts(upgradeContainerService, "vlabs", templateapp, parametersapp, outputDirectory, false, false); err != nil {
writer := &acsengine.ArtifactWriter{
Translator: translator,
}
if err := writer.WriteTLSArtifacts(upgradeContainerService, "vlabs", templateapp, parametersapp, outputDirectory, false, false); err != nil {
log.Fatalf("error writing artifacts: %s \n", err.Error())
}
}

Просмотреть файл

@ -6,6 +6,7 @@ import (
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/armhelpers"
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/onsi/ginkgo/reporters"
. "github.com/onsi/gomega"
"github.com/satori/go.uuid"
@ -29,7 +30,12 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
cs := api.ContainerService{}
ucs := api.UpgradeContainerService{}
uc := UpgradeCluster{}
locale, _ := i18n.LoadTranslations()
uc := UpgradeCluster{
Translator: &i18n.Translator{
Locale: locale,
},
}
mockClient := armhelpers.MockACSEngineClient{}
mockClient.FailListVirtualMachines = true
@ -40,6 +46,9 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() {
err := uc.UpgradeCluster(subID, "TestRg", &cs, &ucs, "12345678")
Expect(err.Error()).To(Equal("Error while querying ARM for resources: ListVirtualMachines failed"))
// Clean up
os.RemoveAll("./translations")
})
It("Should return error message when failing to detete VMs during upgrade operation", func() {

Просмотреть файл

@ -7,6 +7,7 @@ import (
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/armhelpers"
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/Azure/acs-engine/pkg/operations"
log "github.com/Sirupsen/logrus"
@ -17,6 +18,7 @@ var _ UpgradeNode = &UpgradeAgentNode{}
// UpgradeAgentNode upgrades a Kubernetes 1.5.3 agent node to 1.6.2
type UpgradeAgentNode struct {
Translator *i18n.Translator
TemplateMap map[string]interface{}
ParametersMap map[string]interface{}
UpgradeContainerService *api.ContainerService
@ -47,7 +49,7 @@ func (kan *UpgradeAgentNode) CreateNode(poolName string, agentNo int) error {
templateVariables := kan.TemplateMap["variables"].(map[string]interface{})
templateVariables[poolOffsetVarName] = agentNo
WriteTemplate(kan.UpgradeContainerService, kan.TemplateMap, kan.ParametersMap)
WriteTemplate(kan.Translator, kan.UpgradeContainerService, kan.TemplateMap, kan.ParametersMap)
random := rand.New(rand.NewSource(time.Now().UnixNano()))
deploymentSuffix := random.Int31()

Просмотреть файл

@ -7,6 +7,7 @@ import (
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/armhelpers"
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/Azure/acs-engine/pkg/operations"
log "github.com/Sirupsen/logrus"
)
@ -16,6 +17,7 @@ var _ UpgradeNode = &UpgradeMasterNode{}
// UpgradeMasterNode upgrades a Kubernetes 1.5.3 master node to 1.6.2
type UpgradeMasterNode struct {
Translator *i18n.Translator
TemplateMap map[string]interface{}
ParametersMap map[string]interface{}
UpgradeContainerService *api.ContainerService
@ -46,7 +48,7 @@ func (kmn *UpgradeMasterNode) CreateNode(poolName string, masterNo int) error {
masterOffset, _ := templateVariables["masterCount"]
log.Infoln(fmt.Sprintf("Master pool set count to: %v temporarily during upgrade...", masterOffset))
WriteTemplate(kmn.UpgradeContainerService, kmn.TemplateMap, kmn.ParametersMap)
WriteTemplate(kmn.Translator, kmn.UpgradeContainerService, kmn.TemplateMap, kmn.ParametersMap)
random := rand.New(rand.NewSource(time.Now().UnixNano()))
deploymentSuffix := random.Int31()

Просмотреть файл

@ -7,6 +7,7 @@ import (
"github.com/Azure/acs-engine/pkg/acsengine"
"github.com/Azure/acs-engine/pkg/api"
"github.com/Azure/acs-engine/pkg/armhelpers"
"github.com/Azure/acs-engine/pkg/i18n"
log "github.com/Sirupsen/logrus"
)
@ -15,6 +16,7 @@ var _ UpgradeWorkFlow = &Kubernetes162upgrader{}
// Kubernetes162upgrader upgrades a Kubernetes 1.5.3 cluster to 1.6.2
type Kubernetes162upgrader struct {
Translator *i18n.Translator
ClusterTopology
GoalStateDataModel *api.ContainerService
@ -25,7 +27,7 @@ type Kubernetes162upgrader struct {
func (ku *Kubernetes162upgrader) ClusterPreflightCheck() error {
// Check that current cluster is 1.5.3
if ku.DataModel.Properties.OrchestratorProfile.OrchestratorVersion != api.Kubernetes153 {
return fmt.Errorf("Upgrade to Kubernetes 1.6.2 is not supported from version: %s",
return ku.Translator.Errorf("Upgrade to Kubernetes 1.6.2 is not supported from version: %s",
ku.DataModel.Properties.OrchestratorProfile.OrchestratorVersion)
}
@ -62,17 +64,22 @@ func (ku *Kubernetes162upgrader) upgradeMasterNodes() error {
// Upgrade Master VMs
templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.GoalStateDataModel)
if err != nil {
return fmt.Errorf("error generating upgrade template: %s", err.Error())
return ku.Translator.Errorf("error generating upgrade template: %s", err.Error())
}
log.Infoln(fmt.Sprintf("Prepping master nodes for upgrade..."))
if err := acsengine.NormalizeResourcesForK8sMasterUpgrade(log.NewEntry(log.New()), templateMap, ku.DataModel.Properties.MasterProfile.IsManagedDisks(), nil); err != nil {
transformer := &acsengine.Transformer{
Translator: ku.Translator,
}
if err := transformer.NormalizeResourcesForK8sMasterUpgrade(log.NewEntry(log.New()), templateMap, ku.DataModel.Properties.MasterProfile.IsManagedDisks(), nil); err != nil {
log.Fatalln(err)
return err
}
upgradeMasterNode := UpgradeMasterNode{}
upgradeMasterNode := UpgradeMasterNode{
Translator: ku.Translator,
}
upgradeMasterNode.TemplateMap = templateMap
upgradeMasterNode.ParametersMap = parametersMap
upgradeMasterNode.UpgradeContainerService = ku.GoalStateDataModel
@ -92,7 +99,7 @@ func (ku *Kubernetes162upgrader) upgradeMasterNodes() error {
masterNodesInCluster := len(*ku.ClusterTopology.MasterVMs) + mastersUpgradedCount
log.Infoln(fmt.Sprintf("masterNodesInCluster: %d", masterNodesInCluster))
if masterNodesInCluster > expectedMasterCount {
return fmt.Errorf("Total count of master VMs: %d exceeded expected count: %d", masterNodesInCluster, expectedMasterCount)
return ku.Translator.Errorf("Total count of master VMs: %d exceeded expected count: %d", masterNodesInCluster, expectedMasterCount)
}
upgradedMastersIndex := make(map[int]bool)
@ -172,13 +179,16 @@ func (ku *Kubernetes162upgrader) upgradeAgentPools() error {
// Upgrade Agent VMs
templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.GoalStateDataModel)
if err != nil {
return fmt.Errorf("error generating upgrade template: %s", err.Error())
return ku.Translator.Errorf("error generating upgrade template: %s", err.Error())
}
log.Infoln(fmt.Sprintf("Prepping agent pool: %s for upgrade...", *agentPool.Name))
preservePools := map[string]bool{*agentPool.Name: true}
if err := acsengine.NormalizeResourcesForK8sAgentUpgrade(log.NewEntry(log.New()), templateMap, ku.DataModel.Properties.MasterProfile.IsManagedDisks(), preservePools); err != nil {
transformer := &acsengine.Transformer{
Translator: ku.Translator,
}
if err := transformer.NormalizeResourcesForK8sAgentUpgrade(log.NewEntry(log.New()), templateMap, ku.DataModel.Properties.MasterProfile.IsManagedDisks(), preservePools); err != nil {
log.Fatalln(err)
return err
}
@ -191,7 +201,9 @@ func (ku *Kubernetes162upgrader) upgradeAgentPools() error {
}
}
upgradeAgentNode := UpgradeAgentNode{}
upgradeAgentNode := UpgradeAgentNode{
Translator: ku.Translator,
}
upgradeAgentNode.TemplateMap = templateMap
upgradeAgentNode.ParametersMap = parametersMap
upgradeAgentNode.UpgradeContainerService = ku.GoalStateDataModel
@ -269,15 +281,18 @@ func (ku *Kubernetes162upgrader) upgradeAgentPools() error {
func (ku *Kubernetes162upgrader) generateUpgradeTemplate(upgradeContainerService *api.ContainerService) (map[string]interface{}, map[string]interface{}, error) {
var err error
templateGenerator, err := acsengine.InitializeTemplateGenerator(false)
ctx := acsengine.Context{
Translator: ku.Translator,
}
templateGenerator, err := acsengine.InitializeTemplateGenerator(ctx, false)
if err != nil {
return nil, nil, fmt.Errorf("failed to initialize template generator: %s", err.Error())
return nil, nil, ku.Translator.Errorf("failed to initialize template generator: %s", err.Error())
}
var templateJSON string
var parametersJSON string
if templateJSON, parametersJSON, _, err = templateGenerator.GenerateTemplate(upgradeContainerService); err != nil {
return nil, nil, fmt.Errorf("error generating upgrade template: %s", err.Error())
return nil, nil, ku.Translator.Errorf("error generating upgrade template: %s", err.Error())
}
var template interface{}

Просмотреть файл

@ -0,0 +1,59 @@
#!/bin/bash
GO_SOURCE="pkg/acsengine/*.go pkg/api/*.go pkg/operations/*.go pkg/operations/kubernetesupgrade/*.go"
LANGUAGE="en_US"
DOMAIN="acsengine"
generate_po="false"
generate_mo="false"
while getopts "hl:pm" opt; do
case $opt in
h)
echo "$0 [-l language] [-p] [-m]"
echo " -l <language>: Language to translate"
echo " -p extract strings and generate PO file"
echo " -m generate MO file"
exit 0
;;
l)
LANGUAGE="${OPTARG}"
;;
p)
generate_po="true"
;;
m)
generate_mo="true"
;;
\?)
echo "$0 [-l language] [-p] [-m]"
exit 1
;;
esac
done
if ! which go-xgettext > /dev/null; then
echo 'Can not find go-xgettext, install with:'
echo 'go get github.com/gosexy/gettext/go-xgettext'
exit 1
fi
if ! which msginit > /dev/null; then
echo 'Can not find msginit, install with:'
echo 'apt-get install gettext'
exit 1
fi
if [[ "${generate_po}" == "true" ]]; then
echo "Extract strings and generate PO files..."
go-xgettext -o ${DOMAIN}.pot --keyword=Translator.Errorf --keyword-plural=Translator.NErrorf --msgid-bugs-address="" --sort-output ${GO_SOURCE}
msginit -l ${LANGUAGE} -o ${DOMAIN}.po -i ${DOMAIN}.pot
fi
if [[ "${generate_mo}" == "true" ]]; then
echo "Generate MO file..."
if [ ! -f ${DOMAIN}.po ]; then
echo "${DOMAIN}.po not found!"
exit 1
fi
msgfmt -c -v -o ${DOMAIN}.mo ${DOMAIN}.po
fi

Просмотреть файл

@ -36,6 +36,7 @@ gometalinter \
--tests \
--vendor \
--deadline 60s \
--skip test/i18n \
./... || exit_code=1
echo

Просмотреть файл

@ -0,0 +1,45 @@
package fake
import (
"github.com/Azure/acs-engine/pkg/i18n"
"github.com/leonelquinteros/gotext"
)
// This file is used to generate the test translation file
// 1. go-xgettext -o i18ntestinput.pot --keyword=translator.T --keyword-plural=translator.NT --msgid-bugs-address="" --sort-output test/i18n/i18ntestinput.go
// 2. go-xgettext -o i18ntestinput.err.pot --keyword=translator.Errorf --keyword-plural=translator.NErrorf --msgid-bugs-address="" --sort-output test/i18n/i18ntestinput.go
// 3. sed '1,18d' i18ntestinput.err.pot >> i18ntestinput.pot
// 4. msginit -l en_US -o i18ntestinput.po -i i18ntestinput.pot
// 5. Modify i18ntestinput.po using poedit as necessary
// Or msgfmt -c -v -o i18ntestinput.mo i18ntestinput.po
// 6. for d in "default" "en_US"; do cp i18ntestinput.mo translations/test/$d/LC_MESSAGES/acsengine.mo; cp i18ntestinput.po translations/test/$d/LC_MESSAGES/acsengine.po; done
// 7. rm i18ntestinput.*
var (
locale = gotext.NewLocale("d", "l")
translator = &i18n.Translator{
Locale: locale,
}
world = "World"
resource = "Foo"
)
func aloha() {
translator.T("Aloha")
}
func foo() {
translator.T("Hello %s", world)
}
func bar() {
translator.NT("There is %d parameter in resource %s", "There are %d parameters in resource %s", 9, 9, resource)
}
func file() error {
return translator.Errorf("File not exists")
}
func api() error {
return translator.NErrorf("There is %d error in the api model", "There are %d errors in the api model", 3, 3)
}

Двоичные данные
translations/default/LC_MESSAGES/acsengine.mo Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,121 @@
# English translations for acs-engine package.
# Copyright (C) 2017
# This file is distributed under the same license as the acs-engine package.
# Jiangtian Li <jiangtianli@hotmail.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: acsengine\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-25 00:04+0000\n"
"PO-Revision-Date: 2017-07-24 17:23-0700\n"
"Last-Translator: Jiangtian Li <jiangtianli@hotmail.com>\n"
"Language-Team: English\n"
"Language: en_US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.3\n"
#: pkg/acsengine/engine.go:239
#, c-format
msgid "Error reading file %s, Error: %s"
msgstr "Error reading file %s, Error: %s"
#: pkg/operations/kubernetesupgrade/upgradecluster.go:71
#, c-format
msgid "Error while querying ARM for resources: %+v"
msgstr "Error while querying ARM for resources: %+v"
#: pkg/acsengine/transform.go:99
#, c-format
msgid "Found 2 resources with type %s in the template. There should only be 1"
msgstr "Found 2 resources with type %s in the template. There should only be 1"
#: pkg/acsengine/transform.go:122
#, c-format
msgid "Found no resources with type %s in the template. There should have been 1"
msgstr "Found no resources with type %s in the template. There should have been 1"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:102
#, c-format
msgid "Total count of master VMs: %d exceeded expected count: %d"
msgstr "Total count of master VMs: %d exceeded expected count: %d"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:30
#, c-format
msgid "Upgrade to Kubernetes 1.6.2 is not supported from version: %s"
msgstr "Upgrade to Kubernetes 1.6.2 is not supported from version: %s"
#: pkg/operations/kubernetesupgrade/upgradecluster.go:86
#, c-format
msgid "Upgrade to Kubernetes version: %s is not supported from version: %s"
msgstr "Upgrade to Kubernetes version: %s is not supported from version: %s"
#: pkg/acsengine/filesaver.go:24
#, c-format
msgid "error creating directory '%s': %s"
msgstr "error creating directory '%s': %s"
#: pkg/acsengine/engine.go:1194
#, c-format
msgid "error executing template for file %s: %v"
msgstr "error executing template for file %s: %v"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:67
#: pkg/operations/kubernetesupgrade/v162upgrader.go:182
#: pkg/operations/kubernetesupgrade/v162upgrader.go:295
#, c-format
msgid "error generating upgrade template: %s"
msgstr "error generating upgrade template: %s"
#: pkg/acsengine/engine.go:1189
#, c-format
msgid "error parsing file %s: %v"
msgstr "error parsing file %s: %v"
#: pkg/api/apiloader.go:24 pkg/api/upgradeapiloader.go:20
#, c-format
msgid "error reading file %s: %s"
msgstr "error reading file %s: %s"
#: pkg/acsengine/ssh.go:55
#, c-format
msgid "failed to create openssh public key string: %q"
msgstr "failed to create openssh public key string: %q"
#: pkg/acsengine/ssh.go:49
#, c-format
msgid "failed to generate private key for ssh: %q"
msgstr "failed to generate private key for ssh: %q"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:289
#, c-format
msgid "failed to initialize template generator: %s"
msgstr "failed to initialize template generator: %s"
#: pkg/api/apiloader.go:161 pkg/api/upgradeapiloader.go:70
#, c-format
msgid "invalid version %s for conversion back from unversioned object"
msgstr "invalid version %s for conversion back from unversioned object"
#: pkg/acsengine/engine.go:322
#, c-format
msgid "orchestrator '%s' is unsupported"
msgstr "orchestrator '%s' is unsupported"
#: pkg/acsengine/engine.go:187
#, c-format
msgid "template file %s does not exist"
msgstr "template file %s does not exist"
#: pkg/api/apiloader.go:98 pkg/api/upgradeapiloader.go:51
#, c-format
msgid "unrecognized APIVersion '%s'"
msgstr "unrecognized APIVersion '%s'"
#: pkg/acsengine/engine.go:1183
#, c-format
msgid "yaml file %s does not exist"
msgstr "yaml file %s does not exist"

Просмотреть файл

@ -0,0 +1,126 @@
<?xml version="1.0"?>
<LCX SchemaVersion="6.0" Name="acsengine" PsrId="1" SrcCul="en-US" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
<Item ItemType="0" ItemId="1" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error reading file %s, Error: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="2" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error while querying ARM for resources: %+v]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="3" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 2 resources with type %s in the template. There should only be 1]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="4" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found no resources with type %s in the template. There should have been 1]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="5" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Total count of master VMs: %d exceeded expected count: %d]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="6" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes 1.6.2 is not supported from version: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="7" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes version: %s is not supported from version: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="8" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error creating directory '%s': %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="9" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error executing template for file %s: %v]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="10" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error generating upgrade template: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="11" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error parsing file %s: %v]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="12" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error reading file %s: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="13" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to create openssh public key string: %q]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="14" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to generate private key for ssh: %q]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="15" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to initialize template generator: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="16" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[invalid version %s for conversion back from unversioned object]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="17" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[orchestrator '%s' is unsupported]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="18" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[template file %s does not exist]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="19" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[unrecognized APIVersion '%s']]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="20" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[yaml file %s does not exist]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<OwnedComments>
<Cmt Name="LcxAdmin" />
</OwnedComments>
</LCX>

Просмотреть файл

@ -0,0 +1,187 @@
<?xml version="1.0"?>
<LCX SchemaVersion="6.0" Name="acsengine" PsrId="1" SrcCul="en-US" TgtCul="en-US" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
<Item ItemType="0" ItemId="1" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error reading file %s, Error: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Error reading file %s, Error: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="2" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error while querying ARM for resources: %+v]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Error while querying ARM for resources: %+v]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="3" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 2 resources with type %s in the template. There should only be 1]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Found 2 resources with type %s in the template. There should only be 1]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="4" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found no resources with type %s in the template. There should have been 1]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Found no resources with type %s in the template. There should have been 1]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="5" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Total count of master VMs: %d exceeded expected count: %d]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Total count of master VMs: %d exceeded expected count: %d]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="6" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes 1.6.2 is not supported from version: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Upgrade to Kubernetes 1.6.2 is not supported from version: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="7" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes version: %s is not supported from version: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Upgrade to Kubernetes version: %s is not supported from version: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="8" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error creating directory '%s': %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error creating directory '%s': %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="9" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error executing template for file %s: %v]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error executing template for file %s: %v]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="10" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error generating upgrade template: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error generating upgrade template: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="11" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error parsing file %s: %v]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error parsing file %s: %v]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="12" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error reading file %s: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error reading file %s: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="13" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to create openssh public key string: %q]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[failed to create openssh public key string: %q]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="14" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to generate private key for ssh: %q]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[failed to generate private key for ssh: %q]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="15" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to initialize template generator: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[failed to initialize template generator: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="16" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[invalid version %s for conversion back from unversioned object]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[invalid version %s for conversion back from unversioned object]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="17" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[orchestrator '%s' is unsupported]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[orchestrator '%s' is unsupported]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="18" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[template file %s does not exist]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[template file %s does not exist]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="19" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[unrecognized APIVersion '%s']]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[unrecognized APIVersion '%s']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="20" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[yaml file %s does not exist]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[yaml file %s does not exist]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<OwnedComments>
<Cmt Name="LcxAdmin" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="Lss" />
</LCX>

Просмотреть файл

@ -0,0 +1,135 @@
<?xml version="1.0"?>
<LCX SchemaVersion="6.0" Name="acsengine" PsrId="1" SrcCul="en-US" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
<Item ItemId="1">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:239" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="2">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/upgradecluster.go:71" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="3">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/transform.go:99" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="4">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/transform.go:122" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="5">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:102" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="6">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:30" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="7">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/upgradecluster.go:86" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="8">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/filesaver.go:24" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="9">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:1194" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="10">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:67" />
<Str Name="PO_Metadata1" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:182" />
<Str Name="PO_Metadata2" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:295" />
<Str Name="PO_Metadata3" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="11">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:1189" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="12">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/api/apiloader.go:24 pkg/api/upgradeapiloader.go:20" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="13">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/ssh.go:55" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="14">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/ssh.go:49" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="15">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:289" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="16">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/api/apiloader.go:161 pkg/api/upgradeapiloader.go:70" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="17">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:322" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="18">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:187" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="19">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/api/apiloader.go:98 pkg/api/upgradeapiloader.go:51" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="20">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:1183" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Props>
<Str Name="CopyrightHeader0" Val="# English translations for acs-engine package." />
<Str Name="CopyrightHeader1" Val="# Copyright (C) 2017" />
<Str Name="CopyrightHeader2" Val="# This file is distributed under the same license as the acs-engine package." />
<Str Name="CopyrightHeader3" Val="# Jiangtian Li &lt;jiangtianli@hotmail.com&gt;, 2017." />
<Str Name="FromFile" Val="D:\GoWork\src\github.com\Azure\acs-engine\translations\default\LC_MESSAGES\acsengine.po" />
<Str Name="FromRepository" Val="acsengine" />
<Str Name="PO_Header" Val="Project-Id-Version: acsengine\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2017-07-25 00:04+0000\nPO-Revision-Date: 2017-07-24 17:23-0700\nLast-Translator: Jiangtian Li &lt;jiangtianli@hotmail.com&gt;\nLanguage-Team: English\nLanguage: en_US\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n != 1);\nX-Generator: Poedit 2.0.3\n" />
<Str Name="NPlurals" Val="2" />
</Props>
</LCX>

Двоичные данные
translations/en_US/LC_MESSAGES/acsengine.mo Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,121 @@
# English translations for acs-engine package.
# Copyright (C) 2017
# This file is distributed under the same license as the acs-engine package.
# Jiangtian Li <jiangtianli@hotmail.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: acsengine\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-25 00:04+0000\n"
"PO-Revision-Date: 2017-07-24 17:23-0700\n"
"Last-Translator: Jiangtian Li <jiangtianli@hotmail.com>\n"
"Language-Team: English\n"
"Language: en_US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.3\n"
#: pkg/acsengine/engine.go:239
#, c-format
msgid "Error reading file %s, Error: %s"
msgstr "Error reading file %s, Error: %s"
#: pkg/operations/kubernetesupgrade/upgradecluster.go:71
#, c-format
msgid "Error while querying ARM for resources: %+v"
msgstr "Error while querying ARM for resources: %+v"
#: pkg/acsengine/transform.go:99
#, c-format
msgid "Found 2 resources with type %s in the template. There should only be 1"
msgstr "Found 2 resources with type %s in the template. There should only be 1"
#: pkg/acsengine/transform.go:122
#, c-format
msgid "Found no resources with type %s in the template. There should have been 1"
msgstr "Found no resources with type %s in the template. There should have been 1"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:102
#, c-format
msgid "Total count of master VMs: %d exceeded expected count: %d"
msgstr "Total count of master VMs: %d exceeded expected count: %d"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:30
#, c-format
msgid "Upgrade to Kubernetes 1.6.2 is not supported from version: %s"
msgstr "Upgrade to Kubernetes 1.6.2 is not supported from version: %s"
#: pkg/operations/kubernetesupgrade/upgradecluster.go:86
#, c-format
msgid "Upgrade to Kubernetes version: %s is not supported from version: %s"
msgstr "Upgrade to Kubernetes version: %s is not supported from version: %s"
#: pkg/acsengine/filesaver.go:24
#, c-format
msgid "error creating directory '%s': %s"
msgstr "error creating directory '%s': %s"
#: pkg/acsengine/engine.go:1194
#, c-format
msgid "error executing template for file %s: %v"
msgstr "error executing template for file %s: %v"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:67
#: pkg/operations/kubernetesupgrade/v162upgrader.go:182
#: pkg/operations/kubernetesupgrade/v162upgrader.go:295
#, c-format
msgid "error generating upgrade template: %s"
msgstr "error generating upgrade template: %s"
#: pkg/acsengine/engine.go:1189
#, c-format
msgid "error parsing file %s: %v"
msgstr "error parsing file %s: %v"
#: pkg/api/apiloader.go:24 pkg/api/upgradeapiloader.go:20
#, c-format
msgid "error reading file %s: %s"
msgstr "error reading file %s: %s"
#: pkg/acsengine/ssh.go:55
#, c-format
msgid "failed to create openssh public key string: %q"
msgstr "failed to create openssh public key string: %q"
#: pkg/acsengine/ssh.go:49
#, c-format
msgid "failed to generate private key for ssh: %q"
msgstr "failed to generate private key for ssh: %q"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:289
#, c-format
msgid "failed to initialize template generator: %s"
msgstr "failed to initialize template generator: %s"
#: pkg/api/apiloader.go:161 pkg/api/upgradeapiloader.go:70
#, c-format
msgid "invalid version %s for conversion back from unversioned object"
msgstr "invalid version %s for conversion back from unversioned object"
#: pkg/acsengine/engine.go:322
#, c-format
msgid "orchestrator '%s' is unsupported"
msgstr "orchestrator '%s' is unsupported"
#: pkg/acsengine/engine.go:187
#, c-format
msgid "template file %s does not exist"
msgstr "template file %s does not exist"
#: pkg/api/apiloader.go:98 pkg/api/upgradeapiloader.go:51
#, c-format
msgid "unrecognized APIVersion '%s'"
msgstr "unrecognized APIVersion '%s'"
#: pkg/acsengine/engine.go:1183
#, c-format
msgid "yaml file %s does not exist"
msgstr "yaml file %s does not exist"

Просмотреть файл

@ -0,0 +1,126 @@
<?xml version="1.0"?>
<LCX SchemaVersion="6.0" Name="acsengine" PsrId="1" SrcCul="en-US" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
<Item ItemType="0" ItemId="1" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error reading file %s, Error: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="2" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error while querying ARM for resources: %+v]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="3" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 2 resources with type %s in the template. There should only be 1]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="4" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found no resources with type %s in the template. There should have been 1]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="5" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Total count of master VMs: %d exceeded expected count: %d]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="6" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes 1.6.2 is not supported from version: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="7" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes version: %s is not supported from version: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="8" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error creating directory '%s': %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="9" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error executing template for file %s: %v]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="10" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error generating upgrade template: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="11" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error parsing file %s: %v]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="12" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error reading file %s: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="13" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to create openssh public key string: %q]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="14" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to generate private key for ssh: %q]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="15" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to initialize template generator: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="16" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[invalid version %s for conversion back from unversioned object]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="17" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[orchestrator '%s' is unsupported]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="18" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[template file %s does not exist]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="19" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[unrecognized APIVersion '%s']]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="20" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[yaml file %s does not exist]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<OwnedComments>
<Cmt Name="LcxAdmin" />
</OwnedComments>
</LCX>

Просмотреть файл

@ -0,0 +1,187 @@
<?xml version="1.0"?>
<LCX SchemaVersion="6.0" Name="acsengine" PsrId="1" SrcCul="en-US" TgtCul="en-US" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
<Item ItemType="0" ItemId="1" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error reading file %s, Error: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Error reading file %s, Error: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="2" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error while querying ARM for resources: %+v]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Error while querying ARM for resources: %+v]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="3" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 2 resources with type %s in the template. There should only be 1]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Found 2 resources with type %s in the template. There should only be 1]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="4" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found no resources with type %s in the template. There should have been 1]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Found no resources with type %s in the template. There should have been 1]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="5" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Total count of master VMs: %d exceeded expected count: %d]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Total count of master VMs: %d exceeded expected count: %d]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="6" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes 1.6.2 is not supported from version: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Upgrade to Kubernetes 1.6.2 is not supported from version: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="7" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes version: %s is not supported from version: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Upgrade to Kubernetes version: %s is not supported from version: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="8" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error creating directory '%s': %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error creating directory '%s': %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="9" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error executing template for file %s: %v]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error executing template for file %s: %v]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="10" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error generating upgrade template: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error generating upgrade template: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="11" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error parsing file %s: %v]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error parsing file %s: %v]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="12" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error reading file %s: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error reading file %s: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="13" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to create openssh public key string: %q]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[failed to create openssh public key string: %q]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="14" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to generate private key for ssh: %q]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[failed to generate private key for ssh: %q]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="15" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to initialize template generator: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[failed to initialize template generator: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="16" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[invalid version %s for conversion back from unversioned object]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[invalid version %s for conversion back from unversioned object]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="17" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[orchestrator '%s' is unsupported]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[orchestrator '%s' is unsupported]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="18" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[template file %s does not exist]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[template file %s does not exist]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="19" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[unrecognized APIVersion '%s']]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[unrecognized APIVersion '%s']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="20" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[yaml file %s does not exist]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[yaml file %s does not exist]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<OwnedComments>
<Cmt Name="LcxAdmin" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="Lss" />
</LCX>

Просмотреть файл

@ -0,0 +1,135 @@
<?xml version="1.0"?>
<LCX SchemaVersion="6.0" Name="acsengine" PsrId="1" SrcCul="en-US" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
<Item ItemId="1">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:239" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="2">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/upgradecluster.go:71" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="3">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/transform.go:99" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="4">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/transform.go:122" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="5">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:102" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="6">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:30" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="7">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/upgradecluster.go:86" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="8">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/filesaver.go:24" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="9">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:1194" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="10">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:67" />
<Str Name="PO_Metadata1" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:182" />
<Str Name="PO_Metadata2" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:295" />
<Str Name="PO_Metadata3" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="11">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:1189" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="12">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/api/apiloader.go:24 pkg/api/upgradeapiloader.go:20" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="13">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/ssh.go:55" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="14">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/ssh.go:49" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="15">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:289" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="16">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/api/apiloader.go:161 pkg/api/upgradeapiloader.go:70" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="17">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:322" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="18">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:187" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="19">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/api/apiloader.go:98 pkg/api/upgradeapiloader.go:51" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="20">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:1183" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Props>
<Str Name="CopyrightHeader0" Val="# English translations for acs-engine package." />
<Str Name="CopyrightHeader1" Val="# Copyright (C) 2017" />
<Str Name="CopyrightHeader2" Val="# This file is distributed under the same license as the acs-engine package." />
<Str Name="CopyrightHeader3" Val="# Jiangtian Li &lt;jiangtianli@hotmail.com&gt;, 2017." />
<Str Name="FromFile" Val="D:\GoWork\src\github.com\Azure\acs-engine\translations\en_US\LC_MESSAGES\acsengine.po" />
<Str Name="FromRepository" Val="acsengine" />
<Str Name="PO_Header" Val="Project-Id-Version: acsengine\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2017-07-25 00:04+0000\nPO-Revision-Date: 2017-07-24 17:23-0700\nLast-Translator: Jiangtian Li &lt;jiangtianli@hotmail.com&gt;\nLanguage-Team: English\nLanguage: en_US\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n != 1);\nX-Generator: Poedit 2.0.3\n" />
<Str Name="NPlurals" Val="2" />
</Props>
</LCX>

Двоичные данные
translations/zh_CN/LC_MESSAGES/acsengine.mo Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,120 @@
# Chinese translations for acs-engine package.
# Copyright (C) 2017
# This file is distributed under the same license as the acs-engine package.
# Jiangtian Li <jiangtianli@hotmail.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-25 00:11+0000\n"
"PO-Revision-Date: 2017-07-24 17:21-0700\n"
"Last-Translator: Jiangtian Li <jiangtianli@hotmail.com>\n"
"Language-Team: Chinese (simplified)\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.0.3\n"
#: pkg/acsengine/engine.go:239
#, c-format
msgid "Error reading file %s, Error: %s"
msgstr "文件 %s错误读取时出错: %s"
#: pkg/operations/kubernetesupgrade/upgradecluster.go:71
#, c-format
msgid "Error while querying ARM for resources: %+v"
msgstr "查询ARM资源时出错 %+v"
#: pkg/acsengine/transform.go:99
#, c-format
msgid "Found 2 resources with type %s in the template. There should only be 1"
msgstr "模板发现两个类型%s 的资源。应该只有一个"
#: pkg/acsengine/transform.go:122
#, c-format
msgid "Found no resources with type %s in the template. There should have been 1"
msgstr "模板没有发现类型%s 的资源。应该有一个"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:102
#, c-format
msgid "Total count of master VMs: %d exceeded expected count: %d"
msgstr "主虚拟机总数: %d 超过期望的数目: %d"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:30
#, c-format
msgid "Upgrade to Kubernetes 1.6.2 is not supported from version: %s"
msgstr "版本%s 不支持升级到Kubernetes 1.6.2"
#: pkg/operations/kubernetesupgrade/upgradecluster.go:86
#, c-format
msgid "Upgrade to Kubernetes version: %s is not supported from version: %s"
msgstr "版本%s 不支持升级到Kubernetes版本%s"
#: pkg/acsengine/filesaver.go:24
#, c-format
msgid "error creating directory '%s': %s"
msgstr "创建目录 %s 时出错: %s"
#: pkg/acsengine/engine.go:1194
#, c-format
msgid "error executing template for file %s: %v"
msgstr "执行文件 %s %v 模板时出错"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:67
#: pkg/operations/kubernetesupgrade/v162upgrader.go:182
#: pkg/operations/kubernetesupgrade/v162upgrader.go:295
#, c-format
msgid "error generating upgrade template: %s"
msgstr "执行文件 %s 模板时出错"
#: pkg/acsengine/engine.go:1189
#, c-format
msgid "error parsing file %s: %v"
msgstr "解析文件 %s: %v 时出错"
#: pkg/api/apiloader.go:24 pkg/api/upgradeapiloader.go:20
#, c-format
msgid "error reading file %s: %s"
msgstr "读取文件 %s: %s 时出错"
#: pkg/acsengine/ssh.go:55
#, c-format
msgid "failed to create openssh public key string: %q"
msgstr "生成 openssh 公开密钥字符串出错: %q"
#: pkg/acsengine/ssh.go:49
#, c-format
msgid "failed to generate private key for ssh: %q"
msgstr "生成 ssh 私有密钥出错: %q"
#: pkg/operations/kubernetesupgrade/v162upgrader.go:289
#, c-format
msgid "failed to initialize template generator: %s"
msgstr "初始化模板生成器时出错: %s"
#: pkg/api/apiloader.go:161 pkg/api/upgradeapiloader.go:70
#, c-format
msgid "invalid version %s for conversion back from unversioned object"
msgstr "与回是非版本化的对象的转换的版本无效 %s"
#: pkg/acsengine/engine.go:322
#, c-format
msgid "orchestrator '%s' is unsupported"
msgstr "%s 配器是不受支持"
#: pkg/acsengine/engine.go:187
#, c-format
msgid "template file %s does not exist"
msgstr "模板文件 %s 不存在"
#: pkg/api/apiloader.go:98 pkg/api/upgradeapiloader.go:51
#, c-format
msgid "unrecognized APIVersion '%s'"
msgstr "无法识别的 APIVersion '%s'"
#: pkg/acsengine/engine.go:1183
#, c-format
msgid "yaml file %s does not exist"
msgstr "yaml 文件 %s 不存在"

Просмотреть файл

@ -0,0 +1,126 @@
<?xml version="1.0"?>
<LCX SchemaVersion="6.0" Name="acsengine" PsrId="1" SrcCul="en-US" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
<Item ItemType="0" ItemId="1" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error reading file %s, Error: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="2" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error while querying ARM for resources: %+v]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="3" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 2 resources with type %s in the template. There should only be 1]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="4" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found no resources with type %s in the template. There should have been 1]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="5" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Total count of master VMs: %d exceeded expected count: %d]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="6" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes 1.6.2 is not supported from version: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="7" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes version: %s is not supported from version: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="8" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error creating directory '%s': %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="9" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error executing template for file %s: %v]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="10" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error generating upgrade template: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="11" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error parsing file %s: %v]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="12" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error reading file %s: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="13" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to create openssh public key string: %q]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="14" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to generate private key for ssh: %q]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="15" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to initialize template generator: %s]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="16" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[invalid version %s for conversion back from unversioned object]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="17" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[orchestrator '%s' is unsupported]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="18" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[template file %s does not exist]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="19" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[unrecognized APIVersion '%s']]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="20" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[yaml file %s does not exist]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<OwnedComments>
<Cmt Name="LcxAdmin" />
</OwnedComments>
</LCX>

Просмотреть файл

@ -0,0 +1,187 @@
<?xml version="1.0"?>
<LCX SchemaVersion="6.0" Name="acsengine" PsrId="1" SrcCul="en-US" TgtCul="en-US" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
<Item ItemType="0" ItemId="1" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error reading file %s, Error: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Error reading file %s, Error: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="2" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Error while querying ARM for resources: %+v]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Error while querying ARM for resources: %+v]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="3" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 2 resources with type %s in the template. There should only be 1]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Found 2 resources with type %s in the template. There should only be 1]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="4" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found no resources with type %s in the template. There should have been 1]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Found no resources with type %s in the template. There should have been 1]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="5" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Total count of master VMs: %d exceeded expected count: %d]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Total count of master VMs: %d exceeded expected count: %d]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="6" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes 1.6.2 is not supported from version: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Upgrade to Kubernetes 1.6.2 is not supported from version: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="7" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Upgrade to Kubernetes version: %s is not supported from version: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[Upgrade to Kubernetes version: %s is not supported from version: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="8" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error creating directory '%s': %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error creating directory '%s': %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="9" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error executing template for file %s: %v]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error executing template for file %s: %v]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="10" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error generating upgrade template: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error generating upgrade template: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="11" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error parsing file %s: %v]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error parsing file %s: %v]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="12" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[error reading file %s: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[error reading file %s: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="13" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to create openssh public key string: %q]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[failed to create openssh public key string: %q]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="14" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to generate private key for ssh: %q]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[failed to generate private key for ssh: %q]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="15" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[failed to initialize template generator: %s]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[failed to initialize template generator: %s]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="16" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[invalid version %s for conversion back from unversioned object]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[invalid version %s for conversion back from unversioned object]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="17" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[orchestrator '%s' is unsupported]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[orchestrator '%s' is unsupported]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="18" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[template file %s does not exist]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[template file %s does not exist]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="19" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[unrecognized APIVersion '%s']]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[unrecognized APIVersion '%s']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemType="0" ItemId="20" PsrId="1" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[yaml file %s does not exist]]></Val>
<Tgt Cat="Text" Stat="Loc" Appr="PreApproved">
<Val><![CDATA[yaml file %s does not exist]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<OwnedComments>
<Cmt Name="LcxAdmin" />
</OwnedComments>
<Settings Name="@vsLocTools@\current\default.lss" Type="Lss" />
</LCX>

Просмотреть файл

@ -0,0 +1,135 @@
<?xml version="1.0"?>
<LCX SchemaVersion="6.0" Name="acsengine" PsrId="1" SrcCul="en-US" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
<Item ItemId="1">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:239" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="2">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/upgradecluster.go:71" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="3">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/transform.go:99" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="4">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/transform.go:122" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="5">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:102" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="6">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:30" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="7">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/upgradecluster.go:86" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="8">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/filesaver.go:24" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="9">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:1194" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="10">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:67" />
<Str Name="PO_Metadata1" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:182" />
<Str Name="PO_Metadata2" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:295" />
<Str Name="PO_Metadata3" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="11">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:1189" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="12">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/api/apiloader.go:24 pkg/api/upgradeapiloader.go:20" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="13">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/ssh.go:55" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="14">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/ssh.go:49" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="15">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/operations/kubernetesupgrade/v162upgrader.go:289" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="16">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/api/apiloader.go:161 pkg/api/upgradeapiloader.go:70" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="17">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:322" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="18">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:187" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="19">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/api/apiloader.go:98 pkg/api/upgradeapiloader.go:51" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Item ItemId="20">
<Props>
<Str Name="PO_Metadata0" Val="#: pkg/acsengine/engine.go:1183" />
<Str Name="PO_Metadata1" Val="#, c-format" />
</Props>
</Item>
<Props>
<Str Name="CopyrightHeader0" Val="# Chinese translations for acs-engine package." />
<Str Name="CopyrightHeader1" Val="# Copyright (C) 2017" />
<Str Name="CopyrightHeader2" Val="# This file is distributed under the same license as the acs-engine package." />
<Str Name="CopyrightHeader3" Val="# Jiangtian Li &lt;jiangtianli@hotmail.com&gt;, 2017." />
<Str Name="FromFile" Val="D:\GoWork\src\github.com\Azure\acs-engine\translations\zh_CN\LC_MESSAGES\acsengine.po" />
<Str Name="FromRepository" Val="acsengine" />
<Str Name="PO_Header" Val="Project-Id-Version: \nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2017-07-25 00:11+0000\nPO-Revision-Date: 2017-07-24 17:21-0700\nLast-Translator: Jiangtian Li &lt;jiangtianli@hotmail.com&gt;\nLanguage-Team: Chinese (simplified)\nLanguage: zh_CN\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 2.0.3\n" />
<Str Name="NPlurals" Val="2" />
</Props>
</LCX>

0
vendor/github.com/Azure/azure-sdk-for-go/arm/advisor/client.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/advisor/models.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/advisor/operations.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/advisor/recommendations.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/advisor/suppressions.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/advisor/version.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/analysisservices/client.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/analysisservices/models.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/analysisservices/servers.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/analysisservices/version.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/apiexport.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/apioperations.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/apioperationspolicy.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/apipolicy.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/apiproducts.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/apis.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/authorizationservers.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/backends.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/certificates.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/client.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/groups.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/groupusers.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/identityproviders.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/loggers.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/models.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/networkstatus.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/openidconnectproviders.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/operations.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/policysnippets.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/productapis.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/productgroups.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/productpolicy.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/products.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/productsubscriptions.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/properties.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/property.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/quotabycounterkeys.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/quotabyperiodkeys.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/regions.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/reports.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/services.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/subscriptions.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/tenantaccess.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/tenantaccessgit.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/tenantconfiguration.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/tenantconfigurationsyncstate.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/tenantpolicy.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/usergroups.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

0
vendor/github.com/Azure/azure-sdk-for-go/arm/apimanagement/useridentities.go сгенерированный поставляемый Executable file → Normal file
Просмотреть файл

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше