Golang中Yaml文件到结构解析(翻译)

Golang中Yaml文件到结构解析(翻译),go,yaml,Go,Yaml,我正在尝试为我的webapp构建一个翻译功能。我的应用程序中有多个软件包。每个包(目录)中都包含一个翻译文件夹和yaml文件。但我在解析和将其分配给消息时遇到问题 en.yaml msgLogin : "You've login successfully" msgProducts: 0: "You don't have any product." 1: "You have %d product." 2: "You have %d products." errLogin: "Wro

我正在尝试为我的webapp构建一个翻译功能。我的应用程序中有多个软件包。每个包(目录)中都包含一个翻译文件夹和yaml文件。但我在解析和将其分配给消息时遇到问题

en.yaml

msgLogin : "You've login successfully"

msgProducts:
  0: "You don't have any product."
  1: "You have %d product."
  2: "You have %d products."

errLogin: "Wrong password or username"
我的代码:

type TranslationEntry struct {
    Key struct {
        Value interface{}
    }
}

func parseTranslations(dir string) {
    files, _ := ioutil.ReadDir(dir)

    for _, f := range files {
        yamlFile, _ := ioutil.ReadFile(dir + "/" + f.Name())
        var data translation
        if err := yaml.Unmarshal(yamlFile, &data); err != nil {
            return nil, err
        }

        lang := strings.Split(f.Name(), ".")[0]
        switch msg := data.Key.Value.(type) {
        case string:
            message.SetString(language.Make(lang), cast.ToString(data.Key), cast.ToString(data.Key.Value))
        case map[int]string:
            message.Set(language.Make(lang), cast.ToString(data.Key),
                plural.Selectf(1, "%d",
                    "=0", cast.ToString(data.Key.Value["0"]),
                    "=1", cast.ToString(data.Key.Value["1"]),
                    "=2", cast.ToString(data.Key.Value["2"]),
                ))
        }

        translations[lang] = &dictionary{Data: data}
    }
}

我完全不知道如何设计我的结构或解析yaml文件


如果您使用的是YAML库,我认为您使用的是(),要制作一个Golang结构,可以使用Unmarshal从您文章中的YAML文件映射,请执行以下操作:

type TranslationEntry struct {
    MsgLogin string `yaml:"msgLogin"`
    MsgProducts map[int]string `yaml:"msgProducts"`
    ErrLogin string `yaml:"errLogin"`
}
在字段声明之后,``中的内容称为标记。它们是在某些数据类型和Golang结构之间映射时通常指定字段名的方式(在我的例子中,通常我将结构映射到JSON,但我也完成了YAML)。如果您使用的是我上面提到的同一个YAML解析器,那么它就是这样工作的

基本上,双引号内的文本是结构字段将映射到的YAML键。在上述代码中,YAML键名称和结构字段名称之间的唯一区别是大写,但下面是一个使用完全不同名称的示例:

type ExampleStruct struct {
    MyAbcField string `yaml:"abc"`
}

这将在对
ExampleStruct
和以下YAML使用解组时,将
MyAbcField
的值设置为
“我的数据”

abc: "my data"
这允许您设计一个Golang结构,它与您决定构建YAML的方式相匹配

以下是我在围棋场的上述代码:

现在,如果您无法修复YAML文件的结构,还可以将其解析为嵌套映射。您可以通过将
接口{}
类型的变量(空接口)传递给Unmarshal而不是结构来实现这一点。然而,这需要大量的样板文件,因为需要进行类型断言才能访问数据。因此,我建议使用固定结构,除非你绝对无法避免

下面是一个示例,我解析您发布的YAML,然后获得
msgLogin
字段:

var data interface{}
if err := yaml.Unmarshal([]byte(yamlFile), &data); err != nil {
    // handle error
}

// a type assertion that data is a map is needed in order to get keys or iterate
topLevel, ok := data.(map[interface{}]interface{}) 
if !ok {
    // handle error
}

fmt.Println(topLevel["msgLogin"])

下面是我的struct示例的示例,改为使用解析到嵌套映射:

谢谢您的回答。但有一个问题。您已经在结构中使用了MsgLogin MsgProducts等。这些是关键,在每个文件中都会有所不同。我怎么能这么做?啊,我的错。当你在帖子中说“翻译”时,我以为你指的是本地化。对于本地化,您将在每个文件中使用相同的密钥(我必须经常在英语和日语之间进行本地化)。在您的例子中,听起来您需要解析成嵌套的映射。给我一点时间检查一下。我在响应的底部添加了关于如何解析嵌套映射的信息。如果可以的话,我建议您尝试使用固定格式的结构(以避免样板文件),但是嵌套映射应该可以满足您的要求。