๐ŸŒ 59. React Native ๋‹ค๊ตญ์–ด(i18n) ์ฒ˜๋ฆฌ ์ „๋žต ์™„์ „ ์ •๋ฆฌ

JM_Devยท2025๋…„ 7์›” 9์ผ
0
post-thumbnail

์•ฑ์ด ๊ธ€๋กœ๋ฒŒ ์œ ์ €๋ฅผ ๋Œ€์ƒ์œผ๋กœ ๋ฐฐํฌ๋˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด
๋‹ค๊ตญ์–ด(i18n, internationalization) ์ฒ˜๋ฆฌ๋Š” ํ•„์ˆ˜ ์กฐ๊ฑด์ด ๋œ๋‹ค.

React Native์—์„œ๋„ ์‰ฝ๊ณ  ์œ ์—ฐํ•˜๊ฒŒ ๋‹ค๊ตญ์–ด ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋“ค์ด ์žˆ๋‹ค.
๊ฐ€์žฅ ๋งŽ์ด ์“ฐ์ด๋Š” ๋ฐฉ์‹์€ ๋ฐ”๋กœ i18next + react-i18next ์กฐํ•ฉ์ด๋‹ค.


๐Ÿ›  ๊ธฐ๋ณธ ์„ค์น˜ ๋ฐ ์…‹์—…

npm install i18next react-i18next i18next-http-backend i18next-browser-languagedetector

๐Ÿ“ฆ Expo ํ™˜๊ฒฝ์—์„  ์ถ”๊ฐ€ ์„ค์ • ์—†์ด ๋ฐ”๋กœ ๊ฐ€๋Šฅ


๐Ÿ”ง i18n ์ดˆ๊ธฐ ์„ค์ • ํŒŒ์ผ ๋งŒ๋“ค๊ธฐ

// i18n.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import en from './locales/en.json';
import ko from './locales/ko.json';

i18n.use(initReactI18next).init({
  resources: {
    en: { translation: en },
    ko: { translation: ko },
  },
  lng: 'ko',
  fallbackLng: 'en',
  interpolation: {
    escapeValue: false,
  },
});

export default i18n;

๐ŸŒ ๋ฒˆ์—ญ ํŒŒ์ผ ๊ตฌ์กฐ

๐Ÿ“ locales
 โ”ฃ ๐Ÿ“„ en.json
 โ”— ๐Ÿ“„ ko.json
// en.json
{
  "welcome": "Welcome",
  "login": "Login"
}
// ko.json
{
  "welcome": "ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค",
  "login": "๋กœ๊ทธ์ธ"
}

โœ… ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฒˆ์—ญ ์ ์šฉ

import { useTranslation } from 'react-i18next';

export default function Home() {
  const { t } = useTranslation();
  return <Text>{t('welcome')}</Text>;
}

๐ŸŒ€ ์–ธ์–ด ๋ณ€๊ฒฝ ๊ธฐ๋Šฅ ์ถ”๊ฐ€

<Button title="๐Ÿ‡บ๐Ÿ‡ธ English" onPress={() => i18n.changeLanguage('en')} />
<Button title="๐Ÿ‡ฐ๐Ÿ‡ท ํ•œ๊ตญ์–ด" onPress={() => i18n.changeLanguage('ko')} />
  • i18n.changeLanguage(code)๋กœ ์–ธ์ œ๋“  ์‹ค์‹œ๊ฐ„ ์–ธ์–ด ์ „ํ™˜ ๊ฐ€๋Šฅ
  • ์ƒํƒœ ์œ ์ง€ ๋ฐฉ๋ฒ•: AsyncStorage๋กœ ํ˜„์žฌ ์–ธ์–ด ์ €์žฅ ํ›„ ์•ฑ ์‹œ์ž‘ ์‹œ ์ ์šฉ

๐Ÿ’ก ๋‹ค๊ตญ์–ด ์ฒ˜๋ฆฌ ํŒ

ํ•ญ๋ชฉ๋‚ด์šฉ
๋””ํดํŠธ ์–ธ์–ด ์„ค์ •lng: 'ko', fallbackLng: 'en' ๋“ฑ์œผ๋กœ ์ฒ˜๋ฆฌ
ํ…์ŠคํŠธ fallbackํ‚ค ๋ˆ„๋ฝ ์‹œ key ์ž์ฒด ํ‘œ์‹œ๋จ ({t('missing.key')})
๋ฆฌ์ŠคํŠธ/๋ฐฐ์—ด ์ฒ˜๋ฆฌt('list', { returnObjects: true }) ์‚ฌ์šฉ
์ค‘์ฒฉ๋œ ํ…์ŠคํŠธ"title": { "main": "Hello", "sub": "World" } ํ˜•์‹ ๊ฐ€๋Šฅ

๐Ÿ“Œ ์‹ค์ „ ์ ์šฉ ์˜ˆ์‹œ (์–ธ์–ด ์„ค์ • ํ™”๋ฉด)

<View>
  <Text>{t('choose_language')}</Text>
  <Button onPress={() => i18n<.changeLanguage('en')} title="๐Ÿ‡บ๐Ÿ‡ธ English" />
  <Button onPress={() => i18n.changeLanguage('ko')} title="๐Ÿ‡ฐ๐Ÿ‡ท ํ•œ๊ตญ์–ด" />
</View>

โœ๏ธ ๋‚ด๊ฐ€ ๋А๋‚€ ์ 

์›น์—์„  i18n์„ ์ž์ฃผ ์จ๋ดค์ง€๋งŒ,
React Native์—์„œ๋„ ์ƒ๊ฐ๋ณด๋‹ค ํŽธํ•˜๊ฒŒ ์ ์šฉ๋˜์—ˆ๋‹ค.
ํŠนํžˆ ๋‹ค๊ตญ์–ด๊ฐ€ ํ•„์ˆ˜์ธ ์•ฑ์„ ๊ฐœ๋ฐœํ•  ๋•Œ
์ดˆ๊ธฐ๋ถ€ํ„ฐ ๊ตฌ์กฐ์ ์œผ๋กœ ์ค€๋น„ํ•ด๋‘๋ฉด ๋‚˜์ค‘์— ์‹œ๊ฐ„ ์•„๋‚„ ์ˆ˜ ์žˆ์Œ.


๐ŸŒ โ€œ์ „ ์„ธ๊ณ„ ์œ ์ €์—๊ฒŒ ๋‹ค๊ฐ€๊ฐ€๋Š” ์ฒซ ๊ฑธ์Œ์€ ๋ฒˆ์—ญ์—์„œ ์‹œ์ž‘๋œ๋‹ค.โ€


profile
๊ฐœ๋ฐœ์ž๋กœ ์ทจ์—…์„ ์ค€๋น„ ์ค‘ ์ด๋ฉฐ, ์—ด์‹ฌํžˆ ๊ณต๋ถ€ ์ค‘ ์ž…๋‹ˆ๋‹ค!

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