React-intl for non components

后端 未结 5 2049
醉酒成梦
醉酒成梦 2021-02-05 17:14

Currently I have the following code to expose react-intl to non-components, but it throws an error for intl as undefined.

I have created a separate component as \'Curren

相关标签:
5条回答
  • 2021-02-05 17:14

    There's a new way to do it pretty easily with createIntl, it returns an object that you can use outside React components. Here's an example from the documentation.

    import {createIntl, createIntlCache, RawIntlProvider} from 'react-intl'
    
    // This is optional but highly recommended
    // since it prevents memory leak
    const cache = createIntlCache()
    
    const intl = createIntl({
      locale: 'fr-FR',
      messages: {}
    }, cache)
    
    // Call imperatively
    intl.formatNumber(20)
    
    // Pass it to IntlProvider
    <RawIntlProvider value={intl}>{foo}</RawIntlProvider>
    

    I personally store the intl object in Redux store so I can access it everywhere in my app.

    0 讨论(0)
  • 2021-02-05 17:17

    There's also another approach very simple I used for solving a similar problem: Provide access to the intl object for a non-component:

    import { IntlProvider, addLocaleData } from 'react-intl';
    import localeDataDE from 'react-intl/locale-data/de';
    import localeDataEN from 'react-intl/locale-data/en';
    import { formMessages } from '../../../store/i18n'; // I defined some messages here
    import { Locale } from '../../../../utils'; //I set the locale fom here
    
    addLocaleData([...localeDataEN, ...localeDataDE]);
    const locale = Locale.setLocale(); //my own methods to retrieve locale
    const messages = Locale.setMessages(); //getting messages from the json file.
    const intlProvider = new IntlProvider({ locale, messages });
    const { intl } = intlProvider.getChildContext();
    
    export const SCHEMA = {
      salutation: {
        label: intl.formatMessage(formMessages.salutationLabel),
        errormessages: {
          required: intl.formatMessage(formMessages.salutationError),
        },
      },
      academic_title_code: {
        label: intl.formatMessage(formMessages.academicTitleLabel),
      },
    };
    

    It's working like a charm!

    UPDATE for v3.x

    After migration to react-intl 3.x

    import { createIntl, createIntlCache } from 'react-intl'
    import { formMessages } from '../../../store/i18n'; // I defined some messages here
    import { Locale } from '../../../../utils'; //I set the locale fom here
    
    const locale = Locale.setLocale(); //my own methods to retrieve locale
    const messages = Locale.setMessages(); //getting messages from the json file.
    // This is optional but highly recommended
    // since it prevents memory leak
    const cache = createIntlCache();
    const intl = createIntl({ locale, messages }, cache)
    
    export const SCHEMA = {
      salutation: {
        label: intl.formatMessage(formMessages.salutationLabel),
        errormessages: {
          required: intl.formatMessage(formMessages.salutationError),
        },
      },
      academic_title_code: {
        label: intl.formatMessage(formMessages.academicTitleLabel),
      },
    };
    
    0 讨论(0)
  • 2021-02-05 17:24

    There's also another way solving a similar problem to used react-intl formatMessage for non-components.

    Create a LocaleStore.js store file.

     import _formatMessage from "format-message";
    
        export default class LocaleStore {
    
          formatMessage = (id, values) => {
            if (!(id in this.messages)) {
              console.warn("Id not found in intl list: " + id);
              return id;
            }
            return _formatMessage(this.messages[id], values);
          };
        }
    

    import LocaleStore your CombinedStores.js

    import LocaleStore from "./stores/LocaleStore";
    import en from "./translations/en";
    import de from "./translations/de";
    import Global from "./stores/global"
    const locale = new LocaleStore("en", {
      en,
      de
    });
    export default {
    global:new Global(locale) 
    }
    

    now you can use this in your GlobalStore.js

        class GlobalStore {
        constructor(locale) {
         this.locale = locale;
        }
    
       formatMessage=(message_is,formatLanguage="en")=> {
         return  this.locale.formatMessage(message_id, formatLanguage);
        }
      }
    
    0 讨论(0)
  • 2021-02-05 17:35

    If you can accept to use a function component I prefer to use the useIntl hook

    https://reactjs.org/docs/components-and-props.html#function-and-class-components

    I can then get values like this:

    import { useIntl } from "react-intl";
    
    const intl = useIntl()
    intl.formatMessage({ id: 'myId' }),
    

    https://formatjs.io/docs/react-intl/api/#useintl-hook

    0 讨论(0)
  • 2021-02-05 17:39

    This line: const { intl } = this.context.intl; should be const { intl } = this.context;

    Here is a reference post of someone doing almost the exact same thing as you are: https://github.com/yahoo/react-intl/issues/983#issuecomment-342314143

    In the above the author is creating essentially a singleton that is exported instead of creating a new instance each time like you have above. This might be something you want to consider as well.

    0 讨论(0)
提交回复
热议问题