2

I'm currently working with React-intl v. ^4.7.6. I have a folder called translations where all my locale translations are in. I use IntlProvider to select which file to load based on the user's browser. It seems like FormatttedMessage or intl.formatMessage can't do this.

Here is what my translation file looks like. Of course, there would be one for every language. transtions/eng.json

{
  "header.about": "About",
  "header.resume": "Resume",
  "Education": [{
    "school": "ABC University",
    "degree": "(B.Eng)",
    "graduated": "2030 - Present",
    "location": "Canada",
    "description": [
      "d1",
      "d2"
    ]
  },
    {
      "school": "College",
      "degree": "Science",
      "graduated": "2030",
      "location": "Canada",
      "description": [
        "Graduated with honors"
      ]
    }]

[... other translations ...]
}
bobob
  • 103
  • 1
  • 9
  • Does this [one](https://stackoverflow.com/a/45662052/9449426) help you? Are you using CRA or/and typescript? – NearHuscarl Aug 24 '20 at 03:53
  • I'm using typescript but unfortunately this is not helping. The Json file is loaded by `IntlProvider` based on the user's browser language – bobob Aug 24 '20 at 13:08
  • If you're using typescript, check if you have `resolveJsonModule` set to true in your `tsconfig.json` – NearHuscarl Aug 24 '20 at 13:31

1 Answers1

0

I have another approach to resolve your problem. (Though it might not be the best solution and it is not exactly using your en/ german translate, but i think they are similar)

First we can define a file with all localization keys:

// i18n/keys.js 
export const student = {
 
  projects: [
    {
      name: "student.projects.0.name",
      desc: "student.projects.0.desc",
    },
    {
      name: "student.projects.1.name",
      desc: "student.projects.1.desc",
    },
  ],
};

export const localizationKeys = {
  student: student,
};

In i18n locale files, we can define the translations as below:

// i18n/en/student.js
export const student = {
  projects: [
    {
      name: "Camera",
      desc: "Photo",
    },
    {
      name: "Foods",
      desc: "Apple",
    },
  ],
};

// i18n/zh_tw/student.js
export const student = {
  projects: [
    {
      name: "拍攝",
      desc: "照片",
    },
    {
      name: "食物",
      desc: "蘋果",
    },
  ],
};

Export the translations in i18n to locale modules for react-i18n

// i18n/en/index.js
import { student } from "./student";

const en = {
  general: general,
};

export default en;

// i18n/zh_tw/index.js
import { student } from "./student";

const zh_tw = {
  student: student,
};

export default zh_tw;

In your react components, you can access your localization Keys (keys.js) to get back each of the i18n keys name.

import React from "react";
import { useIntl } from "react-intl";
import { localizationKeys } from "./i18n/keys";
import { IntlProvider } from "react-intl";
import zh_tw from "./i18n/zh_tw";
import flatten from "flat";
import en from "./i18n/en";

const messages = {
  en: flatten(en),
  "zh-Hant-TW": flatten(zh_tw),
};

export default function ProjectShowcase() => {
  const intl = useIntl();
  const [locale, setLocale] = useState(navigator.language);
  const [mergedMessages, setMergedMessages] = useState(messages["en"]);

  useEffect(() => {
    // Merging english and current locale, avoid showing Text id if cannot look for the translate in locale file
    // In this case, it will always show EN translate as default if the text-id not found in a "zh_tw" locale
    setMergedMessages(Object.assign({}, messages["en"], messages[locale]));
  }, [locale]);
  
  return (
  <IntlProvider
      messages={mergedMessages}
      locale={locale}
      key={locale}
      defaultLocale="en"
    >
    {localizationKeys.student.projects.map((p, idx) => {
        return (
          <ul>
            <li>
              <span>
                {intl.formatMessage({
                  id: localizationKeys.student.projects[idx].name,
                })}
              </span>
              {` (${intl.formatMessage({
                id: localizationKeys.student.projects[idx].desc,
              })})`}
            </li>
          </ul>
        );
      })
    }
 </IntlProvider>
  )
}

I have developed a little example on the react-intl, you may find more completed code inside: https://github.com/applelok/react-localization

appletabo
  • 239
  • 2
  • 12
  • TL:DR Refactor out arrays outside locale files to obtain similar behavior. Too much work, imo. – Ferit Jul 15 '21 at 12:22