alibaba / react-intl-universal

Internationalize React apps. Not only for Component but also for Vanilla JS.
1.33k stars 153 forks source link

Message with variable is not working #252

Closed DaCao closed 2 months ago

DaCao commented 2 months ago

I came across this following issue and couldn't figure out why:

in the root index.js file:

...
// Init intl to the default language Japanese.
initLocale(LANGUAGE_CODE.JAPANESE);
...

ReactDOM.render(
  <BrowserRouter>
    <MaterialUIControllerProvider>
        <App />
    </MaterialUIControllerProvider>
  </BrowserRouter>,
  document.getElementById('root')
);

and initLocale in defined as:

const initLocale = async (currentLocale) => {
  await intl.init({
    currentLocale,
    locales: {
      [LANGUAGE_CODE.ENGLISH]: require('locales/en-US.json'),
      [LANGUAGE_CODE.CHINESE]: require('locales/zh-CN.json'),
      [LANGUAGE_CODE.JAPANESE]: require('locales/ja-JP.json'),
    },
  });
};

in the code:

      {intl.get(
        'page_edit_modal_text_hint_next',
        { arg1: 'hahaha' }
      )}

and in the locale file of 'locales/ja-JP.json':

...
"page_edit_modal_text_hint_next": "現在選択されているすべての {arg1} 件の依頼に変更を適用いたします。よろしいでしょうか?",
...

Now, when the page renders, it is displaying:

現在選択されているすべての {arg1} 件の依頼に変更を適用いたします。よろしいでしょうか?

instead of :

現在選択されているすべての hahaha 件の依頼に変更を適用いたします。よろしいでしょうか?

why is the arg1 variable not working?

version: "react-intl-universal": "^2.11.1",

cwtuan commented 2 months ago

any warning message in console?

cwtuan commented 2 months ago

any warning message in console?

DaCao commented 2 months ago

any warning message in console?

@cwtuan

There are warning messages like:

react-intl-universal locales data "null" not exists. More info: https://github.com/alibaba/react-intl-universal/issues/144#issuecomment-1345193138

but they point to a completely different place in the code. I don't think this warning message is relavent to my question. In the code:

{intl.get(
        'page_edit_modal_text_hint_next',
        { arg1: 'hahaha' }
      )}

intl.get() is able to get the right text, which is "現在選択されているすべての {arg1} 件 .... "; however, it failed to fill in the arg1 variable.

cwtuan commented 2 months ago

I can't reproduce this issue.

You could try it: https://npm.runkit.com/react-intl-universal

require("react/package.json"); // react is a peer dependency. 
const intl = require("react-intl-universal")
intl.init({
    currentLocale:'jp',
    locales: {
     "jp": {
        "page_edit_modal_text_hint_next": "現在選択されているすべての {arg1} 件の依頼に変更を適用いたします。よろしいでしょうか?",
     }
    },
  });

console.log('intl',  intl.get('page_edit_modal_text_hint_next', { arg1: 'hahaha' } ))

image

DaCao commented 2 months ago

@cwtuan Thank you for the fast response!

I tried this:

const initLocale = async (currentLocale) => {
  await intl.init({
    currentLocale,
    locales: {
      [LANGUAGE_CODE.ENGLISH]: require('locales/en-US.json'),
      [LANGUAGE_CODE.CHINESE]: require('locales/zh-CN.json'),
      [LANGUAGE_CODE.JAPANESE]: require('locales/ja-JP.json'),
    },
  });
  console.log('Locale data:', intl.options.locales);
  console.log('Locale initialized');
  console.log(
    intl.get('page_edit_modal_text_hint_next', {
      arg1: 'hahaha',
    })
  );
};

and was able to print the correct text:

現在選択されているすべての hahaha 件の依頼に変更を適用いたします。よろしいでしょうか?

Back to the root index.js file:

...
// Init intl to the default language Japanese.
initLocale(LANGUAGE_CODE.JAPANESE);
console.log(' === pass initLocale ');
...

ReactDOM.render(
  <BrowserRouter>
    <MaterialUIControllerProvider>
        <App />
    </MaterialUIControllerProvider>
  </BrowserRouter>,
  document.getElementById('root')
);

the string:

=== pass initLocale

was printed before the Locale initialized strings was printed.

Perhaps it is because the rendering started before initLocal was able to finish execution.

but I am not sure how to fix this issue

cwtuan commented 2 months ago

The render should start after the app is initialized:

Example: https://github.com/alibaba/react-intl-universal/blob/master/packages/react-intl-universal/examples/nextjs-example/pages/index.tsx#L100

DaCao commented 2 months ago

@cwtuan thank you for your reply. I tried the following:

the helper function:

const initLocale = async (currentLocale) => {
  await intl.init({
    currentLocale,
    locales: {
      [LANGUAGE_CODE.ENGLISH]: require('locales/en-US.json'),
      [LANGUAGE_CODE.CHINESE]: require('locales/zh-CN.json'),
      [LANGUAGE_CODE.JAPANESE]: require('locales/ja-JP.json'),
    },
  });
  console.log('Locale initialized');
  console.log(
    intl.get('page_edit_modal_text_hint_next', {
      arg1: 'hahaha',
    })
  );
};

in the root index.js:

const AppWrapper = () => {
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const initialize = async () => {
      await initLocale(LANGUAGE_CODE.JAPANESE);
      setLoading(false);
    };
    initialize();
  }, []);

  if (loading) {
    return <></>;
  }

  console.log(' === pass initLocale 1');
  console.log(
    intl.get('kenshin_kanban_case_batch_edit_modal_text_hint_next', {
      arg1: 'hahaha',
    })
  );

  return (
    <BrowserRouter>
      <MaterialUIControllerProvider>
          <App />
      </MaterialUIControllerProvider>
    </BrowserRouter>
  );
};

ReactDOM.render(<AppWrapper />, document.getElementById('root'));

in :

const App = () => {

...

    console.log(' === pass initLocale 2');
    console.log(
      intl.get('page_edit_modal_text_hint_next', {
        arg1: 'hahaha',
      })
    );
    return (
      <BaseApp>
        <Dashboard currentUser={currentUser} />
      </BaseApp>
    );
}

export default App;

As soon as you get inside the <Dashboard /> component, there is:

const Dashboard = () => {

  ... 

  console.log(' === pass initLocale 3');
  console.log(
    intl.get('page_edit_modal_text_hint_next', {
      arg1: 'hahaha',
    })
  );

 return (
 ....
)

Now, from the console print messages:

Locale initialized 現在選択されているすべての hahaha 件の依頼に変更を適用いたします。よろしいでしょうか? === pass initLocale 1 現在選択されているすべての hahaha 件の依頼に変更を適用いたします。よろしいでしょうか? === pass initLocale 2 現在選択されているすべての hahaha 件の依頼に変更を適用いたします。よろしいでしょうか?

=== pass initLocale 3 現在選択されているすべての {arg1} 件の依頼に変更を適用いたします。よろしいでしょうか?

I don't see why it was successful in the level of <App /> , but failed at the <Dashboard /> level.

Could you please take a look and offer some suggestions?

DaCao commented 2 months ago

I have found the problem. It was very silly: I accidentally loaded locales the again in the component:

const Dashboard = () => {

  ...
  // somewhere in the code, the init step is called again without await. Deleting this line fixed the bug! 
  initLocale()

  ... 

  console.log(' === pass initLocale 3');
  console.log(
    intl.get('page_edit_modal_text_hint_next', {
      arg1: 'hahaha',
    })
  );

 return (
 ....
)

Thank you @cwtuan !!

This issue can be closed now