[vue] 다국어 처리 (vue-i18n)

adc0612·2022년 5월 21일
2

개요

이전에 진행했던 vue 프로젝트에 다국어 처리가 필요해졌다.
다국어 처리는 웹 브라우저를 사용하는 국가에 따라 다양한 언어 등을 지원하게 만드는 것이다.
찾아보니 vue에서는 vue-i18n 라이브러리를 이용해 다국어 처리를 쉽게 가능하게 하는 것 같다.
기존에 한국어로 하드코딩 되어있던 모든 워딩을 vue-i18n에서 제공되는 변수로 바꿔주면 됐다.

vue-i18n 공식 문서 사이트


설치

npm을 이용해 설치할 수 있다. (vue 2버전)

npm install vue-i18n@8

vue cli 3.x이상 버전이면 아래로 설치하는 것이 좋다.
필요한 import문이 같이 생성된다.
필자는 vue add로 설치했다.

vue add i18n

i18n 설정

vue add로 설치하면 아래와 같이 src폴더안에 locales폴더와 i18n.js파일이 생성 된 것을 볼 수 있다.

i18n.js 파일을 아래와 같은 코드로 바꿨다.
아래와 같이 설정하면 locales폴더안에 원하는 언어 코드로 폴더를 만들고 안에 번역한 json을 넣어주면 알아서 key value 형태로 들어간다.

import Vue from 'vue';
import VueI18n from 'vue-i18n';

Vue.use(VueI18n);

function loadLocaleMessages() {
  // json 파일을 읽어들이기 위한 function
  const requireLang = require.context('@/locales', true, /\.json$/);
  const messages = {};
  // json file read
  for (const file of requireLang.keys()) {
    if (file === './index.js') continue; // index.js 파일 제외
    const path = file.replace(/(\.\/|\.json$)/g, '').split('/');
    path.reduce((o, s, i) => {
      if (o[s]) return o[s];
      o[s] = i + 1 === path.length ? requireLang(file) : {};
      return o[s];
    }, messages);
  }
  return messages;
}

const options = {
  
  locale: 'en', // 기본언어 (영어)
  fallbackLocale: 'ko', // 지정한 언어에 번역이 없을 때 보여줄 언어 (한국어)
  messages: loadLocaleMessages(),
  silentTranslationWarn: true,
};

export default new VueI18n(options);

예시로 아래와 같이 폴더와 파일구조로 되어있으면 영어(en), 한국어(ko), 베트남어(vi)가 들어가게 된다.

각 언어 폴더안에 파일들은 아래와 같이 접근할 수 있다.
message.json 파일 안에 error객체안에 requiredField값을 사용할려면 아래와 같이 접근한다.

<!-- in template -->
<span class="blind">{{ $t('message.error.requiredField') }}</span>
// in script
let text = this.$i18n.t('message.error.requiredField');

i18n 적용

번역 json

번역을 넣을 변수를 json파일 안에 만들고 번역을 넣는다.

src/locales/ko/common.json

{
  "gender": {
    "M": "남자",
    "W": "여자"
  },
}

src/locales/en/common.json

{
  "gender": {
    "M": "man",
    "W": "woman"
  },
}

i18n 적용할 곳

vue 파일

vue 파일에서 json에서 지정한 변수를 넣는다.
따로 i18n라이브러리를 import안하고 사용 가능하다.

<!-- in template -->
<span>{{ $t('common.gender.M') }}</span>
// in script
let gender = this.$i18n.t('common.gender.M');

js 파일

js파일에서는 i18n을 import해서 아래와 같이 사용한다.

import i18n from '@/i18n';

export default {
  state: {
    genderStatus: [
      { text: i18n.t('common.gender.M'), value: 'M' },
      { text: i18n.t('common.gender.W'), value: 'W' },
    ],
  },
};

i18n 활용 형태

1. 기본 text

번역에서 지정한 변수를 할당하면 변수에 저장된 텍스트가 국가에 따라 불러오게 된다.

번역 json 파일

{
  "gender": {
    "M": "man",
    "W": "woman"
  },
}

vue 파일

<!-- in template -->
<span>{{ $t('common.gender.M') }}</span> <!-- man -->
// in script
let gender = this.$i18n.t('common.gender.M'); // man

js 파일

import i18n from '@/i18n';

export default {
  state: {
    genderStatus: [
      { text: i18n.t('common.gender.M'), value: 'M' }, // man
      { text: i18n.t('common.gender.W'), value: 'W' }, // woman
    ],
  },
};

2. 기본 text + 변수

텍스트 안에 값이나 변수를 받아서 언어에 따라 다르게 표현해야 할 때가 있다.
예:
한국어: 총 합계는 10개 입니다.
영어: Total is 10.

그럴때는 그 값을 변수로 지정해서 언어마다 그 위치를 변경해주면 된다.

번역 json 파일

변수 여러개도 가능하다.
src/locales/ko/message.json

{
  "message": {
    "total": "총 합계는 {num}개 입니다.",
    "totalWithDate": "{fromDate}부터 {toDate}까지 총 학생 수는 {count}명입니다."
  },
}

src/locales/en/message.json

{
  "message": {
    "total": "Total is {num}.",
    "totalWithDate": "From {fromDate} to {toDate}, the total number of students is {count}."
  },
}

vue 파일

<!-- in template -->
<span>{{ $t('message.total', {num: 10}) }}</span> <!-- Total is 10 -->
<span>
 {{ $t('message.totalWithDate', {
  count: 23,
  fromDate: '02/02/2022',
  toDate: '05/02/2022',
  }) 
 }}
</span> <!-- From 02/02/2022 to 02/02/2022, the total number of students is 23.-->
// in script
let message = this.$i18n.t('message.total', {num: 10}); // Total is 10.
let messageDate = this.$i18n.t('message.totalWithDate', {
  count: 23,
  fromDate: '02/02/2022',
  toDate: '05/02/2022',
  }) ; // From 02/02/2022 to 02/02/2022, the total number of students is 23.

js 파일

import i18n from '@/i18n';

let message = i18n.t('message.total', {num: 10}); // Total is 10.
let messageDate = i18n.t('message.totalWithDate', {
  count: 23,
  fromDate: '02/02/2022',
  toDate: '05/02/2022',
  }) ; // From 02/02/2022 to 02/02/2022, the total number of students is 23.

3. text + number

텍스트 안에 숫자를 받아서 언어에 따라 다르게 표현해야 할 때가 있다.
예:
한국어: 친구보다 사탕을 5개 더 가지고 있다.
영어: I have 5 more candies than my friend.

그럴때는 그 숫자를 전달하고 언어마다 그 위치를 변경해주면 된다.

번역 json 파일

숫자는 자동으로 {n}에 담게 된다.
src/locales/ko/message.json

{
  "message": {
    "candy": "친구보다 사탕을 {n}개 더 가지고 있다."
  },
}

src/locales/en/message.json

{
  "message": {
    "candy": "I have {n} more candies than my friend."
  },
}

vue 파일

번역 텍스트 옆에 인자로 숫자를 (변수가 number type이면 가능) 보내면 된다.

<!-- in template -->
<span>{{ $tc('message.candy', 5) }}</span> <!-- I have 5 more candies than my friend. -->
<!-- count = 5 라고 가정 -->
<span>{{ $tc('message.candy', count) }}</span> <!-- I have 5 more candies than my friend.-->
// in script
let message = this.$i18n.tc('message.candy', 5); // I have 5 more candies than my friend.
let count = 5;
let messageWithVal = this.$i18n.tc('message.candy', count); // I have 5 more candies than my friend.

js 파일

import i18n from '@/i18n';

let message = i18n.tc('message.candy', 5); // I have 5 more candies than my friend.
let count = 5;
let messageWithVal = i18n.tc('message.candy', count); // I have 5 more candies than my friend.

더 많은 기능

더 많은 기능과 자세한 설명은 공식사이트에 잘 기록되어있으니 참고
vue-i18n 공식 활용 문서

0개의 댓글