Enhance i18n support and refactor API response handling in assistant functions

- Introduced global i18n initialization and connector setup in the Load function for better localization support.
- Refactored handleAssistantList, handleAssistantDetail, and handleAssistantTags functions to utilize the new Translate method for improved response translation based on user locale.
- Simplified locale handling by removing redundant code and centralizing translation logic.
This commit is contained in:
Max 2025-05-25 10:51:02 +08:00
parent 6467a9c37e
commit 1b921cf7b0
4 changed files with 175 additions and 55 deletions

View file

@ -889,22 +889,15 @@ func (neo *DSL) handleAssistantList(c *gin.Context) {
return
}
// Translate the response
locale := "en-us" // Default locale
if loc := c.Query("locale"); loc != "" {
locale = strings.ToLower(strings.TrimSpace(loc))
}
for i, ast := range response.Data {
id := ast["assistant_id"].(string)
if locales, ok := assistant.Locales[id]; ok {
if loc := c.Query("locale"); loc != "" {
loc = strings.ToLower(strings.TrimSpace(loc))
if _, ok := locales[loc]; ok {
locale = loc
}
}
if i18n, ok := locales[locale]; ok {
response.Data[i] = i18n.Parse(ast).(map[string]interface{})
}
}
response.Data[i] = assistant.Translate(locale, id, ast).(map[string]interface{})
}
c.JSON(200, response)
c.Done()
}
@ -995,18 +988,12 @@ func (neo *DSL) handleAssistantDetail(c *gin.Context) {
}
locale := "en-us" // Default locale
id := response.Data[0]["assistant_id"].(string)
if locales, ok := assistant.Locales[id]; ok {
if loc := c.Query("locale"); loc != "" {
loc = strings.ToLower(strings.TrimSpace(loc))
if _, ok := locales[loc]; ok {
locale = loc
}
}
if i18n, ok := locales[locale]; ok {
response.Data[0] = i18n.Parse(response.Data[0]).(map[string]interface{})
}
// Translate the response
if loc := c.Query("locale"); loc != "" {
locale = strings.ToLower(strings.TrimSpace(loc))
}
id := response.Data[0]["assistant_id"].(string)
response.Data[0] = assistant.Translate(locale, id, response.Data[0]).(map[string]interface{})
c.JSON(200, map[string]interface{}{"data": response.Data[0]})
c.Done()
@ -1118,6 +1105,21 @@ func (neo *DSL) handleAssistantTags(c *gin.Context) {
return
}
c.JSON(200, gin.H{"data": tags})
// Translate the tags
locale := "en-us" // Default locale
if loc := c.Query("locale"); loc != "" {
locale = strings.ToLower(strings.TrimSpace(loc))
}
// Translate the tags
items := []map[string]interface{}{}
for _, value := range tags {
items = append(items, map[string]interface{}{
"label": assistant.Translate(locale, "", value).(string),
"key": value,
})
}
c.JSON(200, gin.H{"data": items})
c.Done()
}

View file

@ -1,7 +1,12 @@
package assistant
import (
"path/filepath"
"strings"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/fs"
"github.com/yaoapp/kun/maps"
)
// Locales the locales
@ -49,3 +54,98 @@ func (i18n I18n) Parse(input any) any {
return input
}
// GetI18n load the i18n from path
func GetI18n(path string) (map[string]I18n, error) {
app, err := fs.Get("app")
if err != nil {
return nil, err
}
// Get the global i18n
globalI18ns, hasGlobal := Locales["__global__"]
// i18ns
localesdir := filepath.Join(path, "locales")
var i18ns map[string]I18n = map[string]I18n{}
if has, _ := app.Exists(localesdir); has {
locales, err := app.ReadDir(localesdir, true)
if err != nil {
return nil, err
}
// load locales
for _, locale := range locales {
localeData, err := app.ReadFile(locale)
if err != nil {
return nil, err
}
var messages maps.Map = map[string]any{}
err = application.Parse(locale, localeData, &messages)
if err != nil {
return nil, err
}
name := strings.ToLower(strings.TrimSuffix(filepath.Base(locale), ".yml"))
// Merge the global i18n
if hasGlobal {
global, has := globalI18ns[name]
if has {
for key, value := range global.Messages {
if _, ok := messages[key]; !ok {
messages[key] = value
}
}
}
}
i18ns[name] = I18n{Locale: name, Messages: messages.Dot()}
namer := strings.Split(name, "-")
if len(namer) > 1 {
// Merge the global i18n
if hasGlobal {
global, has := globalI18ns[namer[0]]
if has {
for key, value := range global.Messages {
if _, ok := messages[key]; !ok {
messages[key] = value
}
}
}
}
i18ns[namer[0]] = I18n{Locale: name, Messages: messages.Dot()}
}
}
}
return i18ns, nil
}
// Translate translate the input
func Translate(locale string, id string, input any) any {
locale = strings.ToLower(strings.TrimSpace(locale))
i18ns, has := Locales[id]
if !has {
i18ns = map[string]I18n{}
}
i18n, has := i18ns[locale]
if !has {
namer := strings.Split(locale, "-")
lang := namer[0]
i18n, has = i18ns[lang]
}
if !has {
var hasGlobal bool = false
i18ns, hasGlobal = Locales["__global__"]
if hasGlobal {
i18n, has = i18ns[locale]
}
}
if has {
return i18n.Parse(input)
}
return input
}

View file

@ -14,7 +14,6 @@ import (
"github.com/yaoapp/gou/fs"
"github.com/yaoapp/gou/rag/driver"
v8 "github.com/yaoapp/gou/runtime/v8"
"github.com/yaoapp/kun/maps"
"github.com/yaoapp/yao/neo/store"
neovision "github.com/yaoapp/yao/neo/vision"
"github.com/yaoapp/yao/openai"
@ -315,37 +314,11 @@ func LoadPath(path string) (*Assistant, error) {
}
// i18ns
localesdir := filepath.Join(path, "locales")
var i18ns map[string]I18n = map[string]I18n{}
if has, _ := app.Exists(localesdir); has {
locales, err := app.ReadDir(localesdir, true)
if err != nil {
return nil, err
}
// load locales
for _, locale := range locales {
localeData, err := app.ReadFile(locale)
if err != nil {
return nil, err
}
var messages maps.Map
err = application.Parse(locale, localeData, &messages)
if err != nil {
return nil, err
}
if messages != nil {
name := strings.ToLower(strings.TrimSuffix(filepath.Base(locale), ".yml"))
i18ns[name] = I18n{Locale: name, Messages: messages.Dot()}
namer := strings.Split(name, "-")
if len(namer) > 1 {
i18ns[namer[0]] = I18n{Locale: name, Messages: messages.Dot()}
}
}
}
data["locales"] = i18ns
locales, err := GetI18n(path)
if err != nil {
return nil, err
}
data["locales"] = locales
return loadMap(data)
}

View file

@ -63,6 +63,18 @@ func Load(cfg config.Config) error {
return err
}
// Initialize Connectors
err = initConnectors()
if err != nil {
return err
}
// Initialize Global I18n
err = initGlobalI18n()
if err != nil {
return err
}
// Initialize Assistant
err = initAssistant()
if err != nil {
@ -72,6 +84,39 @@ func Load(cfg config.Config) error {
return nil
}
// initGlobalI18n initialize the global i18n
func initGlobalI18n() error {
locales, err := assistant.GetI18n("neo")
if err != nil {
return err
}
assistant.Locales["__global__"] = locales
return nil
}
// initConnectors initialize the connectors
func initConnectors() error {
path := filepath.Join("neo", "connectors.yml")
if exists, _ := application.App.Exists(path); !exists {
return nil
}
// Open the connectors
bytes, err := application.App.Read(path)
if err != nil {
return err
}
var connectors map[string]assistant.ConnectorSetting = map[string]assistant.ConnectorSetting{}
err = application.Parse("connectors.yml", bytes, &connectors)
if err != nil {
return err
}
Neo.Connectors = connectors
return nil
}
// initStore initialize the store
func initStore() error {