diff --git a/.babelrc b/.babelrc index f814ba282..c7bacd749 100644 --- a/.babelrc +++ b/.babelrc @@ -13,10 +13,8 @@ ], "plugins": [ "@emotion", - "@babel/proposal-optional-chaining", - "@babel/proposal-nullish-coalescing-operator", "@babel/plugin-transform-typescript", - "react-intl-auto" + "react-intl-auto" // delete when migration to i18next is complete ], "env": { "test": { @@ -32,4 +30,4 @@ ] } } -} \ No newline at end of file +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a9000b09..6a7bd2dd9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: steps: - uses: actions/setup-node@v2 with: - node-version: '14.x' + node-version: "14.x" - name: Checkout uses: actions/checkout@v2 - name: Get yarn cache directory path @@ -33,6 +33,8 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage/lcov.info + - name: Check translations + run: yarn run i18n --fail-on-update slack-notification: if: always() name: Slack Notification diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index e583cf5e7..b39d657c5 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -7,7 +7,7 @@ import { } from "@apollo/client"; import React, { ReactElement } from "react"; -import { Provider as IntlProvider } from "../src/locale"; +import { Provider as I18nProvider } from "../src/i18n"; import { Provider as ThemeProvider } from "../src/theme"; import { Provider as DndProvider } from "../src/util/use-dnd"; @@ -31,9 +31,9 @@ export const decorators = [ (storyFn: () => ReactElement) => ( - + {storyFn()} - + ), diff --git a/i18next-parser.config.js b/i18next-parser.config.js new file mode 100644 index 000000000..4b46645a5 --- /dev/null +++ b/i18next-parser.config.js @@ -0,0 +1,6 @@ +module.exports = { + locales: ["en", "ja"], + output: "src/i18n/translations/$LOCALE.yml", + input: ["src/**/*.{ts,tsx}"], + useKeysAsDefaultValue: true, +}; diff --git a/package.json b/package.json index f0a48504a..8af0c4511 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,9 @@ "storybook:screenshot": "storycap --serverCmd 'npx http-server ./storybook-static -p 6006' --serverTimeout 100000 http://localhost:6006 --max-old-space-size=2048", "cypress:open": "cypress open", "cypress:run": "cypress run", - "gen": "run-p gen:*", - "gen:gql": "graphql-codegen --config codegen.yml", - "gen:i18n": "extract-messages -d en -l=en,ja -o translations -f yaml 'src/**/*.ts*' --extractFromFormatMessageCall", + "gql": "graphql-codegen --config codegen.yml", + "i18n": "i18next", + "i18n:legacy": "extract-messages -d en -l=en,ja -o src/i18n/translations/legacy -f yaml 'src/**/*.ts*' --extractFromFormatMessageCall", "gen:doc:plugin": "ts-node -O '{\"module\":\"CommonJS\"}' ./bin/pluginDoc" }, "engines": { @@ -127,6 +127,7 @@ "html-webpack-plugin": "^5.4.0", "html-webpack-tags-plugin": "^3.0.0", "husky": "^7.0.4", + "i18next-parser": "^6.3.0", "jest": "^27.5.0", "jest-transform-yaml": "^1.0.0", "json-loader": "^0.5.7", @@ -177,6 +178,8 @@ "github-markdown-css": "^5.1.0", "graphiql": "^1.8.7", "graphql": "^16.3.0", + "i18next": "^21.6.16", + "i18next-browser-languagedetector": "^6.1.4", "jotai": "^1.6.4", "js-file-download": "^0.4.12", "leaflet": "^1.7.1", @@ -195,6 +198,7 @@ "react-dom": "^17.0.2", "react-dropzone": "^12.0.5", "react-ga": "^3.3.0", + "react-i18next": "^11.16.7", "react-intl": "^5.24.6", "react-leaflet": "^3.2.5", "react-markdown": "^8.0.2", diff --git a/src/app.tsx b/src/app.tsx index 44caa7a8f..d38bda0c1 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -16,7 +16,7 @@ import SettingsProjectList from "@reearth/components/pages/Settings/ProjectList" import WorkspaceSettings from "@reearth/components/pages/Settings/Workspace"; import AssetSettings from "@reearth/components/pages/Settings/Workspace/Asset"; import WorkspaceList from "@reearth/components/pages/Settings/WorkspaceList"; -import { Provider as IntlProvider } from "@reearth/locale"; +import { Provider as I18nProvider } from "@reearth/i18n"; import { Provider as Auth0Provider } from "./auth"; import RootPage from "./components/pages/Authentication/RootPage"; @@ -44,7 +44,7 @@ const App: React.FC = () => { - + }> @@ -70,7 +70,7 @@ const App: React.FC = () => { - + diff --git a/src/components/atoms/ConfirmationModal/index.tsx b/src/components/atoms/ConfirmationModal/index.tsx index 8c2f57455..a91d353ef 100644 --- a/src/components/atoms/ConfirmationModal/index.tsx +++ b/src/components/atoms/ConfirmationModal/index.tsx @@ -1,5 +1,6 @@ import React from "react"; -import { useIntl } from "react-intl"; + +import { useTranslation } from "@reearth/i18n"; import Button from "../Button"; import Modal from "../Modal"; @@ -23,7 +24,7 @@ const ConfirmationModal: React.FC = ({ isOpen, onClose, }) => { - const intl = useIntl(); + const { t } = useTranslation(); const handleProceed = () => { onProceed(); @@ -37,19 +38,9 @@ const ConfirmationModal: React.FC = ({ size="sm" onClose={onClose} button1={ -