모던웹(NEMV) 혼자 제작 하기 3기 - 91 국제화 쉽게 구현하기(vue-i18n)

4 분 소요

모던 개발자라면 앱이던 웹이던 항상 다국어 지원이 가능할 통로를 열어두어야한다고 생각합니다.

더이상 국제화시대에 한글만 지원하는 확장성 없는 사이트를 만들면 안되겠죠?

i18n이란?

그저 국제화란 뜻입니다.

위키에 따르면~

국제화와 현지화는 출판물이나 하드웨어 또는 소프트웨어 등의 제품을 언어 및 문화권 등이 다른 여러 환경에 대해 사용할 수 있도록 지원하는 것을 의미한다. 이때 국제화는 제품 자체가 여러 환경을 지원할 수 있도록 제품을 설계하는 것을 의미하며, 현지화는 제품을 각 환경에 대해 지원하는 것을 의미한다.
국제화(internationalization)를 I18N이나 i18n으로, 현지화(localization)를 L10N이나 l10n 등으로 표기하기도 한다.[1] 이것은 두 단어의 영어 철자에서 첫 글자와 마지막 글자만 뺀 나머지 글자들을 그 숫자로 표시한 것이다. (I18N은 ‘I’ + 18글자 + ‘N’을 뜻한다) L의 소문자와 I의 대문자가 서로 비슷하기 때문에 보통 i18n과 L10n을 많이 사용한다. 그 외에 다국어화(multilingualization, m17n)라는 표현을 사용하기도 한다.

출처: https://ko.wikipedia.org/wiki/국제화와_지역화

레거시 장비와 통신하지 않는 이상 euc-kr 같은 갈라파고스 인코딩을 사용하면 안됩니다~

원리

만약 영어와 한국어를 토글 시키려면 어떻게 해야할까요?

저는 과거에 이렇게 해결했습니다.

const lang = {
  hello: {
    en: 'hello',
    ko: '안녕하세요',
    ru: 'Привет'
  },
  test: {
    en: 'test',
    ko: '시험',
    ru: 'тестовое задание'
  }
}
// 사용하기

lang.hello['ko'] // 한국어
lang.hello['en'] // 영어
lang.hello['ru'] // 러시아어

이런식으로 충분히 뷰에서 사용 가능한 것을 알 수가 있죠~

급하게 구현하느라 코드도 난잡해지고.. 뭔가 주류적이지 않은 방법이었죠..

그래서 일반적인 방법을 찾아봤습니다..

뷰티파이는 국제화에 대한 대응이 되어 있었습니다.

https://vuetifyjs.com/ko/framework/internationalization

근데 이 방법은 뷰티파이 콤포넌트에 들어 있는 언어를 국제화 시키는 것입니다.

vue-i18n 설치

전방위로 사용하기 위해서는 vue-i18n을 사용하면 됩니다.

yarn add vue-i18n 으로 설치해서 이것 저것 손보는 방법도 있지만~

최고의 방법은 vue-cli3의 플러그인 설치입니다!

역시 중요한 기능은 플러그인으로 만들어 놓으신 분들께 늘 감사한 마음을 가지고 있습니다.

$ cd fe
$ vue add i18n
yarn add v1.13.0
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...

success Saved lockfile.
info To upgrade, run the following command:
$ brew upgrade yarn
success Saved 12 new dependencies.
info Direct dependencies
└─ vue-cli-plugin-i18n@0.6.0
info All dependencies
├─ cli-table3@0.5.1
├─ colors@1.3.3
├─ deepmerge@2.2.1
├─ dot-object@1.7.1
├─ dotenv@6.2.0
├─ emoji-regex@7.0.3
├─ esm@3.2.22
├─ flat@4.1.0
├─ is-valid-glob@1.0.0
├─ vue-cli-plugin-i18n@0.6.0
├─ vue-i18n-extract@0.4.14
└─ vue-i18n@8.10.0
✨  Done in 6.27s.
✔  Successfully installed plugin: vue-cli-plugin-i18n

? The locale of project localization. en
? The fallback locale of project localization. en
? The directory where store localization messages of project. It's stored under `src` directory. locales
? Enable locale messages in Single file components ? No

🚀  Invoking generator for vue-cli-plugin-i18n...
📦  Installing additional dependencies...

yarn install v1.13.0
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
✨  Done in 2.74s.
⚓  Running completion hooks...

✔  Successfully invoked generator for plugin: vue-cli-plugin-i18n
   The following files have been updated / added:

     src/i18n.js
     src/locales/en.json
     vue.config.js
     package.json
     src/main.js
     src/views/test/lv3.vue
     yarn.lock

   You should review these changes with git diff and commit them.

모두 기본값으로 설치하고 나면 몇가지 파일들이 생성되어 있습니다.

사용은 처음 해보지만 딱 봐도 뭘 해야할 지 알 수 있는 구조 입니다.

살펴보기

동작 방법은 아래 링크에 자세히 나와있습니다.

http://kazupon.github.io/vue-i18n/guide/formatting.html

src/locales/en.json

{
  "message": "hello i18n !!"
}

이 파일을 딱 보면 알 수 있죠~

src/locales/ko.json을 만들어야 할 것 같다는 것을~

src/locales/ko.json

{
  "message": "안녕 i18n !!"
}

ko.json을 이렇게 만들어보면 되는 것이죠~

src/i18n.js

근데 src/locales/ko.json을 대체 어떻게 찾을까요 바로 i18n.js파일에 비밀이 있습니다.

function loadLocaleMessages () {
  const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
  const messages = {}
  locales.keys().forEach(key => {
    const matched = key.match(/([A-Za-z0-9-_]+)\./i)
    if (matched && matched.length > 1) {
      const locale = matched[1]
      messages[locale] = locales(key)
    }
  })
  return messages
}

뭔지 잘 모르겠지만 ./locales 디렉토리를 뒤져서 찾아서 뭔가 한다는 것을 알 수가 있습니다.

표시

<p v-html="$t('message.hello')"></p>

공식 가이드에 따르면 위와 같이 꺼내 쓰면 된답니다~

바꾸기

i18n.locale = 'en'

이런식으로 바꾸면 된답니다~

구현하기

원하는 것들을 찾았으니 간단히 구현해보겠습니다.

fe/src/App.vue

<v-toolbar-title>{{siteTitle}} {{$t('message')}}</v-toolbar-title>
<v-list>
    <v-list-tile  @click="changeLocale">
      <v-list-tile-title>{{$i18n.locale === 'en' ? '한글' : 'English'}}</v-list-tile-title>
    </v-list-tile>
    
<script>
  changeLocale () {
    if (this.$i18n.locale === 'en') this.$i18n.locale = 'ko'
    else this.$i18n.locale = 'en'
  }
</script>

간단히 한글과 영어만 토글시켜봅니다.

alt toggle

잘 변환됩니다~

하지만 메뉴항목은 얘기가 다릅니다.

src/locales/en.json

{
  "message": "hello i18n !!",
  "dashboard": "Dashboard",
  "today": "Today"
}

src/locales/ko.json

{
  "message": "안녕 i18n !!",
  "dashboard": "현황",
  "today": "오늘"
}

이렇게 만들어 두고 테스트를 해봅시다~

  items: [
    {
      icon: 'donut_large',
      title: this.$t('dashboard'), // '현황',
      act: true,
      subItems: [
        {
          title: this.$t('today'), // '오늘',
          to: {
            path: '/'
          }
        }
      ]
    },
    // ..

이런 식으로 구현 후 초기 값은 얻을 수 있지만..

로케일이 변해도 감지가 안되기 때문에 변화가 이루어지지 않습니다..

로케일 변경시 강제로 넣어줄 수 밖에 없습니다.

  changeLocale () {
    if (this.$i18n.locale === 'en') this.$i18n.locale = 'ko'
    else this.$i18n.locale = 'en'
    
    this.items[0].title = this.$t('dashboard')
    this.items[0].subItems[0].title = this.$t('today')
  }

위와 같이 처리하기 위해 사실 dashboard 같은 작명 보다는 title-N-N 등으로 지어서 반복문으로 간단히 끝내는 것이 좋겠죠~

alt change

결론

코딩이야 린트같은 것들이 잘 정돈해주지만..

구현 방법은 가지각색입니다.

그래서 i18n을 구현하는 방법은 여러가지이지만..

플러그인으로 잘 정돈된(스캐폴딩) 방법을 사용해서 다른 개발자가 보기에도 편한 코드를 만들어 주는 것이 늘 이롭습니다~

최대한 디폴트(기본값)를 흐트러트리지 말고 생산성을 위한 코드만 애드온 시키는 것이 유지보수에 좋은 프로젝트가 된다고 생각합니다~

소스

소스 확인

시험해보기

https://fkkmemi.com

영상

댓글남기기