gcanti / tcomb-validation

Validation library based on type combinators
MIT License
400 stars 23 forks source link

Localization support in `getValidationErrorMessage`? #27

Closed th0r closed 9 years ago

th0r commented 9 years ago

Hi and thanks for the great lib!

I have one question though: what is the proper way to return localized error messages from getValidationErrorMessage function?

The problem is I have to pass user's locale into this function somehow in order to return proper error message and the only solution I found now is to construct one struct per locale (but I don't like it):

// ./structs/ShortString.js

const _ = require('lodash');
const t = require('tcomb');

const intl = require('./intl');

module.exports = _.memoize(locale => {
    const ShortString = t.subtype(t.String, s => s.length < 3);

    ShortString.getValidationErrorMessage = value => {
        if (!value) {
            return intl(locale, 'Required');
        }

        if (value.length >= 3) {
            return intl(locale, 'Too long my friend');
        }
    };

    return ShortString;
});

// Some Express.js middleware
const ShortString = require('./structs/ShortString');

app.use((req, res) => {
    const locale = getUserLocale(req);

    const validationResult = validate(req.query.str, ShortString(locale));
});

The other solution could be is to pass an external options (or context) argument to validate(). Then this example would look like this:

// ./structs/ShortString.js

const _ = require('lodash');
const t = require('tcomb');

const intl = require('./intl');

const ShortString = t.subtype(t.String, s => s.length < 3);

ShortString.getValidationErrorMessage = (value, context) => {
    const { locale } = context;

    if (!value) {
        return intl(locale, 'Required');
    }

    if (value.length >= 3) {
        return intl(locale, 'Too long my friend');
    }
};

module.exports = ShortString;

// Some Express.js middleware
const ShortString = require('./structs/ShortString');

app.use((req, res) => {
    const locale = getUserLocale(req);

    const validationResult = validate(req.query.str, ShortString, { locale });
});

What do you think about it?

gcanti commented 9 years ago

Hi, the current signature is

validate(value, type, [path]) -> ValidationResult

What about replacing the path argument with a context argument?

validate(value, type, [context]) -> ValidationResult

where getValidationErrorMessage will have the following signature:

getValidationErrorMessage(value, path, context)

Note.

th0r commented 9 years ago

@gcanti The only concern I have is that path is an option, while context values are not. So, maybe something like this?

validate(value, type, [options]) -> ValidationResult

options (optional) is an object with the following keys:

options can be an array (as path prefix) for backward compatibility

gcanti commented 9 years ago

:+1:

gcanti commented 9 years ago

Just published v2.2.0 https://github.com/gcanti/tcomb-validation/releases/tag/v2.2.0 Let me know if everything's ok Giulio

th0r commented 9 years ago

@gcanti Incredible speed, man! Thanks!

th0r commented 9 years ago

@gcanti It would be great to add context support to tcomb-form.

gcanti commented 9 years ago

@th0r https://github.com/gcanti/tcomb-form/issues/197