我正在尝试为我的 web 应用程序构建翻译功能。我的应用程序中有多个包。每个包(目录)都包含一个翻译文件夹和里面的 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 库(https://godoc.org/gopkg.in/yaml.v2),则可以创建一个 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"`
}
这将设置
MyAbcField
的值至"my data"
将 Unmarshal 与 ExampleStruct
一起使用时和以下 YAML:abc: "my data"
这允许您设计一个匹配的 Golang 结构,但是您决定构建您的 YAML。
这是我在 Go Playground 中的上述代码:https://play.golang.org/p/Q9FvNsw-BOx
现在,如果您无法修复 YAML 文件的结构,您也可以解析为嵌套映射。您可以通过传递
interface{}
类型的变量来完成此操作。 (空接口(interface))到 Unmarshal 而不是结构。但是,这需要大量样板文件,因为您需要执行类型断言才能访问您的数据。因此,除非您绝对无法避免,否则我建议使用固定结构。这是一个示例,我解析您发布的 YAML,然后获取
msgLogin
field :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"])
这是我的结构示例的 Go Playground,改为使用解析为嵌套 map :https://play.golang.org/p/ERBjClSazkz
关于go - Yaml 文件在 Golang 中进行结构解析(翻译),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61514438/