TanStack Start v1에서 언어 전환 컴포넌트를 구축하는 방법

동일한 페이지에 머물면서 언어 전환하기

문제

다국어 애플리케이션에서 사용자가 언어를 전환할 때, 동일한 페이지에서 새로운 언어로 동일한 콘텐츠를 보기를 기대합니다. 잘못 구현된 언어 전환기는 언어 선택을 다른 목적지로의 탐색으로 처리하여 사용자를 홈페이지로 리디렉션하고 현재 위치를 완전히 잃게 만듭니다. 이는 사용자 흐름을 방해하고 특히 사용자가 워크플로우 깊숙이 있거나 특정 콘텐츠를 보고 있을 때 불편함을 초래합니다. 과제는 URL의 나머지 경로, 검색 매개변수 및 해시를 유지하면서 URL의 언어 세그먼트만 변경하는 전환기를 구축하는 것입니다.

솔루션

현재 URL 경로명을 읽고 경로의 로케일 세그먼트를 교체하여 사용 가능한 각 언어에 대한 링크를 구성하는 언어 전환 컴포넌트를 구축합니다. URL 구조에서 현재 로케일을 추출한 다음, 다른 모든 URL 세그먼트를 그대로 유지하면서 로케일 부분을 대체하여 지원되는 다른 언어에 대한 새 경로를 생성합니다. 이러한 경로를 사용하여 사용자가 현재 페이지 컨텍스트를 잃지 않고 언어를 전환할 수 있는 링크를 렌더링합니다.

단계

1. 지원되는 로케일 정의

애플리케이션이 지원하는 모든 언어를 나열하고 기본 로케일을 식별하는 구성 파일을 생성합니다.

export const locales = ["en", "fr", "es", "de"] as const;

export type Locale = (typeof locales)[number];

export const defaultLocale: Locale = "en";

이 구성은 사용 가능한 언어에 대한 단일 정보 소스 역할을 하며 전환기 링크를 생성하는 데 사용됩니다.

2. 경로명에서 현재 로케일을 추출하는 헬퍼 생성

경로명을 파싱하고 로케일 세그먼트가 있는 경우 이를 추출하는 유틸리티 함수를 작성합니다.

import { defaultLocale, locales, type Locale } from "./locales";

export function getLocaleFromPathname(pathname: string): Locale {
  const segments = pathname.split("/").filter(Boolean);
  const firstSegment = segments[0];

  if (firstSegment && locales.includes(firstSegment as Locale)) {
    return firstSegment as Locale;
  }

  return defaultLocale;
}

이 함수는 첫 번째 경로 세그먼트를 검사하여 지원되는 로케일과 일치하면 해당 값을 반환하고, 그렇지 않으면 기본값으로 대체합니다.

3. 로컬라이즈된 경로를 생성하는 헬퍼 만들기

현재 경로명과 대상 로케일을 받아 로케일 세그먼트가 교체된 새 경로를 구성하는 함수를 작성합니다.

import { defaultLocale, locales, type Locale } from "./locales";

export function getLocalizedPath(
  pathname: string,
  targetLocale: Locale,
): string {
  const segments = pathname.split("/").filter(Boolean);
  const firstSegment = segments[0];

  const hasLocalePrefix =
    firstSegment && locales.includes(firstSegment as Locale);

  if (hasLocalePrefix) {
    segments[0] = targetLocale;
  } else {
    segments.unshift(targetLocale);
  }

  return "/" + segments.join("/");
}

이 함수는 기존 로케일 세그먼트를 교체하거나 대상 로케일을 경로 앞에 추가하여, 새 URL이 다른 언어로 동일한 페이지를 가리키도록 보장합니다.

4. 언어 전환 컴포넌트 구축하기

현재 위치를 사용하여 지원되는 모든 언어에 대한 링크를 생성하는 컴포넌트를 만듭니다.

import { Link } from "@tanstack/react-router";
import { useLocation } from "@tanstack/react-router";
import { locales, type Locale } from "./locales";
import { getLocaleFromPathname, getLocalizedPath } from "./locale-helpers";

export function LanguageSwitcher() {
  const location = useLocation();
  const currentLocale = getLocaleFromPathname(location.pathname);

  return (
    <nav>
      <ul>
        {locales.map((locale) => {
          const isActive = locale === currentLocale;
          const localizedPath = getLocalizedPath(location.pathname, locale);

          return (
            <li key={locale}>
              <Link
                to={localizedPath}
                search={location.search}
                hash={location.hash}
                aria-current={isActive ? "page" : undefined}
              >
                {locale.toUpperCase()}
              </Link>
            </li>
          );
        })}
      </ul>
    </nav>
  );
}

이 컴포넌트는 현재 경로명을 읽고 활성 로케일을 확인한 다음, 현재 페이지 구조, 검색 매개변수 및 해시 프래그먼트를 유지하는 각 지원 언어에 대한 링크를 렌더링합니다. 사용자는 동일한 논리적 페이지에 머물면서 언어를 전환할 수 있습니다.