[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)가 들어가게 된다.
locales 폴더 구조

각 언어 폴더안에 파일들은 아래와 같이 접근할 수 있다.
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개의 댓글