From 11e8425fad9ebb6220a7234390a4aa35ac9e2859 Mon Sep 17 00:00:00 2001 From: Danah Date: Sun, 1 Dec 2024 18:34:23 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20url=EC=97=90=20lang=20param=EC=9D=B4=20?= =?UTF-8?q?=EC=9E=88=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20=EB=B8=8C=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=EC=A0=80=20lang=EB=B3=B4=EB=8B=A4=20=EC=9A=B0?= =?UTF-8?q?=EC=84=A0=ED=95=98=EC=97=AC=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.test.tsx | 16 +++++-- src/App.tsx | 8 ++++ src/components/molecules/Footer/Footer.tsx | 10 ++-- src/components/molecules/Header/Header.tsx | 46 +++++++----------- src/components/utils/LangLayout.tsx | 24 ++++++++++ src/utils/i18n.ts | 54 ++++++++++++++++++++++ 6 files changed, 121 insertions(+), 37 deletions(-) create mode 100644 src/components/utils/LangLayout.tsx diff --git a/src/App.test.tsx b/src/App.test.tsx index c10622f..7e5e4ca 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -2,7 +2,7 @@ import { HelmetProvider } from "react-helmet-async"; import { MemoryRouter, type MemoryRouterProps } from "react-router-dom"; -import { render, screen } from "@testing-library/react"; +import { render, screen, waitFor } from "@testing-library/react"; import { userEvent } from "@testing-library/user-event"; import ThemeProvider from "@providers/ThemeProvider"; @@ -30,15 +30,21 @@ describe("상단 네비게이션", () => { const languageButton = await screen.findByTestId("language-button"); expect(languageButton).toBeInTheDocument(); await userEvent.click(languageButton); - expect(await screen.findByTestId(/language-option-korea/)).toBeInTheDocument(); + expect(await screen.findByTestId(/language-option-korean/)).toBeInTheDocument(); expect(await screen.findByTestId(/language-option-english/)).toBeInTheDocument(); if (languageButton.getAttribute("aria-label") === "한국어") { await userEvent.click(screen.getByTestId("language-option-english")); - expect(languageButton.getAttribute("aria-label")).equal("english"); + await waitFor(async () => { + const languageButton = await screen.findByTestId("language-button"); + expect(languageButton.getAttribute("aria-label")).equal("English"); + }); } else { - await userEvent.click(screen.getByTestId("language-option-korea")); - expect(languageButton.getAttribute("aria-label")).equal("korea"); + await userEvent.click(screen.getByTestId("language-option-korean")); + await waitFor(async () => { + const languageButton = await screen.findByTestId("language-button"); + expect(languageButton.getAttribute("aria-label")).equal("한국어"); + }); } }); diff --git a/src/App.tsx b/src/App.tsx index ea2db8f..b2ba992 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,7 @@ import { Route, Routes } from "react-router-dom"; import ErrorBoundary from "@components/utils/ErrorBoundary"; +import LangLayout from "@components/utils/LangLayout"; import Error404Page from "@pages/error/404/page"; import Error500Page from "@pages/error/500/page"; import HowToConnectPage from "@pages/faq/how-to-connect/page"; @@ -25,6 +26,13 @@ function App() { /> } /> } /> + }> + } /> + } /> + } /> + } /> + } /> + } /> diff --git a/src/components/molecules/Footer/Footer.tsx b/src/components/molecules/Footer/Footer.tsx index 13e157e..b74ebb3 100644 --- a/src/components/molecules/Footer/Footer.tsx +++ b/src/components/molecules/Footer/Footer.tsx @@ -1,4 +1,4 @@ -import { Link } from "react-router-dom"; +import { Link, useParams } from "react-router-dom"; import Button from "@components/atoms/Button"; import Container from "@components/atoms/Container"; @@ -7,6 +7,10 @@ import { GoogleFirebase } from "@utils/google-firebase"; import { Copyright, Divider, InfoBox, PolicyButtonGroup, StyledFooter } from "./Footer.styles"; function Footer() { + const { lang } = useParams(); + + const prefixUrlLang = lang ? `/${lang}` : ""; + const handleLogEvent = (label: string) => { GoogleFirebase.logEvent("click_top_nav", { item_name: label @@ -20,12 +24,12 @@ function Footer() { Copyright © {new Date().getFullYear()} Plandy - handleLogEvent("terms")}> + handleLogEvent("terms")}> - handleLogEvent("privacy")}> + handleLogEvent("privacy")}> diff --git a/src/components/molecules/Header/Header.tsx b/src/components/molecules/Header/Header.tsx index 96be095..f76e067 100644 --- a/src/components/molecules/Header/Header.tsx +++ b/src/components/molecules/Header/Header.tsx @@ -1,6 +1,5 @@ -import { useState } from "react"; - -import { Link } from "react-router-dom"; +import { useTranslation } from "react-i18next"; +import { Link, useLocation, useNavigate, useParams } from "react-router-dom"; import Button from "@components/atoms/Button"; import Container from "@components/atoms/Container"; @@ -9,31 +8,21 @@ import Select, { Option } from "@components/atoms/Select"; import useThemeStore from "@stores/theme"; import { GoogleFirebase } from "@utils/google-firebase"; -import i18n from "@utils/i18n"; +import { matchSupportLanguage, SupportLanguage } from "@utils/i18n"; import { Adornment, HeaderInner, Logo, StyledHeader } from "./Header.styles"; -const Language = { - en: { - name: "English", - value: "english" - }, - ko: { - name: "한국어", - value: "korean" - }, - ja: { - name: "日本語", - value: "japanese" - } -}; - function Header() { + const { i18n } = useTranslation(); + const navigate = useNavigate(); + const { pathname } = useLocation(); + const { lang } = useParams(); + const mode = useThemeStore((state) => state.mode); const updateTrigger = useThemeStore((state) => state.updateTrigger); const updateMode = useThemeStore((state) => state.updateMode); - const [language, setLanguage] = useState(i18n.language); + const prefixUrlLang = lang ? `/${lang}` : ""; const handleClick = () => { updateTrigger("manual"); @@ -42,8 +31,7 @@ function Header() { }; const handleChangeLang = (newLang?: string) => { - i18n.changeLanguage(newLang); - setLanguage(newLang || "en"); + navigate(`/${newLang}${pathname.replace(prefixUrlLang, "")}`); }; const handleLogEvent = (label: string) => { @@ -56,7 +44,7 @@ function Header() { - handleLogEvent("logo")}> + handleLogEvent("logo")}> - handleLogEvent("faq")}> + handleLogEvent("faq")}> - handleLogEvent("guide")}> + handleLogEvent("guide")}> @@ -77,18 +65,18 @@ function Header() {