本文的原文连接是:
https://blog.csdn.net/freewebsys/article/details/80765024
博主地址是:http://blog.csdn.net/freewebsys
前言
https://getqor.com/cn
QOR经过全新架构,以加速开发与部署内容管理系统(CMS)、电子商务系统和业务应用程序。QOR由这类系统中抽象出的通用功能模块构成,其中包含灵活可配置的后台、内容发布系统、媒体库等等。
文档:
https://doc.getqor.com/
代码:
https://github.com/golangpkg/qor-cms-demos
全部qor文章:
https://blog.csdn.net/freewebsys/article/category/7742598
1,i18n
qor 在设计的时候是支持 国际化的。
使用的i18n 开发的,所以只要汉化翻译下就行。
https://github.com/qor/i18n
在yaml 中进行配置。
en-US:
qor_admin:
actions:
advanced_filter: " 高级过滤"
然后页面中使用 t 标签:
{{t "qor_admin.filter.advanced_filter" "Advanced Filter"}}
2,main代码
代码在:
https://github.com/golangpkg/qor-cms-demos/tree/master/demo06-i18n
package main
import (
"fmt"
"net/http"
"github.com/qor/admin"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/qor/i18n"
"github.com/qor/i18n/backends/yaml"
"path/filepath"
//"github.com/qor/l10n"
"github.com/qor/l10n"
"os"
)
// 用户
type User struct {
gorm.Model
Name string
}
func main() {
// 注册数据库,可以是sqlite3 也可以是 mysql 换下驱动就可以了。
DB, _ := gorm.Open("sqlite3", "demo.db")
DB.AutoMigrate(&User{}, ) //自动创建表。
i18nPath := os.Getenv("GOPATH") + "/src/github.com/golangpkg/qor-cms-demos/demo06-i18n"
println("i18nPath: ", i18nPath)
I18n := i18n.New(
//database.New(DB), // load translations from the database
yaml.New(filepath.Join(i18nPath, "config/locales")), // load translations from the YAML files in directory `config/locales`
)
I18n.SaveTranslation(&i18n.Translation{Key: "qor_i18n.form.saved", Locale: "en-US", Value: "保存"})
l10n.Global = "zh-CN"
I18n.T("en-US", "demo.greeting") // Not exist at first
I18n.T("en-US", "demo.hello") // Exists in the yml file
fmt.Println(I18n)
// 初始化admin 还有其他的,比如API
Admin := admin.New(&admin.AdminConfig{DB: DB, I18n: I18n})
// 创建admin后台对象资源。
Admin.AddResource(&User{})
Admin.AddResource(I18n)
// 启动服务
mux := http.NewServeMux()
Admin.MountTo("/admin", mux)
fmt.Println("Listening on: 9000")
http.ListenAndServe(":9000", mux)
}
yaml可以生效得加上 :
i18nPath := os.Getenv("GOPATH") + "/src/github.com/golangpkg/qor-cms-demos/demo06-i18n"
println("i18nPath: ", i18nPath)
I18n := i18n.New(
//database.New(DB), // load translations from the database
yaml.New(filepath.Join(i18nPath, "config/locales")), // load translations from the YAML files in directory `config/locales`
)
....
//在admin 配置中再指名i18n。
Admin := admin.New(&admin.AdminConfig{DB: DB, I18n: I18n})
其中yaml 中的中文:
demo06-i18n/config/locales/qor-admin.en-US.yml
en-US:
qor_admin:
actions:
advanced_filter: " 高级过滤"
bulk_edit: " 块编辑 "
exit_bulk_edit: " 退出块编辑 "
please_select_an_item: " 请选择一个 "
search_bar_search: " 查询 "
filter:
advanced_filter: " 高级过滤"
apply: " 应用 "
checkbox:
false: " 假 "
is_blank: " 是否空 "
is_present: " 是否在当前 "
true: " 真 "
number:
eq: " 等于 "
gt: " 大于 "
lt: " 小于 "
save_this_filter: " 保存这个过滤 "
saved_filter: " 保存过滤 "
strings:
conts: " 包含 "
end_with: " 结束于 "
eq: " 等于 "
start_with: " 开始于 "
form:
add: " 增加 "
add_items: " 增加项 "
are_you_sure: " 是否确定? "
cancel: " 取消 "
cancel_edit: " 取消编辑 "
confirm:
button:
cancel: " 取消 "
ok: " 确定 "
crop_image: " 拷贝图片 "
ok: " 确定 "
save_changes: " 更新 "
select_many_hint_button: " 完成 "
submit: " 提交 "
layout:
header:
actions: " 操作 "
logo: "xxxx"
skip_to_content: " 跳至内容 "
pagination:
first: " 首页 "
next: " 下一页 "
page_num: " {{.Pages}}页 "
previous: " 上一页 "
last: " 尾页 "
20_entries: " 20条记录 "
50_entries: " 50条记录 "
100_entries: " 100条记录 "
show_all: " 全部 "
search_center:
all: " 全部 "
hint: " 查询… "
view_all: " 显示全部 "
showpage:
inlineedit:
button:
cancel_edit: " 取消编辑 "
save: " 保存 "
3,页面效果
修改页面
增加页面:
分页效果:
翻译,在yaml 配置里面的可以有个web界面
4,查询views下面templ模板
本来以为qor-admin当中还是有个默认的配置文件。
只要找过来,汉化下,就行呢。结果没有找到。
没有办法就想到扫描下views下面的模板文件,然后解析下。
{{t "qor_admin.filter.advanced_filter" "Advanced Filter"}}
模板,有一个默认的 字符串,没有配置,得文件一个一个解析。
使用golang 进行开发的时候,本来想使用一个python扫描下,但是用docker 环境中,
没有安装python,于是使用golang重写写一个扫描程序。
用起来和 python 一样,运行速度也快,和动态脚本一样。
代码:
package main
import (
"testing"
"log"
"os"
"io/ioutil"
"strings"
"sort"
)
var (
i18nPath = os.Getenv("GOPATH") + "/src/github.com/qor/admin/views"
i18nMap = make(map[string]string)
)
func readDir(base, dir string) {
files, err := ioutil.ReadDir(base + "/" + dir)
if err != nil {
log.Fatal(err)
}
for _, f := range files {
mode := f.Mode()
if mode.IsDir() {
//递归循环,base目录,加上相对目录即可。
readDir(base, dir+"/"+f.Name())
} else if strings.Contains(f.Name(), ".tmpl") {
//println(f.Name())
ReadFile(base + "/" + dir + "/" + f.Name())
}
}
}
func Test_Find(t *testing.T) {
println("i18nPath: ", i18nPath)
readDir(i18nPath, "")
var keys []string
for k := range i18nMap {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
k2 := strings.Replace(k, ".", "\t", -1)
println(k2, ": \"", i18nMap[k], "\"")
}
}
func ReadFile(fileName string) {
data, err := ioutil.ReadFile(fileName)
println("read file :", fileName)
if err == nil {
content := string(data)
print(len(content))
result := GetStringInBetween(content, "{{", "}}")
//println(result)
//fmt.Print(string(data))
for _, val := range result {
val = strings.Replace(val, "\"", "", -1)
//会有多个空格,只split 2 个。
vals := strings.SplitN(val, " ", 2)
println(val, "len:", len(vals))
if len(vals) == 2 {
//println(vals[0], ":", vals[1])
i18nMap[vals[0]] = vals[1]
}
}
}
}
// GetStringInBetween Returns empty string if no start string found
//https://stackoverflow.com/questions/26916952/go-retrieve-a-string-from-between-two-characters-or-other-strings
func GetStringInBetween(str string, start string, end string) (result []string) {
s := 1
for s > 0 {
s = strings.Index(str, start)
//println(s)
if s == -1 {
break
}
s += len(start)
e := strings.Index(str, end)
//println("start:", s, ",end:", e)
if e <= s { //有可数组越界的可能。
break
}
tmpStr := str[s:e]
//判断里面是否存中 t 前缀。
if strings.Contains(tmpStr, "qor_admin") && strings.HasPrefix(tmpStr, "t ") {
//println(tmpStr)
//println(tmpStr)
//替换字符串。
result = append(result, strings.Replace(tmpStr, "t ", "", -1))
}
str = strings.Replace(str, start+tmpStr+end, "", -1)
}
return
}
i18n_test.go 使用golang 的test 进行扫描。和main 在一起也可以执行。
然后就在将打印结果转换成yaml 就行了。
循环查询views下面的tmpl文件,然后再用GetStringInBetween循环返回一个字符串数组。
本来想用正则匹配的,但是实在是没有写出来。
strings.SplitN(val, " ", 2)
//split 按照空格拆分,发现里面有多个,其实只需要拆分成2个,所以用SplitN 参数2。
5,总结
i18n 还是非常方便的,研究了下使用配置文件yaml的方式,解决中文问题。
qor 在设计上是支持yaml但是,并没有一默认的配置文件。
还是自己检索了下views下面的模板文件,然后汇总出来了。
凑成了一个yaml文件,这样就不用修改代码了,并且qor-admin系统更新了,
yaml也不影响。
本文的原文连接是:
https://blog.csdn.net/freewebsys/article/details/80765024
博主地址是:http://blog.csdn.net/freewebsys