이전에 진행했던 vue 프로젝트에 다국어 처리가 필요해졌다.
다국어 처리는 웹 브라우저를 사용하는 국가에 따라 다양한 언어 등을 지원하게 만드는 것이다.
찾아보니 vue에서는 vue-i18n 라이브러리를 이용해 다국어 처리를 쉽게 가능하게 하는 것 같다.
기존에 한국어로 하드코딩 되어있던 모든 워딩을 vue-i18n에서 제공되는 변수로 바꿔주면 됐다.
npm을 이용해 설치할 수 있다. (vue 2버전)
npm install vue-i18n@8
vue cli 3.x이상 버전이면 아래로 설치하는 것이 좋다.
필요한 import문이 같이 생성된다.
필자는 vue add로 설치했다.
vue add 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');
번역을 넣을 변수를 json파일 안에 만들고 번역을 넣는다.
src/locales/ko/common.json
{
"gender": {
"M": "남자",
"W": "여자"
},
}
src/locales/en/common.json
{
"gender": {
"M": "man",
"W": "woman"
},
}
vue 파일에서 json에서 지정한 변수를 넣는다.
따로 i18n라이브러리를 import안하고 사용 가능하다.
<!-- in template -->
<span>{{ $t('common.gender.M') }}</span>
// in script
let gender = this.$i18n.t('common.gender.M');
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' },
],
},
};
번역에서 지정한 변수를 할당하면 변수에 저장된 텍스트가 국가에 따라 불러오게 된다.
{
"gender": {
"M": "man",
"W": "woman"
},
}
<!-- in template -->
<span>{{ $t('common.gender.M') }}</span> <!-- man -->
// in script
let gender = this.$i18n.t('common.gender.M'); // man
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
],
},
};
텍스트 안에 값이나 변수를 받아서 언어에 따라 다르게 표현해야 할 때가 있다.
예:
한국어: 총 합계는 10개 입니다.
영어: Total is 10.
그럴때는 그 값을 변수로 지정해서 언어마다 그 위치를 변경해주면 된다.
변수 여러개도 가능하다.
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}."
},
}
<!-- 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.
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.
텍스트 안에 숫자를 받아서 언어에 따라 다르게 표현해야 할 때가 있다.
예:
한국어: 친구보다 사탕을 5개 더 가지고 있다.
영어: I have 5 more candies than my friend.
그럴때는 그 숫자를 전달하고 언어마다 그 위치를 변경해주면 된다.
숫자는 자동으로 {n}에 담게 된다.
src/locales/ko/message.json
{
"message": {
"candy": "친구보다 사탕을 {n}개 더 가지고 있다."
},
}
src/locales/en/message.json
{
"message": {
"candy": "I have {n} more candies than my friend."
},
}
번역 텍스트 옆에 인자로 숫자를 (변수가 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.
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 공식 활용 문서