[add] language pack support for page
This commit is contained in:
parent
850e4dacc5
commit
6283b6e34c
10 changed files with 281 additions and 9 deletions
|
|
@ -40,4 +40,6 @@ func check(t *testing.T) {
|
||||||
filters := lang.Page.Layout["filters"].([]interface{})
|
filters := lang.Page.Layout["filters"].([]interface{})
|
||||||
begin := filters[0].(map[string]interface{})
|
begin := filters[0].(map[string]interface{})
|
||||||
assert.Equal(t, "開始時間", begin["name"])
|
assert.Equal(t, "開始時間", begin["name"])
|
||||||
|
|
||||||
|
assert.Equal(t, "請選擇開始時間", lang.Filters["開始時間"].Input.Props["placeholder"])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,19 @@ func (chart *Chart) Lang(trans func(widget string, inst string, value *string) b
|
||||||
trans(widget, inst, &chart.Page.Primary)
|
trans(widget, inst, &chart.Page.Primary)
|
||||||
transMap(widget, inst, chart.Page.Layout, trans)
|
transMap(widget, inst, chart.Page.Layout, trans)
|
||||||
chart.Output = transAny(widget, inst, chart.Output, trans)
|
chart.Output = transAny(widget, inst, chart.Output, trans)
|
||||||
|
|
||||||
|
// Filters
|
||||||
|
for name, filter := range chart.Filters {
|
||||||
|
new := name
|
||||||
|
trans(widget, inst, &new)
|
||||||
|
trans(widget, inst, &filter.Label)
|
||||||
|
delete(chart.Filters, name)
|
||||||
|
|
||||||
|
// Props
|
||||||
|
transMap(widget, inst, filter.Input.Props, trans)
|
||||||
|
chart.Filters[new] = filter
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func transAny(widget string, inst string, input interface{}, trans func(widget string, inst string, value *string) bool) interface{} {
|
func transAny(widget string, inst string, input interface{}, trans func(widget string, inst string, value *string) bool) interface{} {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ import (
|
||||||
func init() {
|
func init() {
|
||||||
lang.RegisterWidget("tables", "table")
|
lang.RegisterWidget("tables", "table")
|
||||||
lang.RegisterWidget("charts", "chart")
|
lang.RegisterWidget("charts", "chart")
|
||||||
lang.RegisterWidget("kanban", "kanban")
|
lang.RegisterWidget("kanban", "page")
|
||||||
|
lang.RegisterWidget("screen", "page")
|
||||||
|
lang.RegisterWidget("pages", "page")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load language packs
|
// Load language packs
|
||||||
|
|
|
||||||
125
page/lang.go
Normal file
125
page/lang.go
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
package page
|
||||||
|
|
||||||
|
// Lang for applying a language pack
|
||||||
|
func (page *Page) Lang(trans func(widget string, inst string, value *string) bool) {
|
||||||
|
inst := page.Flow.Name
|
||||||
|
widget := "page"
|
||||||
|
|
||||||
|
trans(widget, inst, &page.Name)
|
||||||
|
trans(widget, inst, &page.Label)
|
||||||
|
trans(widget, inst, &page.Description)
|
||||||
|
trans(widget, inst, &page.Page.Primary)
|
||||||
|
transMap(widget, inst, page.Page.Layout, trans)
|
||||||
|
page.Output = transAny(widget, inst, page.Output, trans)
|
||||||
|
|
||||||
|
// Filters
|
||||||
|
for name, filter := range page.Filters {
|
||||||
|
new := name
|
||||||
|
trans(widget, inst, &new)
|
||||||
|
trans(widget, inst, &filter.Label)
|
||||||
|
delete(page.Filters, name)
|
||||||
|
|
||||||
|
// Props
|
||||||
|
transMap(widget, inst, filter.Input.Props, trans)
|
||||||
|
page.Filters[new] = filter
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func transAny(widget string, inst string, input interface{}, trans func(widget string, inst string, value *string) bool) interface{} {
|
||||||
|
switch input.(type) {
|
||||||
|
case []interface{}:
|
||||||
|
values := input.([]interface{})
|
||||||
|
transArr(widget, inst, values, trans)
|
||||||
|
input = values
|
||||||
|
break
|
||||||
|
|
||||||
|
case map[string]interface{}:
|
||||||
|
values := input.(map[string]interface{})
|
||||||
|
for name, value := range values {
|
||||||
|
new := name
|
||||||
|
newValue := value
|
||||||
|
|
||||||
|
switch value.(type) {
|
||||||
|
case string:
|
||||||
|
val := value.(string)
|
||||||
|
trans(widget, inst, &val)
|
||||||
|
newValue = val
|
||||||
|
break
|
||||||
|
|
||||||
|
case []interface{}:
|
||||||
|
vals := value.([]interface{})
|
||||||
|
transArr(widget, inst, vals, trans)
|
||||||
|
newValue = vals
|
||||||
|
break
|
||||||
|
|
||||||
|
case map[string]interface{}:
|
||||||
|
vals := value.(map[string]interface{})
|
||||||
|
transMap(widget, inst, vals, trans)
|
||||||
|
newValue = vals
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
trans(widget, inst, &new)
|
||||||
|
delete(values, name)
|
||||||
|
values[new] = newValue
|
||||||
|
}
|
||||||
|
input = values
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return input
|
||||||
|
}
|
||||||
|
|
||||||
|
func transMap(widget string, inst string, values map[string]interface{}, trans func(widget string, inst string, value *string) bool) {
|
||||||
|
for key, value := range values {
|
||||||
|
|
||||||
|
switch value.(type) {
|
||||||
|
|
||||||
|
case string:
|
||||||
|
v := value.(string)
|
||||||
|
trans(widget, inst, &v)
|
||||||
|
values[key] = v
|
||||||
|
break
|
||||||
|
|
||||||
|
case []interface{}:
|
||||||
|
v := value.([]interface{})
|
||||||
|
transArr(widget, inst, v, trans)
|
||||||
|
values[key] = v
|
||||||
|
break
|
||||||
|
|
||||||
|
case map[string]interface{}:
|
||||||
|
v := value.(map[string]interface{})
|
||||||
|
transMap(widget, inst, v, trans)
|
||||||
|
values[key] = v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func transArr(widget string, inst string, values []interface{}, trans func(widget string, inst string, value *string) bool) {
|
||||||
|
for key, value := range values {
|
||||||
|
switch value.(type) {
|
||||||
|
|
||||||
|
case string:
|
||||||
|
v := value.(string)
|
||||||
|
trans(widget, inst, &v)
|
||||||
|
values[key] = v
|
||||||
|
break
|
||||||
|
|
||||||
|
case []interface{}:
|
||||||
|
v := value.([]interface{})
|
||||||
|
transArr(widget, inst, v, trans)
|
||||||
|
values[key] = v
|
||||||
|
break
|
||||||
|
|
||||||
|
case map[string]interface{}:
|
||||||
|
v := value.(map[string]interface{})
|
||||||
|
transMap(widget, inst, v, trans)
|
||||||
|
values[key] = v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
13
page/page.go
13
page/page.go
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/yaoapp/gou"
|
"github.com/yaoapp/gou"
|
||||||
|
"github.com/yaoapp/gou/lang"
|
||||||
"github.com/yaoapp/kun/exception"
|
"github.com/yaoapp/kun/exception"
|
||||||
"github.com/yaoapp/kun/log"
|
"github.com/yaoapp/kun/log"
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
|
|
@ -24,15 +25,15 @@ func Load(cfg config.Config) error {
|
||||||
|
|
||||||
var errs error = nil
|
var errs error = nil
|
||||||
if err := LoadFrom(path.Join(cfg.Root, "/kanban"), ""); err != nil {
|
if err := LoadFrom(path.Join(cfg.Root, "/kanban"), ""); err != nil {
|
||||||
log.Trace("load kanban error: %s ", err.Error())
|
// log.Trace("load kanban error: %s ", err.Error())
|
||||||
errs = err
|
errs = err
|
||||||
}
|
}
|
||||||
if err := LoadFrom(path.Join(cfg.Root, "/screen"), ""); err != nil {
|
if err := LoadFrom(path.Join(cfg.Root, "/screen"), ""); err != nil {
|
||||||
log.Trace("load screen error: %s", err.Error())
|
// log.Trace("load screen error: %s", err.Error())
|
||||||
errs = err
|
errs = err
|
||||||
}
|
}
|
||||||
if err := LoadFrom(path.Join(cfg.Root, "/pages"), ""); err != nil {
|
if err := LoadFrom(path.Join(cfg.Root, "/pages"), ""); err != nil {
|
||||||
log.Trace("load screen error: %s", err.Error())
|
// log.Trace("load screen error: %s", err.Error())
|
||||||
errs = err
|
errs = err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,6 +94,12 @@ func LoadPage(source []byte, name string) (*Page, error) {
|
||||||
page.Prepare()
|
page.Prepare()
|
||||||
page.SetupAPIs()
|
page.SetupAPIs()
|
||||||
Pages[name] = page
|
Pages[name] = page
|
||||||
|
|
||||||
|
// Apply a language pack
|
||||||
|
if lang.Default != nil {
|
||||||
|
lang.Default.Apply(Pages[name])
|
||||||
|
}
|
||||||
|
|
||||||
return page, nil
|
return page, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,22 @@
|
||||||
package page
|
package page
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
|
"github.com/yaoapp/yao/lang"
|
||||||
"github.com/yaoapp/yao/model"
|
"github.com/yaoapp/yao/model"
|
||||||
"github.com/yaoapp/yao/query"
|
"github.com/yaoapp/yao/query"
|
||||||
"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)
|
||||||
model.Load(config.Conf)
|
model.Load(config.Conf)
|
||||||
query.Load(config.Conf)
|
query.Load(config.Conf)
|
||||||
|
|
@ -25,5 +31,15 @@ func check(t *testing.T) {
|
||||||
for key := range Pages {
|
for key := range Pages {
|
||||||
keys = append(keys, key)
|
keys = append(keys, key)
|
||||||
}
|
}
|
||||||
assert.Equal(t, 1, len(keys))
|
assert.Equal(t, 2, len(keys))
|
||||||
|
|
||||||
|
lang := Pages["lang"]
|
||||||
|
output := lang.Output.(map[string]interface{})
|
||||||
|
assert.Equal(t, "{{$in}}", output["參數"])
|
||||||
|
|
||||||
|
filters := lang.Page.Layout["filters"].([]interface{})
|
||||||
|
begin := filters[0].(map[string]interface{})
|
||||||
|
assert.Equal(t, "開始時間", begin["name"])
|
||||||
|
|
||||||
|
assert.Equal(t, "請選擇開始時間", lang.Filters["開始時間"].Input.Props["placeholder"])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/yaoapp/gou"
|
"github.com/yaoapp/gou"
|
||||||
"github.com/yaoapp/kun/any"
|
"github.com/yaoapp/kun/any"
|
||||||
"github.com/yaoapp/kun/utils"
|
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
_ "github.com/yaoapp/yao/helper"
|
_ "github.com/yaoapp/yao/helper"
|
||||||
"github.com/yaoapp/yao/model"
|
"github.com/yaoapp/yao/model"
|
||||||
|
|
@ -68,8 +67,6 @@ func TestProcessData(t *testing.T) {
|
||||||
}
|
}
|
||||||
process := gou.NewProcess("xiang.page.Data", args...)
|
process := gou.NewProcess("xiang.page.Data", args...)
|
||||||
response := ProcessData(process)
|
response := ProcessData(process)
|
||||||
utils.Dump(response)
|
|
||||||
|
|
||||||
assert.NotNil(t, response)
|
assert.NotNil(t, response)
|
||||||
|
|
||||||
res := any.Of(response).Map().Dot()
|
res := any.Of(response).Map().Dot()
|
||||||
|
|
|
||||||
10
tests/langs/zh-hk/pages/lang.yml
Normal file
10
tests/langs/zh-hk/pages/lang.yml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
Start: 開始時間
|
||||||
|
End: 結束時間
|
||||||
|
City: 城市
|
||||||
|
Please select a start time: 請選擇開始時間
|
||||||
|
Please select an end time: 請選擇結束時間
|
||||||
|
Industry: 行業
|
||||||
|
Billing: 計費
|
||||||
|
Merge Reulst: 合併結果
|
||||||
|
Parameter: 參數
|
||||||
|
Merge: 合併
|
||||||
100
tests/pages/lang.page.json
Normal file
100
tests/pages/lang.page.json
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
{
|
||||||
|
"label": "::Demo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "::Demo",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "行业",
|
||||||
|
"engine": "xiang",
|
||||||
|
"query": {
|
||||||
|
"select": [
|
||||||
|
"city",
|
||||||
|
":COUNT(id) as 数量",
|
||||||
|
"industries[*](string 50) as industry"
|
||||||
|
],
|
||||||
|
"from": "$service",
|
||||||
|
"wheres": [
|
||||||
|
{ "field": "created_at", ">": "?:$from.0" },
|
||||||
|
{ "field": "created_at", "<": "?:$to" }
|
||||||
|
],
|
||||||
|
"orders": "数量 desc",
|
||||||
|
"limit": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "计费",
|
||||||
|
"engine": "xiang",
|
||||||
|
"query": {
|
||||||
|
"select": ["city", ":COUNT(id) as 数量", "price_options[*] as option"],
|
||||||
|
"from": "$service",
|
||||||
|
"wheres": [
|
||||||
|
{ "field": "created_at", ">": "?:$from.0" },
|
||||||
|
{ "field": "created_at", "<": "?:$to" }
|
||||||
|
],
|
||||||
|
"orders": "数量 desc",
|
||||||
|
"limit": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "合并结果",
|
||||||
|
"process": "xiang.helper.ArrayPluck",
|
||||||
|
"args": [
|
||||||
|
["城市", "行业", "计费"],
|
||||||
|
{
|
||||||
|
"行业": { "key": "city", "value": "数量", "items": "{{$res.行业}}" },
|
||||||
|
"计费": { "key": "city", "value": "数量", "items": "{{$res.计费}}" }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"output": {
|
||||||
|
"::Merge": "{{$res.合并结果}}",
|
||||||
|
"::Billing": "{{$res.计费}}",
|
||||||
|
"::Industry": "{{$res.行业}}",
|
||||||
|
"::Parameter": "{{$in}}"
|
||||||
|
},
|
||||||
|
"apis": {
|
||||||
|
"data": {
|
||||||
|
"disable": false,
|
||||||
|
"guard": "-",
|
||||||
|
"default": [{ "from": "1980-01-02", "to": "2050-12-31" }]
|
||||||
|
},
|
||||||
|
"setting": { "disable": false, "guard": "-" }
|
||||||
|
},
|
||||||
|
"filters": {
|
||||||
|
"::Start": {
|
||||||
|
"label": "::Start",
|
||||||
|
"bind": "from",
|
||||||
|
"input": {
|
||||||
|
"type": "date",
|
||||||
|
"props": {
|
||||||
|
"placeholder": "::Please select a start time"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::End": {
|
||||||
|
"label": "::End",
|
||||||
|
"bind": "to",
|
||||||
|
"input": {
|
||||||
|
"type": "date",
|
||||||
|
"props": {
|
||||||
|
"placeholder": "::Please select an end time"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"primary": "::City",
|
||||||
|
"layout": {
|
||||||
|
"filters": [
|
||||||
|
{ "name": "::Start", "width": 6 },
|
||||||
|
{ "name": "::End", "width": 6 }
|
||||||
|
],
|
||||||
|
"charts": [
|
||||||
|
{ "type": "line", "props": {} },
|
||||||
|
{ "type": "bar", "props": {} }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"actions": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
"name": "行业",
|
"name": "行业",
|
||||||
"engine": "xiang",
|
"engine": "xiang",
|
||||||
"query": {
|
"query": {
|
||||||
"debug": true,
|
"debug": false,
|
||||||
"select": [
|
"select": [
|
||||||
"city",
|
"city",
|
||||||
":COUNT(id) as 数量",
|
":COUNT(id) as 数量",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue