项目作者: devakone

项目描述 :
A set of helper hooks and components to use with i18next, react-i18next and Formik
高级语言: JavaScript
项目地址: git://github.com/devakone/react-i18next-helpers.git
创建时间: 2019-06-12T19:58:24Z
项目社区:https://github.com/devakone/react-i18next-helpers

开源协议:MIT License

下载


react-i18next-helpers

A set of helper hooks and components to use with i18next, react-i18next and Formik; i18next makes translating a breeze in apps, and using the react-i18next opens up the API for most React Applications. However, there are blind spots like with any other libraries. These helpers are here to help you cover these blind spots.

Using Formik and translating errors

If you use Formik and you have errors rendered on the screen, you will notice that if you change the current language, your errors remain in the language they were before the translation. This library gives you a hook you can use to make sure that when the i18n language changes, your form errors are also translated.

Render Example

This example is based on using the render method for rendering a Formik form

  1. ...
  2. <Formik component={ContactForm} ></Formik>;
  3. ...
  4. import useTranslateFormErrors from '../../hooks/use-translate-form-errors';
  5. const ContactForm = ({
  6. handleSubmit,
  7. handleChange,
  8. handleBlur,
  9. values,
  10. errors,
  11. touched,
  12. setFieldTouched
  13. }) => {
  14. useTranslateFormErrors(errors, touched, setFieldTouched);
  15. return (
  16. <form onSubmit={handleSubmit}>
  17. <input
  18. type="text"
  19. onChange={handleChange}
  20. onBlur={handleBlur}
  21. value={values.name}
  22. name="name"
  23. />
  24. {errors.name && <div>{errors.name}</div>}
  25. <button type="submit">Submit</button>
  26. </form>
  27. );
  28. }

Just passing the errors, touched, and setFieldTouched FormikProps to the hook in your render method ensures that your errors will get translated if the language changes.

HOC Example

  1. <Formik
  2. render={({ handleSubmit, handleChange, handleBlur, setFieldTouched, values, errors, touched }) => (
  3. <WithTranslateFormErrors errors={errors} touched={touched} setFieldTouched={setFieldTouched}>
  4. <form onSubmit={handleSubmit}>
  5. <input
  6. type="text"
  7. onChange={handleChange}
  8. onBlur={handleBlur}
  9. value={values.name}
  10. name="name"
  11. />
  12. {errors.name &&
  13. <div>
  14. {errors.name}
  15. </div>}
  16. <button type="submit">Submit</button>
  17. </form>
  18. </WithTranslateFormErrors>
  19. )}
  20. />
  21. import PropTypes from 'prop-types';
  22. import React, { useEffect } from 'react';
  23. import { useTranslation } from 'react-i18next';
  24. const useTranslateFormErrors = (errors, touched, setFieldTouched) => {
  25. const { i18n } = useTranslation();
  26. useEffect(() => {
  27. i18n.on('languageChanged', lng => {
  28. Object.keys(errors).forEach(fieldName => {
  29. if (Object.keys(touched).includes(fieldName)) {
  30. setFieldTouched(fieldName);
  31. }
  32. });
  33. });
  34. return () => {
  35. i18n.off('languageChanged', lng => {});
  36. };
  37. }, [errors]);
  38. };
  39. const WithTranslateFormErrors = ({ errors, touched, setFieldTouched, children }) => {
  40. useTranslateFormErrors(errors, touched, setFieldTouched);
  41. return <>{children}</>;
  42. };
  43. WithTranslateFormErrors.propTypes = {
  44. form: PropTypes.object
  45. };
  46. export default WithTranslateFormErrors;

Just passing the errors, touched, and setFieldTouched FormikProps to the HOC in your render method ensures that your errors will get translated if the language changes.

Translating raw or dynamic HTML

If you’re ever in need of translating HTML you’re adding dynamically to your app, and to keep content in that HTML translated, you can use the useTranslateHtmlElement hook.

  1. import dompurify from 'dompurify';
  2. import useTranslateHtmlElement from './use-translate-html-element';
  3. // Our safe HTML rendering component
  4. // From https://dev.to/jam3/how-to-prevent-xss-attacks-when-using-dangerouslysetinnerhtml-in-react-1464
  5. function SafeHTMLComponent() {
  6. // title is dynamic HTML
  7. const title = response.from.backend.title;
  8. // sanitizer will sanitize the HTML
  9. const sanitizer = dompurify.sanitize;
  10. const safeTitle = sanitizer(title);
  11. const [ref] = useTranslateHtmlElement(safeTitle);
  12. return
  13. import React, { useEffect, useState } from 'react';
  14. import { useTranslation } from 'react-i18next';
  15. const translateI18nTokensInHtmlElement = (i18n, htmlElement) => {
  16. const i18nTokenNodes = htmlElement.querySelectorAll('[data-i18n]');
  17. for (let i = 0; i < i18nTokenNodes.length; i++) {
  18. i18nTokenNodes[i].innerHTML = i18n.t(i18nTokenNodes[i].getAttribute('data-i18n'));
  19. }
  20. };
  21. const useTranslateHtmlElement = html => {
  22. const { i18n } = useTranslation();
  23. const [node, setRef] = useState(null);
  24. const translateIfNodeRendered = node => {
  25. if (node) {
  26. translateI18nTokensInHtmlElement(i18n, node);
  27. }
  28. };
  29. useEffect(() => {
  30. translateIfNodeRendered(node);
  31. i18n.on('languageChanged', lng => {
  32. translateIfNodeRendered(node);
  33. });
  34. return () => {
  35. i18n.off('languageChanged', lng => {});
  36. };
  37. }, [html]);
  38. return [setRef];
  39. };
  40. export default useTranslateHtmlElement;

The example is self explanatory.