Skip to content

Commit f1a5b27

Browse files
committed
Translate validation error messages
1 parent b2e054b commit f1a5b27

File tree

6 files changed

+127
-6
lines changed

6 files changed

+127
-6
lines changed

app/app.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ func Run(ctx context.Context, distFS embed.FS, pragmasSQL string, localesFS embe
5757
return err
5858
}
5959

60+
intl.SetupZogI18n()
61+
6062
s := server.New(cfg, logger, sqlDB, queries, vite, sessionStore, email, i18nBundle)
6163

6264
return server.Run(ctx, s, logger, cfg.Port)

app/forms/members.forms.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
z "github.com/Oudwins/zog"
77
"github.com/Oudwins/zog/zhttp"
8+
"github.com/nicolashery/simply-shared-notes/app/rctx"
89
)
910

1011
var memberNameSchema = z.String().Trim().Required().Min(1).Max(255)
@@ -19,7 +20,8 @@ var createMemberSchema = z.Struct(z.Shape{
1920

2021
func ParseCreateMember(r *http.Request) (CreateMember, map[string][]string) {
2122
var form CreateMember
22-
errs := createMemberSchema.Parse(zhttp.Request(r), &form)
23+
intl := rctx.GetIntl(r.Context())
24+
errs := createMemberSchema.Parse(zhttp.Request(r), &form, intl.ZogParseOpts())
2325
if errs == nil {
2426
return form, nil
2527
}
@@ -37,7 +39,8 @@ var updateMemberSchema = z.Struct(z.Shape{
3739

3840
func ParseUpdateMember(r *http.Request) (UpdateMember, map[string][]string) {
3941
var form UpdateMember
40-
errs := updateMemberSchema.Parse(zhttp.Request(r), &form)
42+
intl := rctx.GetIntl(r.Context())
43+
errs := updateMemberSchema.Parse(zhttp.Request(r), &form, intl.ZogParseOpts())
4144
if errs == nil {
4245
return form, nil
4346
}

app/forms/notes.forms.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
z "github.com/Oudwins/zog"
77
"github.com/Oudwins/zog/zhttp"
8+
"github.com/nicolashery/simply-shared-notes/app/rctx"
89
)
910

1011
var noteTitleSchema = z.String().Trim().Required().Min(1).Max(255)
@@ -21,7 +22,8 @@ var createNoteSchema = z.Struct(z.Shape{
2122

2223
func ParseCreateNote(r *http.Request) (CreateNote, map[string][]string) {
2324
var form CreateNote
24-
errs := createNoteSchema.Parse(zhttp.Request(r), &form)
25+
intl := rctx.GetIntl(r.Context())
26+
errs := createNoteSchema.Parse(zhttp.Request(r), &form, intl.ZogParseOpts())
2527
if errs == nil {
2628
return form, nil
2729
}
@@ -41,7 +43,8 @@ var updateNoteSchema = z.Struct(z.Shape{
4143

4244
func ParseUpdateNote(r *http.Request) (UpdateNote, map[string][]string) {
4345
var form UpdateNote
44-
errs := updateNoteSchema.Parse(zhttp.Request(r), &form)
46+
intl := rctx.GetIntl(r.Context())
47+
errs := updateNoteSchema.Parse(zhttp.Request(r), &form, intl.ZogParseOpts())
4548
if errs == nil {
4649
return form, nil
4750
}

app/forms/spaces.forms.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
z "github.com/Oudwins/zog"
77
"github.com/Oudwins/zog/zhttp"
8+
"github.com/nicolashery/simply-shared-notes/app/rctx"
89
)
910

1011
type CreateSpace struct {
@@ -36,7 +37,8 @@ func ParseCreateSpace(r *http.Request, requiresCode bool) (CreateSpace, map[stri
3637
form.Code = "placeholder"
3738
}
3839

39-
errs := createSpaceSchema(requiresCode).Parse(zhttp.Request(r), &form)
40+
intl := rctx.GetIntl(r.Context())
41+
errs := createSpaceSchema(requiresCode).Parse(zhttp.Request(r), &form, intl.ZogParseOpts())
4042
if errs == nil {
4143
return form, nil
4244
}
@@ -54,7 +56,8 @@ var updateSpaceSchema = z.Struct(z.Shape{
5456

5557
func ParseUpdateSpace(r *http.Request) (UpdateSpace, map[string][]string) {
5658
var form UpdateSpace
57-
errs := updateSpaceSchema.Parse(zhttp.Request(r), &form)
59+
intl := rctx.GetIntl(r.Context())
60+
errs := updateSpaceSchema.Parse(zhttp.Request(r), &form, intl.ZogParseOpts())
5861
if errs == nil {
5962
return form, nil
6063
}

app/intl/intl.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import (
88
"time"
99

1010
"github.com/BurntSushi/toml"
11+
z "github.com/Oudwins/zog"
12+
zogi18n "github.com/Oudwins/zog/i18n"
13+
"github.com/Oudwins/zog/i18n/en"
1114
"github.com/goodsign/monday"
1215
"github.com/nicksnyder/go-i18n/v2/i18n"
1316
"golang.org/x/text/language"
@@ -46,6 +49,16 @@ func NewBundle(localesFS embed.FS) (*i18n.Bundle, error) {
4649
return b, nil
4750
}
4851

52+
func SetupZogI18n() {
53+
zogi18n.SetLanguagesErrsMap(
54+
map[string]zogi18n.LangMap{
55+
"en": en.Map,
56+
"fr": ZogFrenchMap,
57+
},
58+
"en", // default language
59+
)
60+
}
61+
4962
func New(
5063
logger *slog.Logger,
5164
i18nBundle *i18n.Bundle,
@@ -127,3 +140,9 @@ func (i *Intl) TimeInUserTz(t time.Time) time.Time {
127140

128141
return t.In(i.CurrentTimezone)
129142
}
143+
144+
func (i *Intl) ZogParseOpts() z.ExecOption {
145+
base, _ := i.CurrentLang.Base()
146+
147+
return z.WithCtxValue("lang", base.String())
148+
}

app/intl/zog.fr.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package intl
2+
3+
import (
4+
"github.com/Oudwins/zog/zconst"
5+
)
6+
7+
var ZogFrenchMap zconst.LangMap = map[zconst.ZogType]map[zconst.ZogIssueCode]string{
8+
zconst.TypeString: {
9+
zconst.NotIssueCode(zconst.IssueCodeLen): "la chaîne ne doit pas contenir exactement {{len}} caractère(s)",
10+
zconst.NotIssueCode(zconst.IssueCodeEmail): "ne doit pas être un email valide",
11+
zconst.NotIssueCode(zconst.IssueCodeUUID): "ne doit pas être un UUID valide",
12+
zconst.NotIssueCode(zconst.IssueCodeMatch): "la chaîne est invalide",
13+
zconst.NotIssueCode(zconst.IssueCodeURL): "ne doit pas être une URL valide",
14+
zconst.NotIssueCode(zconst.IssueCodeHasPrefix): "la chaîne ne doit pas commencer par {{prefix}}",
15+
zconst.NotIssueCode(zconst.IssueCodeHasSuffix): "la chaîne ne doit pas se terminer par {{suffix}}",
16+
zconst.NotIssueCode(zconst.IssueCodeContains): "la chaîne ne doit pas contenir {{contained}}",
17+
zconst.NotIssueCode(zconst.IssueCodeContainsDigit): "la chaîne ne doit pas contenir de chiffres",
18+
zconst.NotIssueCode(zconst.IssueCodeContainsUpper): "la chaîne ne doit pas contenir de lettres majuscules",
19+
zconst.NotIssueCode(zconst.IssueCodeContainsLower): "la chaîne ne doit pas contenir de lettres minuscules",
20+
zconst.NotIssueCode(zconst.IssueCodeContainsSpecial): "la chaîne ne doit pas contenir de caractères spéciaux",
21+
zconst.NotIssueCode(zconst.IssueCodeOneOf): "la chaîne ne doit pas être parmi {{one_of_options}}",
22+
zconst.IssueCodeRequired: "est requis",
23+
zconst.IssueCodeNotNil: "ne doit pas être vide",
24+
zconst.IssueCodeMin: "doit contenir au moins {{min}} caractère(s)",
25+
zconst.IssueCodeMax: "doit contenir au plus {{max}} caractère(s)",
26+
zconst.IssueCodeLen: "doit contenir exactement {{len}} caractère(s)",
27+
zconst.IssueCodeEmail: "doit être un email valide",
28+
zconst.IssueCodeUUID: "doit être un UUID valide",
29+
zconst.IssueCodeMatch: "la chaîne est invalide",
30+
zconst.IssueCodeURL: "doit être une URL valide",
31+
zconst.IssueCodeHasPrefix: "doit commencer par {{prefix}}",
32+
zconst.IssueCodeHasSuffix: "doit se terminer par {{suffix}}",
33+
zconst.IssueCodeContains: "doit contenir {{contained}}",
34+
zconst.IssueCodeContainsDigit: "doit contenir au moins un chiffre",
35+
zconst.IssueCodeContainsUpper: "doit contenir au moins une lettre majuscule",
36+
zconst.IssueCodeContainsLower: "doit contenir au moins une lettre minuscule",
37+
zconst.IssueCodeContainsSpecial: "doit contenir au moins un caractère spécial",
38+
zconst.IssueCodeOneOf: "doit être parmi {{one_of_options}}",
39+
zconst.IssueCodeFallback: "la chaîne est invalide",
40+
},
41+
zconst.TypeBool: {
42+
zconst.IssueCodeRequired: "est requis",
43+
zconst.IssueCodeNotNil: "ne doit pas être vide",
44+
zconst.IssueCodeTrue: "doit être vrai",
45+
zconst.IssueCodeEQ: "doit être égal à {{eq}}",
46+
zconst.IssueCodeFalse: "doit être faux",
47+
zconst.IssueCodeFallback: "la valeur est invalide",
48+
},
49+
zconst.TypeNumber: {
50+
zconst.IssueCodeRequired: "est requis",
51+
zconst.IssueCodeNotNil: "ne doit pas être vide",
52+
zconst.IssueCodeLTE: "doit être inférieur ou égal à {{lte}}",
53+
zconst.IssueCodeLT: "doit être inférieur à {{lt}}",
54+
zconst.IssueCodeGTE: "doit être supérieur ou égal à {{gte}}",
55+
zconst.IssueCodeGT: "doit être supérieur à {{gt}}",
56+
zconst.IssueCodeEQ: "doit être égal à {{eq}}",
57+
zconst.NotIssueCode(zconst.IssueCodeEQ): "ne doit pas être égal à {{eq}}",
58+
zconst.IssueCodeOneOf: "doit être parmi {{one_of_options}}",
59+
zconst.NotIssueCode(zconst.IssueCodeOneOf): "ne doit pas être parmi {{one_of_options}}",
60+
zconst.IssueCodeFallback: "le nombre est invalide",
61+
},
62+
zconst.TypeTime: {
63+
zconst.IssueCodeRequired: "est requis",
64+
zconst.IssueCodeNotNil: "ne doit pas être vide",
65+
zconst.IssueCodeAfter: "doit être après {{after}}",
66+
zconst.IssueCodeBefore: "doit être avant {{before}}",
67+
zconst.IssueCodeEQ: "doit être égal à {{eq}}",
68+
zconst.IssueCodeFallback: "l'heure est invalide",
69+
},
70+
zconst.TypeSlice: {
71+
zconst.IssueCodeRequired: "est requis",
72+
zconst.IssueCodeNotNil: "ne doit pas être vide",
73+
zconst.IssueCodeMin: "doit contenir au moins {{min}} élément(s)",
74+
zconst.IssueCodeMax: "doit contenir au plus {{max}} élément(s)",
75+
zconst.IssueCodeLen: "doit contenir exactement {{len}} élément(s)",
76+
zconst.NotIssueCode(zconst.IssueCodeLen): "ne doit pas contenir exactement {{len}} élément(s)",
77+
zconst.IssueCodeContains: "doit contenir {{contained}}",
78+
zconst.NotIssueCode(zconst.IssueCodeContains): "ne doit pas contenir {{contained}}",
79+
zconst.IssueCodeFallback: "la liste est invalide",
80+
},
81+
zconst.TypeStruct: {
82+
zconst.IssueCodeRequired: "est requis",
83+
zconst.IssueCodeNotNil: "ne doit pas être vide",
84+
zconst.IssueCodeFallback: "la structure est invalide",
85+
// JSON
86+
zconst.IssueCodeInvalidJSON: "corps JSON invalide",
87+
// ZHTTP ISSUES
88+
zconst.IssueCodeZHTTPInvalidForm: "données de formulaire invalides",
89+
zconst.IssueCodeZHTTPInvalidQuery: "paramètres de requête invalides",
90+
},
91+
}

0 commit comments

Comments
 (0)