Use Cases

How to Efficiently Implement i18n: Claude Code 활용 가이드

efficiently implement i18n: Claude Code 활용. 실용적인 코드 예시와 단계별 가이드를 포함합니다.

多言語대응でClaude Code가 活きる場面

国際化(i18n)の구현は、翻訳파일の관리、ロケール전환、날짜・数値のフォーマット、RTL대응など多岐にわたります。Claude Code는 이것らの作業を一括で処理し、翻訳漏れのチェックまで行えます。

Next.jsでのi18n基盤구축

> Next.js App Routerでnext-intl를 사용한多言語대응を설정して。
> 日本語と英語をサポートして。URLパスにロケールを含める形式で。

디렉터리구성

src/
  messages/
    ja.json
    en.json
  app/
    [locale]/
      layout.tsx
      page.tsx
  i18n/
    request.ts
    routing.ts

라우팅설정

// src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing';

export const routing = defineRouting({
  locales: ['ja', 'en'],
  defaultLocale: 'ja',
  pathnames: {
    '/': '/',
    '/about': {
      ja: '/about',
      en: '/about',
    },
    '/blog': {
      ja: '/blog',
      en: '/blog',
    },
  },
});
// src/i18n/request.ts
import { getRequestConfig } from 'next-intl/server';
import { routing } from './routing';

export default getRequestConfig(async ({ requestLocale }) => {
  let locale = await requestLocale;
  if (!locale || !routing.locales.includes(locale as 'ja' | 'en')) {
    locale = routing.defaultLocale;
  }

  return {
    locale,
    messages: (await import(`../messages/${locale}.json`)).default,
  };
});

翻訳파일

// src/messages/ja.json
{
  "common": {
    "siteName": "マイアプリ",
    "navigation": {
      "home": "ホーム",
      "about": "概要",
      "blog": "blog",
      "contact": "お問い合わせ"
    },
    "footer": {
      "copyright": "© {year} マイアプリ. All rights reserved."
    }
  },
  "home": {
    "hero": {
      "title": "最高のサービスを提供します",
      "subtitle": "{count, plural, =0 {ユーザーはまだいません} one {# 人のユーザー} other {# 人のユーザー}}が利用中"
    }
  }
}
// src/messages/en.json
{
  "common": {
    "siteName": "MyApp",
    "navigation": {
      "home": "Home",
      "about": "About",
      "blog": "Blog",
      "contact": "Contact"
    },
    "footer": {
      "copyright": "© {year} MyApp. All rights reserved."
    }
  },
  "home": {
    "hero": {
      "title": "We provide the best service",
      "subtitle": "{count, plural, =0 {No users yet} one {# user} other {# users}} using our service"
    }
  }
}

컴포넌트での使用

import { useTranslations } from 'next-intl';

export default function HomePage() {
  const t = useTranslations('home');
  const tc = useTranslations('common');

  return (
    <main>
      <h1>{t('hero.title')}</h1>
      <p>{t('hero.subtitle', { count: 1500 })}</p>

      <nav aria-label={tc('navigation.home')}>
        <a href="/">{tc('navigation.home')}</a>
        <a href="/about">{tc('navigation.about')}</a>
      </nav>
    </main>
  );
}

翻訳の一括생성

Claude Code에翻訳파일の생성を依頼할 수 있습니다。

> src/messages/ja.json を元に英語の翻訳파일を생성して。
> 技術用語は그まま英語で、UIテキストは自然な英語にして。

翻訳漏れのチェック

> ja.jsonとen.jsonのキーを比較して、翻訳漏れがないかチェックして。
> 不足しているキーがあれば추가して。
// scripts/check-translations.ts
import ja from '../src/messages/ja.json';
import en from '../src/messages/en.json';

function getKeys(obj: object, prefix = ''): string[] {
  return Object.entries(obj).flatMap(([key, value]) => {
    const path = prefix ? `${prefix}.${key}` : key;
    if (typeof value === 'object' && value !== null) {
      return getKeys(value as object, path);
    }
    return [path];
  });
}

const jaKeys = new Set(getKeys(ja));
const enKeys = new Set(getKeys(en));

const missingInEn = [...jaKeys].filter(k => !enKeys.has(k));
const missingInJa = [...enKeys].filter(k => !jaKeys.has(k));

if (missingInEn.length) {
  console.log('Missing in en.json:', missingInEn);
}
if (missingInJa.length) {
  console.log('Missing in ja.json:', missingInJa);
}

날짜・数値のフォーマット

import { useFormatter } from 'next-intl';

function PriceDisplay({ amount, date }: { amount: number; date: Date }) {
  const format = useFormatter();

  return (
    <div>
      <p>{format.number(amount, { style: 'currency', currency: 'USD' })}</p>
      <time>{format.dateTime(date, { year: 'numeric', month: 'long', day: 'numeric' })}</time>
      <p>{format.relativeTime(date)}</p>
    </div>
  );
}
// ja: $1,500 / 2026年3月24日 / 2週間前
// en: $1,500 / March 24, 2026 / 2 weeks ago

言語전환컴포넌트

'use client';
import { useRouter, usePathname } from 'next/navigation';
import { useLocale } from 'next-intl';

function LanguageSwitcher() {
  const locale = useLocale();
  const router = useRouter();
  const pathname = usePathname();

  const switchLocale = (newLocale: string) => {
    const newPath = pathname.replace(`/${locale}`, `/${newLocale}`);
    router.push(newPath);
  };

  return (
    <div role="radiogroup" aria-label="Language selection">
      <button
        role="radio"
        aria-checked={locale === 'ja'}
        onClick={() => switchLocale('ja')}
        className={locale === 'ja' ? 'font-bold' : ''}
      >
        日本語
      </button>
      <button
        role="radio"
        aria-checked={locale === 'en'}
        onClick={() => switchLocale('en')}
        className={locale === 'en' ? 'font-bold' : ''}
      >
        English
      </button>
    </div>
  );
}

정리

Claude Code를 활용하면 i18n基盤の구축から翻訳파일の생성、翻訳漏れのチェックまでを효율적으로進められます。특히翻訳파일の一括생성と整合性チェックは、Claude Codeの強みが発揮される場面です。프로젝트の多言語대응方針はCLAUDE.mdに記述しておくと一貫性を保てます。또한プロンプトテクニックを使って翻訳の品質を高めることも할 수 있습니다。

Claude Code의 상세 정보는Anthropic공식 문서를 확인하세요.

#Claude Code #i18n #internationalization #multilingual #React