feat(i18n): Enhance internationalization support for tool specifications and notifications
- Added TitleKey and DescriptionKey fields to ToolSpec for dynamic localization. - Updated tool specifications to use i18nx for titles, descriptions, and appendices. - Refactored notification messages to utilize i18nx for localization in conversation and ticket assignment events. - Improved localization in the debug dialog component for skill definitions. - Added new translation keys in English and Chinese for ticket and conversation assignment notifications. - Ensured that fallback messages are properly localized based on user locale.
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"agent-desk/internal/pkg/enums"
|
||||
"agent-desk/internal/pkg/errorsx"
|
||||
"agent-desk/internal/pkg/eventbus"
|
||||
"agent-desk/internal/pkg/i18nx"
|
||||
"agent-desk/internal/repositories"
|
||||
|
||||
"github.com/mlogclub/simple/sqls"
|
||||
@@ -18,11 +19,19 @@ import (
|
||||
|
||||
var ConversationHumanDispatchService = newConversationHumanDispatchService()
|
||||
|
||||
const (
|
||||
HandoffWaitingMessage = "We are connecting you to a human support agent. Please wait."
|
||||
HandoffOffHoursMessage = "Human support is currently outside service hours. You can keep describing the issue and I will do my best to help. You can also request a human agent again when service hours resume."
|
||||
var (
|
||||
HandoffWaitingMessage = HandoffWaitingMessageForLocale(i18nx.DefaultLocale)
|
||||
HandoffOffHoursMessage = HandoffOffHoursMessageForLocale(i18nx.DefaultLocale)
|
||||
)
|
||||
|
||||
func HandoffWaitingMessageForLocale(locale string) string {
|
||||
return i18nx.Getf(locale, "conversation.handoff.waiting")
|
||||
}
|
||||
|
||||
func HandoffOffHoursMessageForLocale(locale string) string {
|
||||
return i18nx.Getf(locale, "conversation.handoff.offHours")
|
||||
}
|
||||
|
||||
type HandoffDecisionType string
|
||||
|
||||
const (
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"agent-desk/internal/models"
|
||||
"agent-desk/internal/pkg/enums"
|
||||
"agent-desk/internal/pkg/eventbus"
|
||||
"agent-desk/internal/pkg/i18nx"
|
||||
"agent-desk/internal/services"
|
||||
|
||||
"github.com/mlogclub/simple/common/strs"
|
||||
@@ -37,11 +38,11 @@ func handleConversationAssignedNotify(ctx context.Context, event events.Conversa
|
||||
func conversationAssignedNotifyTitle(assignType string) string {
|
||||
switch strings.TrimSpace(assignType) {
|
||||
case events.ConversationAssignTypeTransfer:
|
||||
return "Conversation transferred"
|
||||
return i18nx.Get("notification.conversationTransferred.title")
|
||||
case events.ConversationAssignTypeAutoAssign:
|
||||
return "Conversation auto-assigned"
|
||||
return i18nx.Get("notification.conversationAutoAssigned.title")
|
||||
default:
|
||||
return "Conversation assigned"
|
||||
return i18nx.Get("notification.conversationAssigned.title")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,21 +50,21 @@ func buildConversationAssignedNotifyBody(conversation *models.Conversation, assi
|
||||
if conversation == nil {
|
||||
return ""
|
||||
}
|
||||
reasonLabel := "Assignment reason"
|
||||
reasonKey := "notification.conversationAssigned.reason"
|
||||
if strings.TrimSpace(assignType) == events.ConversationAssignTypeTransfer {
|
||||
reasonLabel = "Transfer reason"
|
||||
reasonKey = "notification.conversationTransferred.reason"
|
||||
}
|
||||
lines := []string{
|
||||
fmt.Sprintf("Conversation ID: #%d", conversation.ID),
|
||||
fmt.Sprintf("Summary: %s", strs.DefaultIfBlank(services.ConversationService.BuildConversationSummary(conversation), "-")),
|
||||
fmt.Sprintf("Channel: %s", resolveConversationChannelLabel(conversation)),
|
||||
fmt.Sprintf("Status: %s", enums.GetIMConversationStatusLabel(conversation.Status)),
|
||||
fmt.Sprintf("Assignee: %s", resolveNotifyUserLabel(assigneeID)),
|
||||
i18nx.Getf(i18nx.DefaultLocale, "notification.conversationAssigned.wxwork.id", conversation.ID),
|
||||
i18nx.Getf(i18nx.DefaultLocale, "notification.conversationAssigned.wxwork.summary", strs.DefaultIfBlank(services.ConversationService.BuildConversationSummary(conversation), "-")),
|
||||
i18nx.Getf(i18nx.DefaultLocale, "notification.conversationAssigned.wxwork.channel", resolveConversationChannelLabel(conversation)),
|
||||
i18nx.Getf(i18nx.DefaultLocale, "notification.conversationAssigned.wxwork.status", enums.GetIMConversationStatusLabel(conversation.Status)),
|
||||
i18nx.Getf(i18nx.DefaultLocale, "notification.assignee", resolveNotifyUserLabel(assigneeID)),
|
||||
}
|
||||
if strings.TrimSpace(reason) != "" {
|
||||
lines = append(lines, fmt.Sprintf("%s: %s", reasonLabel, strings.TrimSpace(reason)))
|
||||
lines = append(lines, i18nx.Getf(i18nx.DefaultLocale, reasonKey, strings.TrimSpace(reason)))
|
||||
}
|
||||
lines = append(lines, fmt.Sprintf("Time: %s", time.Now().Format("2006-01-02 15:04:05")))
|
||||
lines = append(lines, i18nx.Getf(i18nx.DefaultLocale, "notification.time", time.Now().Format("2006-01-02 15:04:05")))
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"agent-desk/internal/events"
|
||||
"agent-desk/internal/pkg/dto/request"
|
||||
"agent-desk/internal/pkg/eventbus"
|
||||
"agent-desk/internal/pkg/i18nx"
|
||||
"agent-desk/internal/services"
|
||||
|
||||
"github.com/mlogclub/simple/common/strs"
|
||||
@@ -31,16 +32,16 @@ func handleTicketAssignedInAppNotification(ctx context.Context, event events.Tic
|
||||
if ticket == nil {
|
||||
return nil
|
||||
}
|
||||
content := fmt.Sprintf("Ticket %s has been assigned to you.", strs.DefaultIfBlank(ticket.TicketNo, fmt.Sprintf("#%d", ticket.ID)))
|
||||
content := i18nx.Getf(i18nx.DefaultLocale, "notification.ticketAssigned.line", strs.DefaultIfBlank(ticket.TicketNo, fmt.Sprintf("#%d", ticket.ID)))
|
||||
if title := strings.TrimSpace(ticket.Title); title != "" {
|
||||
content = content + "\n" + title
|
||||
}
|
||||
if reason := strings.TrimSpace(event.Reason); reason != "" {
|
||||
content = content + "\nAssignment reason: " + reason
|
||||
content = content + "\n" + i18nx.Getf(i18nx.DefaultLocale, "notification.ticketAssigned.reason", reason)
|
||||
}
|
||||
_, err := services.NotificationService.CreateAndPush(request.CreateNotificationRequest{
|
||||
RecipientUserID: event.ToUserID,
|
||||
Title: "Ticket assigned",
|
||||
Title: i18nx.Get("notification.ticketAssigned.title"),
|
||||
Content: content,
|
||||
NotificationType: "ticket_assigned",
|
||||
BizType: "ticket",
|
||||
@@ -61,12 +62,16 @@ func handleConversationAssignedInAppNotification(ctx context.Context, event even
|
||||
if conversation == nil {
|
||||
return nil
|
||||
}
|
||||
content := fmt.Sprintf("Conversation #%d has been assigned to you.", conversation.ID)
|
||||
content := i18nx.Getf(i18nx.DefaultLocale, "notification.conversationAssigned.line", conversation.ID)
|
||||
if summary := strings.TrimSpace(services.ConversationService.BuildConversationSummary(conversation)); summary != "" {
|
||||
content = content + "\n" + summary
|
||||
}
|
||||
if reason := strings.TrimSpace(event.Reason); reason != "" {
|
||||
content = content + "\nAssignment reason: " + reason
|
||||
reasonKey := "notification.conversationAssigned.reason"
|
||||
if strings.TrimSpace(event.AssignType) == events.ConversationAssignTypeTransfer {
|
||||
reasonKey = "notification.conversationTransferred.reason"
|
||||
}
|
||||
content = content + "\n" + i18nx.Getf(i18nx.DefaultLocale, reasonKey, reason)
|
||||
}
|
||||
_, err := services.NotificationService.CreateAndPush(request.CreateNotificationRequest{
|
||||
RecipientUserID: event.ToUserID,
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"agent-desk/internal/models"
|
||||
"agent-desk/internal/pkg/enums"
|
||||
"agent-desk/internal/pkg/eventbus"
|
||||
"agent-desk/internal/pkg/i18nx"
|
||||
"agent-desk/internal/services"
|
||||
"context"
|
||||
"fmt"
|
||||
@@ -29,7 +30,7 @@ func handleTicketAssignedNotify(ctx context.Context, event events.TicketAssigned
|
||||
return nil
|
||||
}
|
||||
content := buildTicketAssignedNotifyBody(ticket, event.ToUserID, event.Reason)
|
||||
return services.WxWorkNotifyService.SendTextToAssigneeOrDefault(event.ToUserID, "Ticket assigned", content)
|
||||
return services.WxWorkNotifyService.SendTextToAssigneeOrDefault(event.ToUserID, i18nx.Get("notification.ticketAssigned.title"), content)
|
||||
}
|
||||
|
||||
func buildTicketAssignedNotifyBody(ticket *models.Ticket, assigneeID int64, reason string) string {
|
||||
@@ -37,14 +38,14 @@ func buildTicketAssignedNotifyBody(ticket *models.Ticket, assigneeID int64, reas
|
||||
return ""
|
||||
}
|
||||
lines := []string{
|
||||
fmt.Sprintf("Ticket no: %s", strs.DefaultIfBlank(ticket.TicketNo, fmt.Sprintf("#%d", ticket.ID))),
|
||||
fmt.Sprintf("Title: %s", strs.DefaultIfBlank(ticket.Title, "-")),
|
||||
fmt.Sprintf("Status: %s", enums.GetTicketStatusLabel(ticket.Status)),
|
||||
fmt.Sprintf("Assignee: %s", resolveNotifyUserLabel(assigneeID)),
|
||||
i18nx.Getf(i18nx.DefaultLocale, "notification.ticketAssigned.wxwork.no", strs.DefaultIfBlank(ticket.TicketNo, fmt.Sprintf("#%d", ticket.ID))),
|
||||
i18nx.Getf(i18nx.DefaultLocale, "notification.ticketAssigned.wxwork.title", strs.DefaultIfBlank(ticket.Title, "-")),
|
||||
i18nx.Getf(i18nx.DefaultLocale, "notification.ticketAssigned.wxwork.status", enums.GetTicketStatusLabel(ticket.Status)),
|
||||
i18nx.Getf(i18nx.DefaultLocale, "notification.assignee", resolveNotifyUserLabel(assigneeID)),
|
||||
}
|
||||
if strings.TrimSpace(reason) != "" {
|
||||
lines = append(lines, fmt.Sprintf("Assignment reason: %s", strings.TrimSpace(reason)))
|
||||
lines = append(lines, i18nx.Getf(i18nx.DefaultLocale, "notification.ticketAssigned.reason", strings.TrimSpace(reason)))
|
||||
}
|
||||
lines = append(lines, fmt.Sprintf("Time: %s", time.Now().Format("2006-01-02 15:04:05")))
|
||||
lines = append(lines, i18nx.Getf(i18nx.DefaultLocale, "notification.time", time.Now().Format("2006-01-02 15:04:05")))
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"agent-desk/internal/pkg/enums"
|
||||
"agent-desk/internal/pkg/errorsx"
|
||||
"agent-desk/internal/pkg/eventbus"
|
||||
"agent-desk/internal/pkg/i18nx"
|
||||
"agent-desk/internal/pkg/utils"
|
||||
"agent-desk/internal/repositories"
|
||||
|
||||
@@ -265,7 +266,7 @@ func (s *ticketService) CreateFromConversation(req request.CreateTicketFromConve
|
||||
title = strings.TrimSpace(ConversationService.BuildConversationSummary(conversation))
|
||||
}
|
||||
if title == "" {
|
||||
title = "Conversation ticket"
|
||||
title = i18nx.Get("ticket.defaultConversationTitle")
|
||||
}
|
||||
description := strings.TrimSpace(req.Description)
|
||||
if description == "" {
|
||||
|
||||
Reference in New Issue
Block a user