0
# Internationalization
1
2
Error message localization with 44+ languages support.
3
4
## Locale Functions
5
6
```typescript { .api }
7
namespace locales {
8
function en(): LocaleConfig; // English (default)
9
function es(): LocaleConfig; // Spanish
10
function fr(): LocaleConfig; // French
11
function de(): LocaleConfig; // German
12
function ja(): LocaleConfig; // Japanese
13
function zh_CN(): LocaleConfig; // Chinese (Simplified)
14
function zh_TW(): LocaleConfig; // Chinese (Traditional)
15
function pt(): LocaleConfig; // Portuguese
16
function ru(): LocaleConfig; // Russian
17
function it(): LocaleConfig; // Italian
18
function ko(): LocaleConfig; // Korean
19
function ar(): LocaleConfig; // Arabic
20
function hi(): LocaleConfig; // Hindi
21
function nl(): LocaleConfig; // Dutch
22
function pl(): LocaleConfig; // Polish
23
function tr(): LocaleConfig; // Turkish
24
function sv(): LocaleConfig; // Swedish
25
function cs(): LocaleConfig; // Czech
26
function da(): LocaleConfig; // Danish
27
function fi(): LocaleConfig; // Finnish
28
function he(): LocaleConfig; // Hebrew
29
function hu(): LocaleConfig; // Hungarian
30
function id(): LocaleConfig; // Indonesian
31
function nb(): LocaleConfig; // Norwegian
32
function ro(): LocaleConfig; // Romanian
33
function sk(): LocaleConfig; // Slovak
34
function th(): LocaleConfig; // Thai
35
function uk(): LocaleConfig; // Ukrainian
36
function vi(): LocaleConfig; // Vietnamese
37
// ... and more
38
}
39
```
40
41
## Global Locale Configuration
42
43
```typescript
44
// Set global locale
45
z.config({ locale: z.locales.es() });
46
47
// All validation errors will use Spanish messages
48
const schema = z.string().min(5);
49
schema.safeParse("abc");
50
// Error message in Spanish: "La cadena debe contener al menos 5 caracteres"
51
```
52
53
## Per-Schema Locale
54
55
```typescript
56
// Per-schema locale via error map
57
const schema = z.string().min(5);
58
59
schema.parse("abc", {
60
errorMap: z.locales.fr(),
61
});
62
// Error message in French
63
```
64
65
## Available Locales
66
67
Full list includes:
68
- ar (Arabic)
69
- bg (Bulgarian)
70
- cs (Czech)
71
- da (Danish)
72
- de (German)
73
- el (Greek)
74
- en (English)
75
- es (Spanish)
76
- fa (Persian)
77
- fi (Finnish)
78
- fr (French)
79
- he (Hebrew)
80
- hi (Hindi)
81
- hu (Hungarian)
82
- id (Indonesian)
83
- it (Italian)
84
- ja (Japanese)
85
- ko (Korean)
86
- nb (Norwegian)
87
- nl (Dutch)
88
- pl (Polish)
89
- pt (Portuguese)
90
- ro (Romanian)
91
- ru (Russian)
92
- sk (Slovak)
93
- sv (Swedish)
94
- th (Thai)
95
- tr (Turkish)
96
- uk (Ukrainian)
97
- vi (Vietnamese)
98
- zh_CN (Chinese Simplified)
99
- zh_TW (Chinese Traditional)
100
101
## Examples
102
103
```typescript
104
// Spanish
105
z.config({ locale: z.locales.es() });
106
107
const UserSchema = z.object({
108
name: z.string().min(3),
109
email: z.email(),
110
age: z.number().positive(),
111
});
112
113
UserSchema.safeParse({ name: "Ab", email: "invalid", age: -5 });
114
// Errors in Spanish
115
116
// French
117
z.config({ locale: z.locales.fr() });
118
const result = z.string().email().safeParse("invalid");
119
// Error: "L'email n'est pas valide"
120
121
// Japanese
122
z.config({ locale: z.locales.ja() });
123
const result = z.number().min(10).safeParse(5);
124
// Error: "数値は10以上である必要があります"
125
126
// Arabic (RTL language)
127
z.config({ locale: z.locales.ar() });
128
const result = z.string().min(5).safeParse("abc");
129
// Error in Arabic
130
131
// Multi-language support
132
const languages = {
133
en: z.locales.en(),
134
es: z.locales.es(),
135
fr: z.locales.fr(),
136
de: z.locales.de(),
137
};
138
139
function validateWithLocale(data: unknown, locale: keyof typeof languages) {
140
const errorMap = languages[locale];
141
return schema.safeParse(data, { errorMap });
142
}
143
```
144
145
## Custom Error Messages with Locales
146
147
```typescript
148
// Override specific messages while keeping locale for others
149
z.config({ locale: z.locales.es() });
150
151
const schema = z.string()
152
.min(5, "Este mensaje es personalizado") // Custom message
153
.email(); // Will use Spanish locale message
154
155
// Per-field custom messages
156
const FormSchema = z.object({
157
username: z.string()
158
.min(3, "El nombre de usuario debe tener al menos 3 caracteres"),
159
email: z.email("Correo electrónico no válido"),
160
age: z.number().positive("La edad debe ser positiva"),
161
});
162
```
163
164
## Common Patterns
165
166
```typescript
167
// Dynamic locale based on user preference
168
function createValidator(userLocale: string) {
169
const localeMap: Record<string, any> = {
170
'en': z.locales.en(),
171
'es': z.locales.es(),
172
'fr': z.locales.fr(),
173
'de': z.locales.de(),
174
'ja': z.locales.ja(),
175
};
176
177
z.config({ locale: localeMap[userLocale] || z.locales.en() });
178
179
return schema;
180
}
181
182
// API with localized errors
183
async function handleRequest(req: Request) {
184
const userLocale = req.headers.get('Accept-Language')?.split(',')[0] || 'en';
185
const locale = getLocale(userLocale);
186
187
const result = schema.safeParse(req.body, { errorMap: locale });
188
189
if (!result.success) {
190
return Response.json({
191
errors: result.error.format(),
192
}, { status: 400 });
193
}
194
195
return Response.json({ data: result.data });
196
}
197
198
// Form validation with user's language
199
function validateForm(formData: FormData, language: string) {
200
const locales: Record<string, any> = {
201
en: z.locales.en(),
202
es: z.locales.es(),
203
fr: z.locales.fr(),
204
};
205
206
const result = FormSchema.safeParse(
207
Object.fromEntries(formData.entries()),
208
{ errorMap: locales[language] || locales.en }
209
);
210
211
return result;
212
}
213
```
214
215
## Fallback Behavior
216
217
```typescript
218
// If locale is not set, English is used by default
219
const result = z.string().min(5).safeParse("abc");
220
// Error: "String must contain at least 5 character(s)"
221
222
// If invalid locale, falls back to default
223
z.config({ locale: undefined });
224
// Uses English (default)
225
```
226