diff --git a/.example/i18n/gi18n/http_view_i18n.go b/.example/i18n/gi18n/http_view_i18n.go index 952ecff7f..dcfda67cb 100644 --- a/.example/i18n/gi18n/http_view_i18n.go +++ b/.example/i18n/gi18n/http_view_i18n.go @@ -1,48 +1,18 @@ package main import ( - "fmt" "github.com/gogf/gf/frame/g" - "github.com/gogf/gf/frame/gmvc" "github.com/gogf/gf/net/ghttp" ) -type Controller struct { - gmvc.Controller -} - -func (c *Controller) Init(r *ghttp.Request) { - c.Controller.Init(r) - c.View.BindFunc("T", c.translate) -} - -func (c *Controller) Index() { - c.View.Display("index.html") -} - -func (c *Controller) translate(langKey, msg string) string { - lang := c.Request.Get("lang", "en") - g.I18n().SetLanguage(lang) - t := g.I18n().T(langKey, lang) - fmt.Println(t, lang, c.Request.Request.Header.Get("Accept-Language")) - return t -} - func main() { - g.I18n().SetPath("i18n-file") - g.View().SetPath(`D:\Workspace\Go\GOPATH\src\github.com\gogf\gf\.example\i18n\gi18n\template`) + g.I18n().SetPath("/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/i18n/gi18n/i18n") s := g.Server() s.BindHandler("/", func(r *ghttp.Request) { - lang := r.Get("lang", "en") - g.I18n().SetLanguage(lang) - r.Response.WriteTplContent(`{#hello}{#world}`) + r.Response.WriteTplContent(`{#hello}{#world}`, g.Map{ + "I18nLanguage": r.Get("lang", "en"), + }) }) - s.BindHandler("/template", func(r *ghttp.Request) { - lang := r.Get("lang", "en") - g.I18n().SetLanguage(lang) - r.Response.WriteTplContent(`{#hello}{#world}`) - }) - s.BindController("/controller", new(Controller)) s.SetPort(8199) s.Run() } diff --git a/net/ghttp/ghttp_client_response.go b/net/ghttp/ghttp_client_response.go index 5ab8fd396..c08de241f 100644 --- a/net/ghttp/ghttp_client_response.go +++ b/net/ghttp/ghttp_client_response.go @@ -20,7 +20,7 @@ type ClientResponse struct { // 获得返回的指定COOKIE值 func (r *ClientResponse) GetCookie(key string) string { - if r.cookies == nil { + if len(r.cookies) == 0 { now := time.Now() for _, v := range r.Cookies() { if v.Expires.UnixNano() < now.UnixNano() { diff --git a/net/ghttp/ghttp_response_view.go b/net/ghttp/ghttp_response_view.go index e2ae43659..8b42a6833 100644 --- a/net/ghttp/ghttp_response_view.go +++ b/net/ghttp/ghttp_response_view.go @@ -13,25 +13,21 @@ import ( ) // 展示模板,可以给定模板参数,及临时的自定义模板函数 -func (r *Response) WriteTpl(tpl string, params ...gview.Params) error { +func (r *Response) WriteTpl(tpl string, params ...gview.Params) { if b, err := r.ParseTpl(tpl, params...); err != nil { r.Write("Template Parsing Error: " + err.Error()) - return err } else { r.Write(b) } - return nil } // 展示模板内容,可以给定模板参数,及临时的自定义模板函数 -func (r *Response) WriteTplContent(content string, params ...gview.Params) error { +func (r *Response) WriteTplContent(content string, params ...gview.Params) { if b, err := r.ParseTplContent(content, params...); err != nil { r.Write("Template Parsing Error: " + err.Error()) - return err } else { r.Write(b) } - return nil } // 解析模板文件,并返回模板内容 diff --git a/net/ghttp/ghttp_server_handler.go b/net/ghttp/ghttp_server_handler.go index 08fc7756e..8fd6f829a 100644 --- a/net/ghttp/ghttp_server_handler.go +++ b/net/ghttp/ghttp_server_handler.go @@ -141,7 +141,6 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) { } // 设置Session Id到Cookie中 if request.Session.Id() != "" && request.GetSessionId() != request.Session.Id() { - request.Response.Header().Set(s.GetSessionIdName(), request.Session.Id()) request.Cookie.SetSessionId(request.Session.Id()) } // 输出Cookie diff --git a/net/ghttp/ghttp_unit_session_test.go b/net/ghttp/ghttp_unit_session_test.go index 174947b8d..6bf92b634 100644 --- a/net/ghttp/ghttp_unit_session_test.go +++ b/net/ghttp/ghttp_unit_session_test.go @@ -93,7 +93,7 @@ func Test_Session_Header(t *testing.T) { if response != nil { defer response.Close() } - sessionId := response.Header.Get(s.GetSessionIdName()) + sessionId := response.GetCookie(s.GetSessionIdName()) gtest.Assert(e1, nil) gtest.AssertNE(sessionId, nil) gtest.Assert(response.ReadAllString(), "") @@ -114,3 +114,50 @@ func Test_Session_Header(t *testing.T) { gtest.Assert(client.GetContent("/get?k=key2"), "") }) } + +func Test_Session_StorageFile(t *testing.T) { + sessionId := "" + gtest.Case(t, func() { + p := ports.PopRand() + s := g.Server(p) + s.BindHandler("/set", func(r *ghttp.Request) { + r.Session.Set(r.Get("k"), r.Get("v")) + r.Response.Write(r.Get("k"), "=", r.Get("v")) + }) + s.SetPort(p) + s.SetDumpRouteMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(200 * time.Millisecond) + + client := ghttp.NewClient() + client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p)) + response, e1 := client.Get("/set?k=key&v=100") + if response != nil { + defer response.Close() + } + sessionId = response.GetCookie(s.GetSessionIdName()) + gtest.Assert(e1, nil) + gtest.AssertNE(sessionId, nil) + gtest.Assert(response.ReadAllString(), "key=100") + }) + time.Sleep(time.Second) + gtest.Case(t, func() { + p := ports.PopRand() + s := g.Server(p) + s.BindHandler("/get", func(r *ghttp.Request) { + r.Response.Write(r.Session.Get(r.Get("k"))) + }) + s.SetPort(p) + s.SetDumpRouteMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(200 * time.Millisecond) + + client := ghttp.NewClient() + client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p)) + client.SetHeader(s.GetSessionIdName(), sessionId) + gtest.Assert(client.GetContent("/get?k=key"), "100") + gtest.Assert(client.GetContent("/get?k=key1"), "") + }) +} diff --git a/os/gsession/gsession_storage_file.go b/os/gsession/gsession_storage_file.go index 137094802..fef92a16e 100644 --- a/os/gsession/gsession_storage_file.go +++ b/os/gsession/gsession_storage_file.go @@ -67,11 +67,8 @@ func NewStorageFile(ttl time.Duration, path ...string) *StorageFile { updatingIdSet: gset.NewStrSet(true), } gtimer.AddSingleton(DefaultStorageFileLoopInterval, func() { - var err error s.updatingIdSet.Iterator(func(v string) bool { - if err = s.doUpdateTTL(v); err != nil { - panic(err) - } + s.doUpdateTTL(v) return true }) }) diff --git a/os/gview/gview.go b/os/gview/gview.go index 982848fe2..a85aad2b4 100644 --- a/os/gview/gview.go +++ b/os/gview/gview.go @@ -5,14 +5,18 @@ // You can obtain one at https://github.com/gogf/gf. // Package gview implements a template engine based on text/template. +// +// Reserved template variable names: +// I18nLanguage: Assign this variable to define i18n language for each page. package gview import ( "errors" "fmt" - "github.com/gogf/gf/i18n/gi18n" "sync" + "github.com/gogf/gf/i18n/gi18n" + "github.com/gogf/gf/os/gres" "github.com/gogf/gf" diff --git a/os/gview/gview_doparse.go b/os/gview/gview_doparse.go index 97035e0cc..96d65ba54 100644 --- a/os/gview/gview_doparse.go +++ b/os/gview/gview_doparse.go @@ -181,38 +181,36 @@ func (view *View) Parse(file string, params ...Params) (parsed string, err error // Note that the template variable assignment cannot change the value // of the existing or view.data because both variables are pointers. // It's need to merge the values of the two maps into a new map. - vars := (map[string]interface{})(nil) + variables := (map[string]interface{})(nil) length := len(view.data) if len(params) > 0 { length += len(params[0]) } if length > 0 { - vars = make(map[string]interface{}, length) + variables = make(map[string]interface{}, length) } if len(view.data) > 0 { if len(params) > 0 { for k, v := range params[0] { - vars[k] = v + variables[k] = v } for k, v := range view.data { - vars[k] = v + variables[k] = v } } else { - vars = view.data + variables = view.data } } else { if len(params) > 0 { - vars = params[0] + variables = params[0] } } buffer := bytes.NewBuffer(nil) - if err := tpl.Execute(buffer, vars); err != nil { + if err := tpl.Execute(buffer, variables); err != nil { return "", err } result := gstr.Replace(buffer.String(), "", "") - if view.i18nManager != nil { - result = view.i18nManager.T(result) - } + result = view.i18nTranslate(result, variables) return result, nil } @@ -237,37 +235,35 @@ func (view *View) ParseContent(content string, params ...Params) (string, error) // Note that the template variable assignment cannot change the value // of the existing or view.data because both variables are pointers. // It's need to merge the values of the two maps into a new map. - vars := (map[string]interface{})(nil) + variables := (map[string]interface{})(nil) length := len(view.data) if len(params) > 0 { length += len(params[0]) } if length > 0 { - vars = make(map[string]interface{}, length) + variables = make(map[string]interface{}, length) } if len(view.data) > 0 { if len(params) > 0 { for k, v := range params[0] { - vars[k] = v + variables[k] = v } for k, v := range view.data { - vars[k] = v + variables[k] = v } } else { - vars = view.data + variables = view.data } } else { if len(params) > 0 { - vars = params[0] + variables = params[0] } } buffer := bytes.NewBuffer(nil) - if err := tpl.Execute(buffer, vars); err != nil { + if err := tpl.Execute(buffer, variables); err != nil { return "", err } result := gstr.Replace(buffer.String(), "", "") - if view.i18nManager != nil { - result = view.i18nManager.T(result) - } + result = view.i18nTranslate(result, variables) return result, nil } diff --git a/os/gview/gview_i18n.go b/os/gview/gview_i18n.go new file mode 100644 index 000000000..0aa653053 --- /dev/null +++ b/os/gview/gview_i18n.go @@ -0,0 +1,23 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gview + +import "github.com/gogf/gf/util/gconv" + +// i18nTranslate translate the content with i18n feature. +func (view *View) i18nTranslate(content string, params Params) string { + if view.i18nManager != nil { + if v, ok := params["I18nLanguage"]; ok { + language := gconv.String(v) + if language != "" { + return view.i18nManager.T(content, language) + } + } + return view.i18nManager.T(content) + } + return content +}