๐ŸŒ next-intl์˜ ICU messages ์‚ฌ์šฉํ•˜๊ธฐ

Haileyยท2024๋…„ 4์›” 30์ผ

next-intl

๋ชฉ๋ก ๋ณด๊ธฐ
3/3

Tip ๐Ÿ’ก ์ด ํฌ์ŠคํŠธ๋Š” next-intl์— ๋Œ€ํ•œ ์‚ฌ์ „์ง€์‹์ด ์žˆ๋Š” ๋ถ„์„ ๋Œ€์ƒ์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
next-intl์„ ์‹œ์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋ž˜ ํฌ์ŠคํŠธ๋ฅผ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.
๐ŸŒ Next.js์—์„œ ๋‹ค๊ตญ์–ด ์ง€์›ํ•˜๊ธฐ (next-intl)

next-intl์—์„œ๋Š” useTranslations()๋ฅผ ์‚ฌ์šฉํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด json ํŒŒ์ผ์— ์žˆ๋Š” ํ…์ŠคํŠธ(๋ฉ”์„ธ์ง€)๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import {useTranslations} from 'next-intl';
 
export default function Index() {
  const t = useTranslations('Index');
  return <h1>{t('title')}</h1>;
}

์œ„์˜ ์˜ˆ์‹œ๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•(Static messages)์ด๋ฉฐ, next-intl๋Š” ์ด ์™ธ์—๋„ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
์ด ํฌ์ŠคํŠธ์—์„œ๋Š” ICU message๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค์„ ์†Œ๊ฐœํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ  ์ž๋ฃŒ ๐Ÿ“‘
next-intl Docs > Usage guide > Messages

Interpolation of dynamic values

Dynamic value๋ฅผ ๋„ฃ์–ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ €๋Š” ์ด๋ฒˆ์— copyright footer๋ฅผ ๋งŒ๋“ค๋ฉด์„œ ํ˜„์žฌ ์—ฐ๋„๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋„๋ก ์—ฐ๋„ ๋ถ€๋ถ„์„ dynamic value๋กœ ์‚ฌ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๊ณผ์ •

  1. json ํŒŒ์ผ์— dynamic value๋ฅผ {} ์•ˆ์— ์ž‘์„ฑํ•ด ์ฃผ์„ธ์š”.
// messages/en.json

"Footer": {
  "copyright": "ยฉ Hailey Kim {year}"
}
  1. ๋ฉ”์„ธ์ง€๋ฅผ ์‚ฌ์šฉํ•  ํŒŒ์ผ์—์„œ useTranslations()์œผ๋กœ ๊ฐ€์ ธ์˜ค์„ธ์š”.
    (์ €๋Š” ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ const t = useTranslations('Footer');๋กœ ๊ฐ€์ ธ์˜ค๊ณ  t๋ฅผ props๋กœ ๋„˜๊ฒจ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.).

  2. t() ์•ˆ์— (ํ‚ค ๊ฐ’, dynamic value)๋ฅผ ์ž‘์„ฑํ•ด ์ฃผ์„ธ์š”.
    (dynamic value๋Š” object๋กœ ๊ฐ์‹ธ์„œ ๋„˜๊ฒจ์ฃผ์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค. {value ์ด๋ฆ„: ๊ฐ’})

// components/common/footer.tsx

import { Translation } from '@/types/intl';

export default function Footer({ t }: { t: Translation }) {
    const year = new Date().getFullYear();

    return (
        <footer className="mt-20 w-72 mx-auto">
            {t('copyright', { year })}
        </footer>
    );
}

๐Ÿ“Œ ์ €๋Š” t๋ฅผ props๋กœ ๋„˜๊ฒจ์ฃผ์—ˆ๊ณ  ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ์“ฐ๊ธฐ ๋•Œ๋ฌธ์— ํƒ€์ž…์„ ๋ช…์‹œํ•ด์•ผ ๋ผ์„œ ์•„๋ž˜์™€ ๊ฐ™์ด useTranslations()์˜ ๋ฆฌํ„ด ๊ฐ’(t)์— ๋Œ€ํ•œ ํƒ€์ž…์„ ๋”ฐ๋กœ ์ž‘์„ฑํ•˜๊ณ  footer์— import ํ•˜์—ฌ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

// types/intl.ts

import { TranslationValues, Formats } from 'next-intl';

export type Translation = {
    <TargetKey>(
        key: TargetKey,
        values?: TranslationValues | undefined,
        formats?: Partial<Formats> | undefined
    ): string;
};

๊ฒฐ๊ณผ

์•„๋ž˜์™€ ๊ฐ™์ด ํ˜„์žฌ ์—ฐ๋„(2024)๊ฐ€ ์ž˜ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


profile
๋น ๋ฅด๊ฒŒ ๋ฐœ์ „ํ•˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€