Skip to content

Make i18n a real AJV plugin #153

Open
@ggondim

Description

@ggondim

Implementation proposal

Considering ajv-i18n's localization function already mutates the errors object:

errorsText()

When using ajv-i18 as a plugin, the ajv.errorsText() function should return the localized error messages.

Currently we need to hack the errors object and then call errorsText().

I propose expose a initialization function in ajv-i18n, just like other plugins, so this function could replace the errorsText() by its localized method.

// @param {Ajv} ajv An Ajv instance
function initialize(ajv) {

  ajv._errorsText = ajv.errorsText;

  // intercepts errorsText function
  ajv.errorsText = (errors) => {
    localize(errors);
    return ajv._errorsText(errors);
  }

}

So, this initialization could be used like other plugins (ajv-keywords example):

require('ajv-i18n')(ajv);

Here is a working Run-Kit running this example.

errors

If the localize method already converts all errors messages in validate.errors , the plugin could also replace errors by a getter/setter that does this conversion:

function initialize(ajv, locale) {

  ajv._compile = ajv.compile;

  // intercepts compile function
  ajv.compile = schema => {
    const validate = ajv._compile(schema);
    Object.defineProperty(validate, 'errors', makeLocalizedErrors(ajv));
    return validate;
  }

}

function makeLocalizedErrors(ajv) {
  return {
    get: () => {
      return ajv._errors;
    },
    set: (errors) => {
      ajv._errors = localize(errors);
    },
    configurable: true
  };
}

Considerations about the existent implementation

What would happen to the current localize function in module.exports?

To work like other AJV's plugins, the current module.exports needs to be changed to the proposed initialization function, that would lead to a breaking change (major version).

But the current localization function exported in localize.jst could be exported as a property of the initialization function, just like ajv-keywords does with the get() function.

module.exports = initialize;

function initialize(ajv) {
  // ... initialize function as defined above
}

initialize.localize = localize;

function localize(errors) {
   // current exported function in module.exports
}

If you don't want to make a breaking change, at least approve the inverse

The inverse could be made, so this plugin injection could be:

module.exports = localize;

function localize(errors) {
   // current exported function in module.exports
}

function initialize(ajv) {
  // ... initialize function as defined above
}

localize.localize = initialize;

... used as:

const { localize } = require('ajv-i18n');
localize(ajv);

When can I make a pull request?

If this implementation design is approved, I start to code it and in a few hours I make a pull request.

Looking forward to a special reply from the most active member, @epoberezkin 🤓

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions