Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom rule: cannot display localized message #2426

Closed
saibotk opened this issue Oct 16, 2019 · 5 comments · Fixed by #2545
Closed

Custom rule: cannot display localized message #2426

saibotk opened this issue Oct 16, 2019 · 5 comments · Fixed by #2545
Labels
🐛 bug Unintended behavior

Comments

@saibotk
Copy link

saibotk commented Oct 16, 2019

Versions

  • vee-validate: 3.0.11
  • vue: 2.6.10

Describe the bug
I cannot seem to add localized messages via the localize() function for custom rules. Instead it will display the generic input is not valid message. I tried everyway of registering the language message, but there just is no way to get the rule return the localized message (not using any other l18n solution, just the internal vee-validate localization).

To reproduce
This is my registration of the custom rule, which does not define a static message (!) (note i also tried all forms of the localize() function (and i suggest to review the documentation, since it is, at least to me, still not clear how this function operates with each input).

import Vue from 'vue';
import _ from 'lodash';
import { ValidationProvider, ValidationObserver, localize, extend } from 'vee-validate/dist/vee-validate.full';
import rules from './rules';
import de from 'vee-validate/dist/locale/de.json';
import deInternal from './lang/de.json';
import enInternal from './lang/en.json';

extend('required_if_empty', rules.required_if_empty);

var mergedDE = _.merge({}, de, deInternal);

// Set vee-validate language
localize({
  en: enInternal,
  de: mergedDE,
});
localize('de');

Vue.component('ValidationObserver', ValidationObserver);
Vue.component('ValidationProvider', ValidationProvider);

Expected behavior
I expect the rule to use the current localized message.

Thank you.

PS: Referencing #2318 here, since it would also lead to the same error, i suppose.

@Anton-Evstigneev
Copy link

Anton-Evstigneev commented Nov 6, 2019

The sourse of the bug is in the init logic: for vee-validate.full.js

2615: // Install locale
2616: localize('en', en);

After this initial call, updateRules() method will never be called again as INSTALLED flag is already set to true:

  var INSTALLED = false;
  function updateRules() {
      if (INSTALLED) {
          return;
      }
      RuleContainer.iterate(function (name, schema) {
          var _a, _b;
          if (schema.message && !DICTIONARY.hasRule(name)) {
              DICTIONARY.merge((_a = {},
                  _a[DICTIONARY.locale] = {
                      messages: (_b = {},
                          _b[name] = schema.message,
                          _b)
                  },
                  _a));
          }
          extend(name, {
              message: function (field, values) {
                  return DICTIONARY.resolve(field, name, values || {});
              }
          });
      });
      INSTALLED = true;
  }
  function localize(locale, dictionary) {
      var _a;
      if (!DICTIONARY) {
          DICTIONARY = new Dictionary('en', {});
      }
      if (typeof locale === 'string') {
          DICTIONARY.locale = locale;
          if (dictionary) {
              DICTIONARY.merge((_a = {}, _a[locale] = dictionary, _a));
          }
          updateRules();
          return;
      }
      DICTIONARY.merge(locale);
      updateRules();
  }

To overcome i used this code to explicitly rewrite translation string for each rule:

Object.keys(newLocaleMessages).forEach(
    ruleName => {
        extend(ruleName, {
            message: newLocaleMessages[ruleName]
        });
    }
);

@saibotk
Copy link
Author

saibotk commented Dec 8, 2019

@logaretm Are you going to take a look at this?

@rangermeier
Copy link

Also, it would be nice, if we could load localizations once and they are picked up by rules that are extend()ed later on somewhere in the app.

As far as I understand, currently l10n messages are only applied to rules that are already registered. But due to this bug it's not possible to re-invoke localize() each time a rule is added.

@logaretm logaretm added the 🐛 bug Unintended behavior label Dec 13, 2019
logaretm added a commit that referenced this issue Dec 13, 2019
…les (#2545)

* fix: make the internal dictionary set itself as the default message handler closes #2426

* docs: added note to docs on localization and defaultMessage conflict

* chore: remove unused function from extend
@saibotk
Copy link
Author

saibotk commented Dec 13, 2019

Thanks 👍

@nicolasigot
Copy link

Hi @logaretm ,
I noticed today an issue following this fix. The issue is when I use the configure method with defaultMessage property and then call localize for the first time.
In this case, the defaultMessage method is replaced by the one you added when you create the DICTIONARY.

image

Is there any way to keep the defaultMessage method if already configured ?
The only workaround I found is to call localize method the first time before the configure method.

Thanks for your feedback,
Nicolas

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Unintended behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants