Skip to content

Vue I18n

Vue I18n is internationalization plugin for Vue.js.

in JavaScript

JavaScript에서 직접 사용하고 싶다면:

this.$t("message.hello")

Single file components

Vue CLI 3.x를 사용한다면:

vue add i18n

그렇지 않다면 vue-i18n-loader를 직접 설치하면 된다:

yarn add -D @intlify/vue-i18n-loader

WARNING

Vue CLI를 사용할 경우, 직접 설정 파일을 구성하면 정상적으로 작동하지 않을 가능성이 높다 ... -_- ;;

YAML Example

<i18n locale="en" lang="yaml">
  hello: "hello world!"
</i18n>

<i18n locale="ja" lang="yml">
  hello: "こんにちは、世界!"
</i18n>

JSON 파일 포함

<i18n src="@/translations/common/lang.json"></i18n>
<i18n locale="ja" lang="yml">
  hello: "こんにちは、世界!"
</i18n>

Simple Example

HTML:

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-i18n/dist/vue-i18n.js"></script>

<div id="app">
  <p>{{ $t("message.hello") }}</p>
</div>

JavaScript:

// If using a module system (e.g. via vue-cli), import Vue and VueI18n and then call Vue.use(VueI18n).
// import Vue from 'vue'
// import VueI18n from 'vue-i18n'
//
// Vue.use(VueI18n)

// Ready translated locale messages
const messages = {
  en: {
    message: {
      hello: 'hello world'
    }
  },
  ja: {
    message: {
      hello: 'こんにちは、世界'
    }
  }
}

// Create VueI18n instance with options
const i18n = new VueI18n({
  locale: 'ja', // set locale
  messages, // set locale messages
})


// Create a Vue instance with `i18n` option
new Vue({ i18n }).$mount('#app')

// Now the app has started!

Vue 컴포넌트가 아닌 곳에서 사용하는 방법

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

Vue.use(VueI18n);

const messages = {
    en: {
        message: {
            hello: 'hello world',
        },
    },
};

const i18n = new VueI18n({
    locale: 'en',
    messages,
});

export default i18n;

Import i18n in your store, then you can use the .t() function to translate or any other.

store.js:

import i18n from 'path/to/i18n';

const state = {
    title: i18n.t('title'),
};

HTML 태그 포함 방법

템플릿에서 <i18n> 태그를 사용해야 한다.

우선 다음 문장을 적용 하는 방법을 알아보자.

No results matching "<strong>{{ search }}</strong>". Press <kbd>enter</kbd> to create a new one

다음과 같이 이름 있는 인자로 추가한다. i18n 문자열에 HTML TAG를 포함해선 안된다.

<i18n lang="yaml">
en:
  no_features: "No results matching \"{search}\". Press {key} to create a new one."

ko:
  no_features: "\"{search}\" 와 일치하는 결과가 없습니다. {key} 키를 눌러 새 항목을 만듭니다."
</i18n>

그리고 사용할 때, 템플릿에서 <i18n>를 사용하여 추가해야 한다.

<template>
  <!-- ... -->
  <i18n path="no_features" tag="span">
    <template #search>
      <strong>{{ searchFeature }}</strong>
    </template>
    <template #key>
      <kbd>enter</kbd>
    </template>
  </i18n>
  <!-- ... -->
</template>

Troubleshooting

언어 변환이 적용되지 않는 현상

몇 가지 확인 사항이 있다.

  • 인스턴스가 생성되는 위치를 잘 생각해보자. 생성자 같은 곳에 추가하면 안된다. 실제 호출되는 위치에 코드를 삽입해야 한다.

Fall back to translate the keypath 'message' with root locale

[vue-i18n] Value of key 'message.greeting' is not a string!
[vue-i18n] Fall back to translate the keypath 'message.greeting' with root locale.

위의 경고가 시끄럽다면, VueI18n 인스턴스 초기화시 silentFallbackWarn: true 옵션을 추가하면 된다.

WebStorm SFC i18n yaml error

WebStorm에서 Single-file component로, vue-i18n을 yaml로 사용할 경우 syntax error 로 판단한다.

<i18n lang="yaml">
_languages: &languages
  en: "English"
  ko: "한국어"

en:
  <<: *languages
  header: "Translations"

ko:
  <<: *languages
  header: "언어선택"
</i18n>

정상적으로 컴파일 되는 코드이다.

따라서 다음과 같은 방법으로 우회한다.

언어 변경시 적용되지 않는 현상

vuetify의 현재 언어를 변경하고 싶을 때, 아래와 같은 방법으로 변경한다.

this.$vuetify.lang.current = lang;
this.$i18n.locale = lang;

저렇게 했음에도 자동으로 언어가 변경되지 않는다면, 하위 컴포넌트에서 변경했는지 확인해 보자. 언어변경 후 화면에 바로 적용되는 범위는 하위 컴포넌트들만 되는듯 하다 <- 확인 필요!

확인 해보니... 하위 컴포넌트 문제는 아니고,,, 반응형 참조 문제로 추정된다.

  • vue-i18n-loader를 사용하여 vue-i18n를 컴포넌트에 지역적으로 사용.
  • this.$i18n.locale = 'ko'; 이렇게 사용한 컴포넌트에 한정된 적용이 이루어짐.
  • 그래서, 모든 컴포넌트에서 this.$i18n.locale = 'ko'; 를 사용하여 반응형 이벤트가 발생되도록 해야 한다.

이것도 확인 필요하다 !!!

임시적으로 다음과 같이 수정하였다.

BaseI18n.ts 파일을 다음과 같이 만들었다.

import { Vue, Watch } from 'vue-property-decorator';

export default class BaseI18n extends Vue {
    @Watch('$vuetify.lang.current')
    updateI18n(newVal: string, oldVal: string) {
        console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
        this.$i18n.locale = newVal;
    }
}

컴포넌트가 아니다 !!! 컴포넌트가 !

<i18n>를 사용하는 모든 컴포넌트로 가서 Vue 대신, 위의 클래스를 상속 받는다.

<script lang="ts">
import BaseI18n from '@/translations/BaseI18n';
import { Component, Prop, Emit, Watch } from 'vue-property-decorator';
import MenuTranslate from '@/components/MenuTranslate.vue';
import { mdiThemeLightDark, mdiApi } from '@mdi/js';

@Component({
  components: {
    MenuTranslate
  }
})
export default class ButtonsConfigPublic extends BaseI18n {
  // ...
}

언어를 변경해야 하는 부분에서 다음과 같이 실행한다.

this.$vuetify.lang.current = 'ko';

그럼 @Watch를 사용하여, this.$vuetify.lang.current를 감시하고 있기 때문에, 해당 컴포넌트의 언어가 일괄 변경된다.

See also

Favorite site