Multilingual Configuration Guide
📚Multi-language document navigation
Choose the appropriate document based on your needs:
- 🚀 Get started quickly: i18n.md (current document) - Learn basic usage in 5 minutes
- 📖 Full User Guide: i18n-user-guide.md - Detailed user guide and best practices
- 🎯 Add new language: add-custom-locale.md - Tutorial on adding a custom language pack
- 🔄 Dynamic language switching: dynamic-locale.md - Dynamic language switching in API development
- 🌐 Front-end integration: frontend-i18n-guide.md - Front-end and back-end separation project integration guide
📖 Overview
schema-dsl supports full multi-language functionality, allowing you to customize translations of field labels and error messages.
Node.js Requirements: >=18.0.0
Default supported language file formats for directory loading (Node >=18):
.js (CommonJS language pack)
.cjs
.json
.jsonc
.json5
Recommendation: If your application is an type: module / ESM project, give priority to using .cjs, .json, .jsonc, .json5; .js is more suitable for CommonJS language pack files.
v2 current capabilities:
- ✅ Support parameterized language switching (no need to modify global state)
- ✅ Supports custom error messages (three formats)
- ✅ TypeScript type definitions are complete
- ✅ Directory recursive loading
.js/.cjs/.json/.jsonc/.json5
🚀 Quick start
Method 1: Dynamically specify the language during validation (recommended) ⭐
import { s, validate } from 'schema-dsl/pure';
const schema = s({ username: 'string:3-32!' });
// Use Chinese error message
const result = validate(schema, { username: 'ab' }, { locale: 'zh-CN' });
// message: "username cannot be less than 3 characters long"
// Use English error message
const result2 = validate(schema, { username: 'ab' }, { locale: 'en-US' });
// message: "username length must be at least 3"
Method 2: Use global configuration (backwards compatible)
import { Locale } from 'schema-dsl/pure';
//Set default language
Locale.setLocale('zh-CN');
// Subsequent validation will use Chinese error messages
const result = validate(schema, data);
📝 Built-in language support
schema-dsl has the following built-in language packages:
🎯 Advanced usage
Basic configuration
import { s, validate } from 'schema-dsl/pure';
import path from 'path';
import zhCN from './i18n/dsl/zh-CN.cjs';
import enUS from './i18n/dsl/en-US.cjs';
// ✅ Method 1: Load from directory (recommended)
s.config({
i18n: path.join(__dirname, 'i18n/dsl') // Node >=18: supports .js/.cjs/.json/.jsonc/.json5
});
// ✅ Method 2: Directly pass in the object
s.config({
i18n: {
'zh-CN': zhCN,
'en-US': enUS
}
});
Directory loading keeps .js / .cjs enabled by default for backwards compatibility. Those files are executed by Node, so use them only for trusted locale directories, or set codeLocaleFiles: 'deny' to load only .json, .jsonc, and .json5.
Directory structure
project/
├── i18n/
│ └── dsl/ # schema-dsl language pack directory
│ ├── zh-CN.cjs # CommonJS / ESM projects are stable
│ ├── en-US.jsonc # with comments/end comma
│ └── ja-JP.json5 # JSON5 style (optional)
Full example (i18n/dsl/zh-CN.cjs)
module.exports = {
// ========== Field labels ==========
'field.username': 'username',
'field.email': 'Email address',
'field.password': 'password',
'field.age': 'Age',
// ========== Override default error message ==========
'required': '{{#label}} is required',
'string.minLength': '{{#label}} cannot be less than {{#limit}} characters',
'string.maxLength': '{{#label}} cannot exceed {{#limit}} characters',
'string.enum': '{{#label}} must be one of the following values: {{#valids}}',
'number.base': '{{#label}} must be a numeric type',
'number.min': '{{#label}} cannot be less than {{#limit}}',
'number.max': '{{#label}} cannot be greater than {{#limit}}',
'boolean.base': '{{#label}} must be of Boolean type',
'enum': '{{#label}} must be one of the following values: {{#allowed}}',
// ========== Custom error message ==========
'custom.invalidEmail': 'The email format is incorrect, please re-enter',
'custom.emailTaken': 'This email address has been registered',
'custom.passwordWeak': 'The password is not strong enough'
};
🎯 How to use
1. Field label translation
const schema = s({
username: s('string:3-32!').label('field.username'),
email: s('email!').label('field.email')
});
const result = validate(schema, { username: 'ab' });
// Error message: "Username cannot be less than 3 characters long"
2. Override the default error message
// language pack
module.exports = {
'required': '{{#label}} must be filled in'
};
// Schema
const schema = s({ username: 'string!' });
validate(schema, {});
// Error message: "username must be filled in"
3. Customize error messages
const schema = s({
status: s('active|inactive').messages({
'enum': 'Status must be active or inactive'
})
});
4. Dynamic language switching
s.config({
i18n: {
'zh-CN': { 'required': '{{#label}} is required' },
'en-US': { 'required': '{{#label}} is required' }
}
});
//Default language (en-US)
validate(schema, data);
// switch to English
validate(schema, data, { locale: 'en-US' });
📋 Built-in error message key
Generic error
String error
Number error
Boolean error
Array error
Pattern error
For the complete list, please refer to: src/locales/zh-CN.ts
🔧 Advanced usage
Nested field labels
// language pack
module.exports = {
'field.address.city': 'city',
'field.address.street': 'street'
};
// Schema
const schema = s({
address: {
city: s('string!').label('field.address.city'),
street: s('string!').label('field.address.street')
}
});
Error message priority
- Field-level custom message -
.messages() method
- Schema-level tag -
.label() method
- Language pack custom message -
i18n Configuration
- Default Error Message - Built-in language pack
// Priority example
s.config({
i18n: {
'zh-CN': {
'required': 'Global required message' // Priority 3
}
}
});
const schema = s({
username: s('string!')
.label('username') // Priority 2
.messages({ 'required': 'Required' }) // Priority 1 (highest)
});
Multilingual best practices
1. Directory structure
project/
├── i18n/
│ └── dsl/
│ ├── zh-CN.cjs # Chinese
│ ├── en-US.cjs # English
│ ├── ja-JP.cjs # Japanese
│ └── index.js # Export tool
import zhCN from './zh-CN.cjs';
import enUS from './en-US.cjs';
import jaJP from './ja-JP.cjs';
export default {
'zh-CN': zhCN,
'en-US': enUS,
'ja-JP': jaJP
};
// use
import localeMessages from './i18n/dsl/index.js';
s.config({
i18n: localeMessages
});
3. Message reuse
// i18n/dsl/common.cjs
module.exports = {
required: '{{#label}} is required',
minLength: '{{#label}} cannot be less than {{#limit}} characters'
};
// i18n/dsl/zh-CN.cjs
import common from './common.cjs';
module.exports = {
...common,
'field.username': 'username',
'field.email': 'Email'
};
📊 Full example
User management system
import { s, validate } from 'schema-dsl/pure';
import path from 'path';
// Configure multiple languages
s.config({
i18n: path.join(__dirname, 'i18n/dsl')
});
//define Schema
const userSchema = s({
username: s('string:3-32!').label('field.username'),
email: s('email!').label('field.email'),
password: s('string:8-32!').label('field.password'),
age: s('number:18-120').label('field.age'),
role: s('admin|user|guest!').label('field.role')
});
// Validation (Chinese)
let result = validate(userSchema, {
username: 'ab',
email: 'invalid',
role: 'admin'
});
console.log(result.errors);
// [
// { path: 'username', message: 'The username cannot be less than 3 characters in length' },
// { path: 'email', message: 'The email address must be a valid email address' },
// { path: 'password', message: 'Password is required' }
// ]
// Validation (English)
result = validate(userSchema, {
username: 'ab'
}, { locale: 'en-US' });
console.log(result.errors[0].message);
// "username must be at least 3 characters"
🐛 FAQ
1. The language pack does not take effect?
Check these common causes first:
- The configuration key should be
i18n, not locales.
- The directory path should point to the folder that contains your locale files.
- The file name should be a locale code, such as
zh-CN.cjs or zh-CN.jsonc.
.js locale files should be CommonJS (module.exports). In ESM projects, prefer .cjs or .json*.
2. Is the error message still in English?
Cause: The current request does not explicitly pass in locale, or the global default language has not yet been switched to the language you expect.
// Method 1: Global settings
import { Locale } from 'schema-dsl/pure';
Locale.setLocale('zh-CN');
//Method 2: Specify during validation
validate(schema, data, { locale: 'zh-CN' });
3. Customized messages are not displayed?
Check Priority:
.messages()s( > ).label() > Language Pack > Default
// Error: label will be overwritten by messages
s('string!')
.label('username')
.messages({ 'required': 'required' }) // This takes effect
Corresponding sample file
Example entry: i18n.ts
Description: Overrides built-in locale switching, field-level message priority, and the minimum working path of custom locales.