vue-i18n (다국어 지원)

Sarahsea 사라씨·2023년 7월 4일
0

grew_Log

목록 보기
1/1
post-thumbnail

vue-i18n 도입기 (아직 도입은 안했다)

! vue-i18n 설치 및 테스트 해본 것 - 개인기록으로 남김 -을 공유

! 설명이 불친절 할 or 없을 수 있음

! 테스트해보고 작성은 나중에 한거라 빠진 내용 있을 수 있음

! 이대로 따라해도 안될 수 있음

개요

  • i18n 이란

    단순히 번역을 하는 개념이 아니라 좀 더 폭넓은 개념,
    “국제화” ; 현지화, 양방향 텍스트 지원, 숫자/날짜/주소 등 표현 방식, 문화적 지원

    스샷 + 참고: https://velog.io/@shallwedance/i18n-l10n이란

  • 사용하게 된 배경

    • 중소형 ESS 현장관리APP 및 원격관리 등 UI 개발시 다국어 지원 고려가 필요하다 → NEEDS!
    • 조사 = 구글링
      https://okky.kr/questions/1010183 다국어 페이지 만들때 다들 어떻게 하시나요? → i18n !
  • vue-i18n 이란

    • i18n 을 적용하는 라이브러리 있겠지~ → 검색 → 응, 있어~ react-i18n → vue도 있겠네? vue-i18n 써볼까?

활용

1. 설정 및 기본 활용 (how to use 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 에 몇몇 키 추가해서 ) 화면 결과

2. with typescript

기존 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: './'
})

3. 변수 활용 (vue 3 composition api )

// **.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>

4. with 차트 라이브러리

  • highchart options
// 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>

화면 결과 “: 한국어 / 영어 설정시

번외) locales 파일 자동화 하기

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/)

1. 용어집 (excel) 로 관리하기 원함 + 대충 원하는 형태 (분류가 필요)

// 대분류(카테고리) > 페이지명 > 컴포넌트명(화면상영역 or UI) > 용어 
// app > home > pageNames(=navigation) > selectLang

// ko.json
{
  "app": {
    "home": {
      "pageNames": {
        "selectLang": "언어 선택",
        "tooling": "다듬기",
        "ecosystem": "에코시스템",
        "community": "커뮤니티",
        "supportVue": "서포트 Vue"
      }
    },
    "Chart": { "header": { "title": "차트 테스트" } }
  }
}

2. npm script로 관리하고 싶다

(명령어 치면 알아서 **.json 형성해줬으면.. 언제손으로다쳐.. 하지만 엑셀 파일은 어쨌든 작성한번은 해야함 ㅠ)

3-1. how to convert xlsx to json

(javascript 로 엑셀파일을 json 으로 변환 방식 서치)

  • xlsxToJson ( docs 불편 나가리)
  • excel.js

3-2. 결과

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://imkh.dev/vue-i18n/

https://serasome.com/@VueJS/_H6AyQgf1k

타입스크립트

vite-plugin-vue-i18n

https://github.com/intlify/vite-plugin-vue-i18n

intlify/vue-i18n-next docs

profile
생각하는 사람

0개의 댓글