[add] language pack support for model
This commit is contained in:
parent
8d88682967
commit
2349d17d99
15 changed files with 143 additions and 125 deletions
130
app/app.go
130
app/app.go
|
|
@ -1,35 +1,32 @@
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
l "github.com/yaoapp/gou/lang"
|
||||||
"github.com/yaoapp/kun/exception"
|
"github.com/yaoapp/kun/exception"
|
||||||
"github.com/yaoapp/kun/log"
|
|
||||||
"github.com/yaoapp/kun/maps"
|
"github.com/yaoapp/kun/maps"
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
"github.com/yaoapp/yao/data"
|
"github.com/yaoapp/yao/data"
|
||||||
|
"github.com/yaoapp/yao/lang"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
"github.com/yaoapp/yao/xfs"
|
"github.com/yaoapp/yao/xfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// langs 语言包
|
// Load Application
|
||||||
var langs = map[string]map[string]string{}
|
|
||||||
|
|
||||||
// Load 加载应用信息
|
|
||||||
func Load(cfg config.Config) {
|
func Load(cfg config.Config) {
|
||||||
Init(cfg)
|
|
||||||
LoadInfo(cfg.Root)
|
|
||||||
LoadLang(cfg)
|
|
||||||
|
|
||||||
lang := strings.ToLower(share.App.Lang)
|
// Load language packs
|
||||||
|
lang.Load(cfg)
|
||||||
|
|
||||||
|
// Set language pack
|
||||||
share.App.L = map[string]string{}
|
share.App.L = map[string]string{}
|
||||||
if l, has := langs[lang]; has {
|
if l.Default != nil {
|
||||||
share.App.L = l
|
share.App.L = l.Default.Global
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load Info
|
||||||
|
LoadInfo(cfg.Root)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// L 语言包
|
// L 语言包
|
||||||
|
|
@ -40,49 +37,6 @@ func L(word string) string {
|
||||||
return word
|
return word
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init 应用初始化
|
|
||||||
func Init(cfg config.Config) {
|
|
||||||
|
|
||||||
// // UI文件目录
|
|
||||||
// if _, err := os.Stat(cfg.RootUI); os.IsNotExist(err) {
|
|
||||||
// err := os.MkdirAll(cfg.RootUI, os.ModePerm)
|
|
||||||
// if err != nil {
|
|
||||||
// xlog.Printf("创建目录失败(%s) %s", cfg.RootUI, err)
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// content, err := data.Asset("xiang/data/index.html")
|
|
||||||
// if err != nil {
|
|
||||||
// xlog.Printf("读取文件失败(%s) %s", cfg.RootUI, err)
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// err = ioutil.WriteFile(filepath.Join(cfg.RootUI, "/index.html"), content, os.ModePerm)
|
|
||||||
// if err != nil {
|
|
||||||
// xlog.Printf("复制默认文件失败(%s) %s", cfg.RootUI, err)
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 数据库目录
|
|
||||||
// if _, err := os.Stat(cfg.RootDB); os.IsNotExist(err) {
|
|
||||||
// err := os.MkdirAll(cfg.RootDB, os.ModePerm)
|
|
||||||
// if err != nil {
|
|
||||||
// xlog.Printf("创建目录失败(%s) %s", cfg.RootDB, err)
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 文件数据目录
|
|
||||||
// if _, err := os.Stat(cfg.RootData); os.IsNotExist(err) {
|
|
||||||
// err := os.MkdirAll(cfg.RootData, os.ModePerm)
|
|
||||||
// if err != nil {
|
|
||||||
// xlog.Printf("创建目录失败(%s) %s", cfg.RootData, err)
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadInfo 应用信息
|
// LoadInfo 应用信息
|
||||||
func LoadInfo(root string) {
|
func LoadInfo(root string) {
|
||||||
info := defaultInfo()
|
info := defaultInfo()
|
||||||
|
|
@ -106,71 +60,15 @@ func LoadInfo(root string) {
|
||||||
info.Icons.Set("png", xfs.Encode(fs.MustReadFile("/yao/icons/icon.png")))
|
info.Icons.Set("png", xfs.Encode(fs.MustReadFile("/yao/icons/icon.png")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.L = share.App.L
|
||||||
share.App = info
|
share.App = info
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadLang 加载语言包
|
|
||||||
func LoadLang(cfg config.Config) error {
|
|
||||||
|
|
||||||
var defaults = []share.Script{}
|
|
||||||
if os.Getenv("YAO_DEV") != "" {
|
|
||||||
defaults = share.GetFilesFS(filepath.Join(os.Getenv("YAO_DEV"), "yao"), ".json")
|
|
||||||
} else {
|
|
||||||
defaults = share.GetFilesBin("yao", ".json")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, lang := range defaults {
|
|
||||||
if lang.Type != "langs" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
content := lang.Content
|
|
||||||
name := strings.ToLower(lang.Name) // 这个读取函数需要优化
|
|
||||||
lang := map[string]string{}
|
|
||||||
err := jsoniter.Unmarshal(content, &lang)
|
|
||||||
if err != nil {
|
|
||||||
log.With(log.F{"name": name}).Error(err.Error())
|
|
||||||
}
|
|
||||||
langs[name] = lang
|
|
||||||
}
|
|
||||||
|
|
||||||
if share.BUILDIN {
|
|
||||||
return LoadLangBuildIn("langs")
|
|
||||||
}
|
|
||||||
return LoadLangFrom(filepath.Join(cfg.Root, "langs"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadLangBuildIn 从制品中读取
|
// LoadLangBuildIn 从制品中读取
|
||||||
func LoadLangBuildIn(dir string) error {
|
func LoadLangBuildIn(dir string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadLangFrom 从特定目录加载
|
|
||||||
func LoadLangFrom(dir string) error {
|
|
||||||
|
|
||||||
if share.DirNotExists(dir) {
|
|
||||||
return fmt.Errorf("%s does not exists", dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := share.Walk(dir, ".json", func(root, filename string) {
|
|
||||||
name := strings.ToLower(share.SpecName(root, filename))
|
|
||||||
content := share.ReadFile(filename)
|
|
||||||
lang := map[string]string{}
|
|
||||||
err := jsoniter.Unmarshal(content, &lang)
|
|
||||||
if err != nil {
|
|
||||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
|
||||||
}
|
|
||||||
if _, has := langs[name]; !has {
|
|
||||||
langs[name] = map[string]string{}
|
|
||||||
}
|
|
||||||
for src, dst := range lang {
|
|
||||||
langs[name][src] = dst
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaultInfo 读取默认应用信息
|
// defaultInfo 读取默认应用信息
|
||||||
func defaultInfo() share.AppInfo {
|
func defaultInfo() share.AppInfo {
|
||||||
info := share.AppInfo{
|
info := share.AppInfo{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
@ -9,7 +10,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoad(t *testing.T) {
|
func TestLoad(t *testing.T) {
|
||||||
|
os.Setenv("YAO_LANG", "zh-cn")
|
||||||
Load(config.Conf)
|
Load(config.Conf)
|
||||||
assert.Equal(t, "Yao", share.App.L["Yao"])
|
assert.Equal(t, "YAO", share.App.L["Yao"])
|
||||||
assert.Equal(t, "Xiang", share.App.L["象传"])
|
assert.Equal(t, "象传", share.App.L["Xiang"])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
36
lang/lang.go
Normal file
36
lang/lang.go
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package lang
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/yaoapp/gou/lang"
|
||||||
|
"github.com/yaoapp/kun/log"
|
||||||
|
"github.com/yaoapp/yao/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
lang.RegisterWidget("tables", "table")
|
||||||
|
lang.RegisterWidget("charts", "chart")
|
||||||
|
lang.RegisterWidget("kanban", "kanban")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load language packs
|
||||||
|
func Load(cfg config.Config) error {
|
||||||
|
root := filepath.Join(cfg.Root, "langs")
|
||||||
|
err := lang.Load(root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := os.Getenv("YAO_LANG")
|
||||||
|
if name != "" {
|
||||||
|
if _, has := lang.Dicts[name]; !has {
|
||||||
|
log.Error("The language pack %s does not found", name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
lang.Pick(name).AsDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
16
lang/lang_test.go
Normal file
16
lang/lang_test.go
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
package lang
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/yaoapp/gou/lang"
|
||||||
|
"github.com/yaoapp/yao/config"
|
||||||
|
"github.com/yaoapp/yao/share"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoad(t *testing.T) {
|
||||||
|
share.DBConnect(config.Conf.DB)
|
||||||
|
Load(config.Conf)
|
||||||
|
assert.Len(t, lang.Dicts, 2)
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/yaoapp/gou"
|
"github.com/yaoapp/gou"
|
||||||
|
"github.com/yaoapp/gou/lang"
|
||||||
"github.com/yaoapp/kun/log"
|
"github.com/yaoapp/kun/log"
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
|
|
@ -31,7 +32,14 @@ func LoadFrom(dir string, prefix string) error {
|
||||||
_, err := gou.LoadModelReturn(string(content), name)
|
_, err := gou.LoadModelReturn(string(content), name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
log.With(log.F{"root": root, "file": filename}).Error(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply the language pack
|
||||||
|
if lang.Default != nil {
|
||||||
|
lang.Default.Apply(gou.Models[name])
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,23 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/yaoapp/gou"
|
"github.com/yaoapp/gou"
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
|
"github.com/yaoapp/yao/lang"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoad(t *testing.T) {
|
func TestLoad(t *testing.T) {
|
||||||
|
|
||||||
|
os.Setenv("YAO_LANG", "zh-hk")
|
||||||
|
lang.Load(config.Conf)
|
||||||
share.DBConnect(config.Conf.DB)
|
share.DBConnect(config.Conf.DB)
|
||||||
|
|
||||||
gou.Models = make(map[string]*gou.Model)
|
gou.Models = make(map[string]*gou.Model)
|
||||||
Load(config.Conf)
|
Load(config.Conf)
|
||||||
LoadFrom("not a path", "404.")
|
LoadFrom("not a path", "404.")
|
||||||
|
|
@ -23,5 +29,9 @@ func check(t *testing.T) {
|
||||||
for key := range gou.Models {
|
for key := range gou.Models {
|
||||||
keys = append(keys, key)
|
keys = append(keys, key)
|
||||||
}
|
}
|
||||||
assert.Equal(t, 10, len(keys))
|
assert.Equal(t, 11, len(keys))
|
||||||
|
|
||||||
|
demo := gou.Select("demo")
|
||||||
|
assert.Equal(t, demo.MetaData.Name, "演示")
|
||||||
|
assert.Equal(t, demo.Columns["action"].Label, "動作")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,7 @@ type Page struct {
|
||||||
// AppInfo 应用信息
|
// AppInfo 应用信息
|
||||||
type AppInfo struct {
|
type AppInfo struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Lang string `json:"lang,omitempty"`
|
L map[string]string `json:"-"`
|
||||||
L map[string]string `json:"-"` // 应用的语言包
|
|
||||||
Short string `json:"short,omitempty"`
|
Short string `json:"short,omitempty"`
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"Yao": "Yao",
|
|
||||||
"象传应用引擎": "Yao App Engine Over load"
|
|
||||||
}
|
|
||||||
1
tests/langs/zh-cn/flows/hello.flow.yml
Normal file
1
tests/langs/zh-cn/flows/hello.flow.yml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Latest: 最新信息
|
||||||
7
tests/langs/zh-cn/global.yml
Normal file
7
tests/langs/zh-cn/global.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
Demo: 演示
|
||||||
|
Phone: 电话号码
|
||||||
|
ZipCode: 邮政编码
|
||||||
|
Uptime: 更新时间
|
||||||
|
Action: 动作
|
||||||
|
Yao: YAO
|
||||||
|
Xiang: 象传
|
||||||
1
tests/langs/zh-cn/models/demo.mod.yml
Normal file
1
tests/langs/zh-cn/models/demo.mod.yml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
SN: 编码
|
||||||
1
tests/langs/zh-hk/flows/hello.flow.yml
Normal file
1
tests/langs/zh-hk/flows/hello.flow.yml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Latest: 最新信息
|
||||||
7
tests/langs/zh-hk/global.yml
Normal file
7
tests/langs/zh-hk/global.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
Demo: 演示
|
||||||
|
Phone: 電話號碼
|
||||||
|
ZipCode: 郵政編碼
|
||||||
|
Uptime: 更新時間
|
||||||
|
Action: 動作
|
||||||
|
Yao: YAO
|
||||||
|
Xiang: 像傳
|
||||||
1
tests/langs/zh-hk/models/demo.mod.yml
Normal file
1
tests/langs/zh-hk/models/demo.mod.yml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
SN: 編碼
|
||||||
35
tests/models/demo.mod.json
Normal file
35
tests/models/demo.mod.json
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"name": "::Demo",
|
||||||
|
"connector": "trace",
|
||||||
|
"table": { "name": "user_trace", "comment": "::Demo" },
|
||||||
|
"columns": [
|
||||||
|
{ "label": "ID", "name": "id", "type": "ID" },
|
||||||
|
{
|
||||||
|
"label": "::SN",
|
||||||
|
"name": "user_sn",
|
||||||
|
"type": "string",
|
||||||
|
"length": 42,
|
||||||
|
"index": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "::Uptime",
|
||||||
|
"name": "uptime",
|
||||||
|
"type": "datetime",
|
||||||
|
"index": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "::Action",
|
||||||
|
"name": "action",
|
||||||
|
"type": "enum",
|
||||||
|
"option": ["进入", "离开"],
|
||||||
|
"index": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"name": "user_sn_action_unique",
|
||||||
|
"type": "unique",
|
||||||
|
"columns": ["user_sn", "action"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue