Есть ли способ перевести ограничения валидации в формы React?

Я использую response-i18next для интернационализации, и я не могу найти никаких встроенных способов перевода ограничений валидации в формы React. Язык сообщений формы зависит от языка браузера и не меняется, если пользователь выбирает другой язык на моем сайте.

Пример снимка экрана - посмотрите, как страница на английском языке, но сообщение об ограничении все еще отображается Голландский.

Есть ли способ сделать так, чтобы сообщения об ограничениях проверки зависели от языковых файлов cookie для переводов? А может их можно перевести с помощью response-i18next?

i18n.js:

import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from 'i18next-browser-languagedetector';

const resources = {
  en: {
    translation: {
      "Name": "Name",
      "Count": "Count",
      "New object": "New object",
      ...,
    }
  },
  nl: {
    translation: {
      "Name": "Naam",
      "Count": "Telling",
      "New object": "Nieuw object",
      ...,
    }
  }
};

i18n
  .use(LanguageDetector)
  .use(initReactI18next) // passes i18n down to react-i18next
  .init({
    resources,
    fallbackLng: "en",
    debug: false,

    keySeparator: false,

    interpolation: {
      escapeValue: false
    },
    detection: {
      // order and from where user language should be detected
      order: ['cookie', 'querystring', 'localStorage', 'navigator', 'htmlTag', 'path', 'subdomain'],

      // keys or params to lookup language from
      lookupQuerystring: 'lng',
      lookupCookie: 'language',
      lookupLocalStorage: 'i18nextLng',
      lookupFromPathIndex: 0,
      lookupFromSubdomainIndex: 0,

      // cache user language on
      caches: ['localStorage', 'cookie'],
      excludeCacheFor: ['cimode'], // languages to not persist (cookie, localStorage)

      // optional expire and domain for set cookie
      cookieMinutes: 10,
      cookieDomain: 'myDomain',

      // optional htmlTag with lang attribute, the default is:
      htmlTag: document.documentElement
    }
  });

Форма реакции:

handleChange = (event) =>  {
    const name = event.target.name;
    const value = event.target.value;
    this.setState(prevstate => {
      const newState = { ...prevstate };
      newState[name] = value;
      return newState;
    });
  } 

render() {
   const { t } = this.props;
   return (
     <>
        <form onSubmit={(e) => this.newObjectHandler(e)}>
          <p>
              <label htmlFor="name">{t("Name")}: </label>
              <input
                type="text"
                name="name"
                minLength="6"
                maxLength="40"
                value={this.state.name}
                onChange={this.handleChange}
                required
              />
          </p>
          <p>
              <label htmlFor="count">{t("Count")}: </label>
              <input
                type="number"
                name="count"
                min="0"
                max="100"
                step="1"
                value={this.state.count}
                onChange={this.handleChange}
                required
              />
          </p>
          <p>
          <input type="submit" value={t("New object")} />
          </p>
        </form>
     </>
   )
 }

person warpfactorten    schedule 13.08.2019    source источник
comment
Можете поделиться кодом?   -  person felixmosh    schedule 13.08.2019
comment
@felixmosh Я не уверен, какой код добавить, но я добавил свой код i18n.js и код с формой.   -  person warpfactorten    schedule 13.08.2019
comment
где твои сообщения об ошибках?   -  person felixmosh    schedule 13.08.2019
comment
@felixmosh сообщений об ошибках нет. Я добавил в свой пост фрагмент скриншота, который должен лучше объяснить проблему.   -  person warpfactorten    schedule 14.08.2019
comment
Ха, как говорится картинка стоимостью 1000 слов,;) напишу ответ через мин   -  person felixmosh    schedule 14.08.2019
comment
Каков точный ожидаемый поток или последовательность событий? Какая часть этого не работает?   -  person Pavel Ye    schedule 06.09.2019


Ответы (1)


Судя по вашему изображению, вы используете собственные сообщения об ошибках браузера.

Чтобы перевести их, вы можете использовать setCustomValidity.

Это выглядело бы так:

render() {
  const { t } = this.props;
  return (
    <>
      <form onSubmit={e => this.newObjectHandler(e)}>
        <p>
          <label htmlFor="name">{t('Name')}: </label>
          <input
            type="text"
            name="name"
            minLength="6"
            maxLength="40"
            value={this.state.name}
            onChange={this.handleChange}
            data-message={t('YOUR_MESSAGE_KEY_HERE')}
            onInvalid={this.handleValidity}
            required
          />
        </p>
        <p>
          <label htmlFor="count">{t('Count')}: </label>
          <input
            type="number"
            name="count"
            min="0"
            max="100"
            step="1"
            value={this.state.count}
            onChange={this.handleChange}
            data-message={t('YOUR_MESSAGE_KEY_HERE_2')}
            onInvalid={this.handleValidity}
            required
          />
        </p>
        <p>
          <input type="submit" value={t('New object')} />
        </p>
      </form>
    </>
  );
};

handleValidity = ({target}) => {
  const message = target.dataset.message;
  target.setCustomValidity(message);
}

Я добавил переведенное сообщение к атрибуту data-message, затем прикрепил событие onInvalid к атрибуту input и инициировал setCustomValidity на нем с сообщением.

person felixmosh    schedule 14.08.2019