Basic Introduction
This feature is supported starting from version v2.10.0.
When developing multi-language applications, internationalization of error messages is a common requirement. The gerror component of the GoFrame framework, starting from version v2.10.0, provides the ITextArgs interface to support internationalization scenarios for error information.
This interface allows error objects to separately expose error message templates and formatting parameters, enabling developers to:
- Obtain the original error message template (unformatted)
- Obtain formatting parameters in the template
- Translate templates according to different language environments
- Reformat translated messages using parameters
This design prevents error messages from being formatted at creation time, ensuring flexibility in internationalization scenarios.
Interface Definition
ITextArgs Interface
// ITextArgs is the interface for Text and Args features.
// This interface is mainly used for i18n features, that needs text and args separately.
type ITextArgs interface {
error
Text() string
Args() []any
}
Core Methods
The gerror.Error object implements the ITextArgs interface and provides the following methods:
| Method | Return Type | Description |
|---|---|---|
Text() | string | Returns the formatting template string of the error message (without parameter substitution). For example: "user %s not found with id: %d" |
Args() | []any | Returns the parameter list used for formatting. For example: ["john", 123] |
TextWithArgs() | string | Returns the complete formatted error message, equivalent to the Error() method. For example: "user john not found with id: 123" |
Use Cases
1. Internationalization (i18n)
In multi-language applications, you can obtain error message templates, translate them in different language environments, and then format them:
package main
import (
"context"
"errors"
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/i18n/gi18n"
)
func main() {
// Create an error with parameters
err := gerror.Newf("user %s not found with id: %d", "john", 123)
// Get error message template and parameters
var e gerror.ITextArgs
if errors.As(err, &e) {
var (
format = e.Text() // "user %s not found with id: %d"
args = e.Args() // ["john", 123]
ctx = context.Background()
i18n = gi18n.New(gi18n.Options{
Language: "zh-CN",
})
)
// In internationalization scenarios, you can translate the template first, then format it
translated := i18n.Tf(ctx, format, args...)
fmt.Println(translated)
}
}
2. Structured Error Handling
In logging systems or monitoring systems, you can separately record error templates and parameters for subsequent analysis:
package main
import (
"context"
"errors"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
)
func main() {
var (
ctx = context.Background()
err = gerror.Newf("failed to connect to database %s:%d", "localhost", 3306)
e gerror.ITextArgs
)
if errors.As(err, &e) {
// Record structured logs
g.Log().Error(ctx, g.Map{
"error_template": e.Text(),
"error_args": e.Args(),
"error_message": e.Error(),
})
}
}
3. Error Analysis and Aggregation
In error collection systems, you can aggregate statistics by error template rather than by complete error message:
package main
import (
"github.com/gogf/gf/v2/errors/gerror"
)
// Error statistics tracker
type ErrorStats struct {
counts map[string]int
}
func (s *ErrorStats) Record(err error) {
if e, ok := err.(gerror.ITextArgs); ok {
// Count by template, not by complete message
template := e.Text()
s.counts[template]++
}
}
Complete Examples
Basic Usage
package main
import (
"errors"
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
)
func main() {
// Create an error with parameters
err := gerror.Newf("user %s not found with id: %d", "john", 123)
// Get complete error message
fmt.Println("Error:", err.Error())
// Output: Error: user john not found with id: 123
// Get error message template and parameters
var e gerror.ITextArgs
if errors.As(err, &e) {
fmt.Println("Template:", e.Text())
// Output: Template: user %s not found with id: %d
fmt.Println("Args:", e.Args())
// Output: Args: [john 123]
}
}
Internationalization Translation Example
The following example demonstrates how to use the ITextArgs interface to implement multi-language translation of error messages:
package main
import (
"errors"
"fmt"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
)
// Simple translation mapping
var translations = map[string]map[string]string{
"en": {
"user %s not found with id: %d": "user %s not found with id: %d",
"failed to connect to database %s:%d": "failed to connect to database %s:%d",
"invalid parameter: %s must be %s": "invalid parameter: %s must be %s",
"operation timeout after %d seconds": "operation timeout after %d seconds",
},
"zh": {
"user %s not found with id: %d": "用户 %s 未找到,ID: %d",
"failed to connect to database %s:%d": "无法连接到数据库 %s:%d",
"invalid parameter: %s must be %s": "无效参数:%s 必须是 %s",
"operation timeout after %d seconds": "操作超时,已等待 %d 秒",
},
"ja": {
"user %s not found with id: %d": "ユーザー %s が見つかりません、ID: %d",
"failed to connect to database %s:%d": "データベース %s:%d への接続に失敗しました",
"invalid parameter: %s must be %s": "無効なパラメータ: %s は %s である必要があります",
"operation timeout after %d seconds": "%d 秒後に操作がタイムアウトしました",
},
}
// Translation function
func translate(template string, lang string) string {
if langMap, ok := translations[lang]; ok {
if trans, ok := langMap[template]; ok {
return trans
}
}
// If no translation is found, return the original template
return template
}
// TranslateError translates an error to the specified language
func TranslateError(err error, lang string) string {
var e gerror.ITextArgs
if errors.As(err, &e) {
// Get template and parameters
template := e.Text()
args := e.Args()
// Translate template
translatedTemplate := translate(template, lang)
// Format translated template with parameters
return fmt.Sprintf(translatedTemplate, args...)
}
// If ITextArgs interface is not supported, return error message directly
return err.Error()
}
func main() {
// Create different types of errors
allErrors := []error{
gerror.Newf("user %s not found with id: %d", "john", 123),
gerror.NewCodef(gcode.CodeInvalidParameter, "invalid parameter: %s must be %s", "age", "positive"),
gerror.Newf("operation timeout after %d seconds", 30),
}
// Test translation in different languages
languages := []string{"en", "zh", "ja"}
for _, err := range allErrors {
fmt.Println("\nOriginal Error:", err.Error())
for _, lang := range languages {
translated := TranslateError(err, lang)
fmt.Printf(" %s: %s\n", lang, translated)
}
}
}
Output Example:
Original Error: user john not found with id: 123
en: user john not found with id: 123
zh: 用户 john 未找到,ID: 123
ja: ユーザー john が見つかりません、ID: 123
Original Error: invalid parameter: age must be positive
en: invalid parameter: age must be positive
zh: 无效参数:age 必须是 positive
ja: 無効なパラメータ: age は positive である必要があります
Original Error: operation timeout after 30 seconds
en: operation timeout after 30 seconds
zh: 操作超时,已等待 30 秒
ja: 30 秒後に操作がタイムアウトしました
Combining with gi18n Component
In actual projects, you can use it in combination with GoFrame's gi18n internationalization component:
package main
import (
"context"
"errors"
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/i18n/gi18n"
"github.com/gogf/gf/v2/os/gctx"
)
// TranslateErrorWithI18n translates error using gi18n
func TranslateErrorWithI18n(ctx context.Context, err error) string {
var e gerror.ITextArgs
if errors.As(err, &e) {
// Get template and parameters
var (
format = e.Text()
args = e.Args()
)
// Format translated template with parameters
return gi18n.Tf(ctx, format, args...)
}
return err.Error()
}
func main() {
var ctx = gctx.New()
// Set language
ctx = gi18n.WithLanguage(ctx, "zh-CN")
// Create error
err := gerror.Newf("user %s not found with id: %d", "john", 123)
// Translate error
translated := TranslateErrorWithI18n(ctx, err)
fmt.Println(translated)
}