! vue-i18n 설치 및 테스트 해본 것 - 개인기록으로 남김 -을 공유
! 설명이 불친절 할 or 없을 수 있음
! 테스트해보고 작성은 나중에 한거라 빠진 내용 있을 수 있음
! 이대로 따라해도 안될 수 있음
i18n 이란
단순히 번역을 하는 개념이 아니라 좀 더 폭넓은 개념,
“국제화” ; 현지화, 양방향 텍스트 지원, 숫자/날짜/주소 등 표현 방식, 문화적 지원
사용하게 된 배경
vue-i18n 이란
1-1. 설치
npm i vue-i18n
설치법: 구글링 하면 나옴 (or 아래 참고링크 참조)
1-2. main.ts 설정 및 i18n, locales 폴더 및 원하는 언어 json 파일 생성
// i18n/index.js
import ko from '@/locales/ko.json'
import en from '@/locales/en.json'
export default {
ko: ko,
en: en
}
// locales/ko.json
{
title: '제목'
}
// locales/en.json
{
title: 'Title'
}
1-3. Vue SFC 내 활용
<script setup lang="ts">
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
</script>
<template>
<WelcomeItem>
<template #icon>
<DocumentationIcon />
</template>
<template #heading>{{ $t('title') }}</template> // 요렇게 template 내에서 활용
...중략
</WelcomeItem>
</template>
(대충 locales 에 몇몇 키 추가해서 ) 화면 결과
기존 main.ts
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
//highchart
import { Chart } from 'highcharts-vue'
app.component('high-chart', Chart)
// vue-i18n
import { createI18n } from 'vue-i18n'
import { messages } from 'vue-i18n'
const i18n = createI18n({
// options
locale: 'ko',
fallbackLocale: 'en',
legacy: false,
messages
})
app.use(i18n)
app.mount('#app')
i18n type 추가 (main.ts)
// main.ts
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
//highchart
import { Chart } from 'highcharts-vue'
app.component('high-chart', Chart)
// vue-i18n
import { createI18n } from 'vue-i18n'
import enUS from './locales/en.json'
import koKR from './locales/ko.json'
type MessageSchema = typeof enUS // json 파일 타입화?해서 messages타입 지정해줌
const i18n = createI18n<[MessageSchema], 'ko' | 'en'>({
// options
locale: 'ko',
fallbackLocale: 'en',
legacy: false,
messages: {
en: enUS,
ko: koKR
}
})
app.use(i18n)
app.mount('#app')
vite config 플러그인 설정 추가
npm i --save-dev @intlify/vite-plugin-vue-i18n
(주의, vite-plugin-vue-i18n 설치시 vite "^4.2.3" peer dependency 오류 날수 있으니 vite 버전 췌크)
[수정]
@intlify/unplugin-vue-i18n 플러그인 설치 (vite 4 이상 위에거 말고 요걸로)
npm i --save-dev @intlify/unplugin-vue-i18n
// vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'node:path'
// import vueI18n from '@intlify/vite-plugin-vue-i18n' // 설치
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite' // vite ver4 이상
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
// vueI18n({
// include: path.resolve(__dirname, './src/locales/**')
// }) // vueI18n 추가
VueI18nPlugin({
include: [path.resolve(__dirname, './src/locales/**')],
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
base: './'
})
// **.vue
<script setup lang="ts">
import { onMounted, computed } from 'vue'
import { StatusApi, statusApi } from '../apis/api/status.api'
import { useI18n } from 'vue-i18n'
const i18n = useI18n() // useI18n을 활용해서 변수, 데이터 등 사용할 수 있는데,
// 그냥 이렇게만 쓰면 error 뜸, main.ts의 createI18n 옵션에서 legacy 설정 false로!
const chartTitle = computed(() => {
return i18n.t('app.Chart.header.title')
})
onMounted(() => {
console.log('chartTitle ', chartTitle.value)
})
</script>
//main.ts
<script>
...
const i18n = createI18n<[MessageSchema], 'ko' | 'en'>({
// options
locale: 'ko',
fallbackLocale: 'en',
legacy: false, // <-- 이거!
messages: {
en: enUS,
ko: koKR
}
})
...
</script>
// chart.vue
<template>
<div class="chart">
<div>{{ $t('app.Chart.header.title') }}</div>
<div>
<high-chart :options="chartOptions" />
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, computed } from 'vue'
import { StatusApi, statusApi } from '../apis/api/status.api'
import { useI18n } from 'vue-i18n'
const i18n = useI18n()
const test = computed(() => {
return i18n.t('app.Chart.header.title')
})
const chartOptions = computed(() => {
return {
chart: {
type: 'column'
},
series: [
{
type: 'column',
name: test.value, // <---차트 컬럼명으로 활용
data: [1, 10, 20, 30, 50, 100, 20, 50],
color: 'blue'
},
{
type: 'column',
name: i18n.t('app.home.pageNames.tooling'), // 걍 바로 넣기
data: new Array(8).fill(100),
color: 'red'
}
]
}
})
onMounted(() => {
console.log('test', test.value)
})
</script>
화면 결과 “: 한국어 / 영어 설정시
vue-i18n 의 locales 활용 방식 예제
// en.json
{
"button": {
"add": "Add",
"delete": "Delete"
}
}
// ko.json
{
"button": {
"add": "추가",
"delete": "삭제"
}
}
// *.vue
<template>
<div>
<button>{{ $t('button.add') }}</button>
</div>
</template>
(출처: https://imkh.dev/vue-i18n/)
// 대분류(카테고리) > 페이지명 > 컴포넌트명(화면상영역 or UI) > 용어
// app > home > pageNames(=navigation) > selectLang
// ko.json
{
"app": {
"home": {
"pageNames": {
"selectLang": "언어 선택",
"tooling": "다듬기",
"ecosystem": "에코시스템",
"community": "커뮤니티",
"supportVue": "서포트 Vue"
}
},
"Chart": { "header": { "title": "차트 테스트" } }
}
}
(명령어 치면 알아서 **.json 형성해줬으면.. 언제손으로다쳐.. 하지만 엑셀 파일은 어쨌든 작성한번은 해야함 ㅠ)
(javascript 로 엑셀파일을 json 으로 변환 방식 서치)
excel.js 설치
npm install -D exceljs
변환하고자 하는 엑셀파일 src/i18n/i18n.xlsx (.gitignore 에도 추가해줌)
src/i18n/exceljs.js 파일생성 (발코드: 이 부분은 알아서 커스텀 하면 될듯(고수님들 지저분한 if문 말고 나은 코드가 있다면 언제든 피드백 대환영입니다 굽신굽신), 엑셀파일을 locales/ko.json 형태로 변환)
// src/i18n/exceljs.js
// convert xlsx file to json for vue-i18n
import Excel from 'exceljs'
import fs from 'fs'
try {
const workbook = new Excel.Workbook()
await workbook.xlsx.readFile('src/i18n/i18n.xlsx')
let output = {}
let langList = []
// 첫번째 시트 worksheets[0]
workbook.worksheets[0].eachRow((row, rowNumber) => {
if (rowNumber == 1) {
// output 언어 종류 설정
langList = row.values.slice(5) // excel 파일내 대분류,페이지명,컴포넌트명,용어 떼고 다음 컬럼부터 언어
langList.forEach((lang) => {
output[lang] = {}
})
// console.log('lang 종류', output)
}
if (rowNumber > 1) {
const rows = row.values
// console.log('rows', rows)
// [empty, 'app', 'home', 'pageNames', 'selectLang', '언어선택', 'select languages']
const category = rows[1]
const page = rows[2]
const component = rows[3]
const target = rows[4]
langList.forEach((lang, idx) => {
if (!output[lang][category]) {
output[lang][category] = {}
}
if (!output[lang][category][page]) {
output[lang][category][page] = {}
}
if (!output[lang][category][page][component]) {
output[lang][category][page][component] = {}
}
if (!output[lang][category][page][component][target]) {
output[lang][category][page][component][target] = {}
}
output[lang][category][page][component][target] = rows[idx + 5]
})
}
})
// 언어별 파일로 저장
langList.forEach((lang) => {
fs.writeFile(`src/locales/${lang}.json`, JSON.stringify(output[lang]), (err) => {
if (err) throw err
})
})
} catch (err) {
console.log('fail to convert xlsx to json', err)
}
스크립트 추가 및 실행
// package.json script 추가
{
...,
"scripts": {
...,
"i18n": "node src/i18n/exceljs.js"
},
...
}
// 터미널
npm run i18n // locales/en.json, ko.json 업데이트 됨
vue-i18n docs
https://github.com/intlify/vue-i18n-next/tree/master/packages/vue-i18n#readme
vue-i18n 사용 포스팅
https://serasome.com/@VueJS/_H6AyQgf1k
타입스크립트
vite-plugin-vue-i18n
https://github.com/intlify/vite-plugin-vue-i18n
intlify/vue-i18n-next docs