# 自製簡易版 I18N in Vue ###### tags: `w3HexSchool` . `vue` . `i18n` > 這篇文章主要說明如何在 Vue 中實現網頁上的 i18n,先備知識必須要已經基本會使用 Vue。 ## 建立 Vue 專案 我們直接用 vue-cli 的初始頁面來做練習: ![](https://i.imgur.com/zLiglLQ.png) 直接透過 vue-cli 建立 Vue 專案: ```bash= $ vue create vue-i18n-sandbox $ cd vue-i18n-sandbox $ npm start ``` ## 定義多語系字典檔 這時候就可以先定義這個字典檔。首先在 `./src` 資料夾內再新增一個 `i18n` 的資料夾,裡面分別放入 `en.json`, `ja.json`, `ko.json`, `tw.json`: ![](https://i.imgur.com/KA2k7ce.png) ```json= // ./src/i18n/en.json { "app": { "hello": "Hello , ${name}" } } ``` ```json= // ./src/i18n/ja.json { "app": { "hello": "こんにちは , ${name}" } } ``` ```json= // ./src/i18n/ko.json { "app": { "hello": "환영합니다 , ${name}" } } ``` ```json= // ./src/i18n/tw.json { "app": { "hello": "歡迎 , ${name}" } } ``` ## 建立 i18n 工具檔案 ( I18nUtil.js ) 在 `./src` 資料夾內新增一個 `utils` 的資料夾,並建立 `I18nUtil.js`: ```javascript= // ./src/utils/I18nUtil.js import _ from 'lodash'; import TwProperty from "../i18n/tw.json"; import EnProperty from "../i18n/en.json"; import JaProperty from "../i18n/ja.json"; import KoProperty from "../i18n/ko.json"; // util import StrFillTemplate from './StrFillTemplate.js'; // the translations const resources = { tw: { translation: TwProperty }, en: { translation: EnProperty }, ja: { translation: JaProperty }, ko: { translation: KoProperty } }; let defaultLanguage = 'tw'; export const translate = (key) => _.get(resources[defaultLanguage].translation, key); export const translateWithParams = (key, params = {}) => StrFillTemplate(_.get(resources[defaultLanguage].translation, key), params); export const setDefaultLanguage = (language) => defaultLanguage = language; export const getDefaultLanguage = () => defaultLanguage; ``` ## StrFillTemplate.js - 讓 `name` 參數在 `runtime` 可以被取代 在 `./src/utils` 資料夾內建立 `StrFillTemplate.js`: ```javascript= // ./src/utils/StrFillTemplate.js /** * 將 模板字串 塞入 參數值. * https://stackoverflow.com/questions/30003353/can-es6-template-literals-be-substituted-at-runtime-or-reused#answer-37217166 * @constructor * @param {string} templateString - template literals . * @param {object} [templateVars={}] - 參數名稱 . */ export default (templateString, templateVars = {}) => { const args = '{' + Object.keys(templateVars).join(',') + '}'; // args = '{ name , value }' const body = "return `" + templateString + "`;"; // new Function 學習 : https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Function return new Function(args, body).call(null, templateVars); // call 教學 : https://ithelp.ithome.com.tw/articles/10195896 }; ``` ## 撰寫切換語言的功能 在 `HelloWorld.vue` 的地方,撰寫四個按鈕可以來切換 `locale`: ```javascript= // ./src/components/HelloWorld.vue <template> <div class="hello"> <h1>{{ msg }}</h1> <div class="container"> <!-- 建立四顆按鈕可以切換 "locale" --> <button @click="changeLocale('en')">English</button> <button @click="changeLocale('tw')">中文</button> <button @click="changeLocale('ja')">日本語</button> <button @click="changeLocale('ko')">한국어</button> </div> </div> </template> <script> import {translateWithParams as t, setDefaultLanguage} from "../utils/I18nUtil"; export default { name: 'HelloWorld', beforeCreate: function () { this.msg = t('app.hello', {name: '小明'}); }, methods: { changeLocale: function (locale) { setDefaultLanguage(locale); this.msg = t('app.hello', {name: '小明'}); } }, data: function () { return { msg: this.msg } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> .container { display: flex; justify-content: center; } button { height: 30px; } </style> ``` 這時候的畫面會像這樣: <iframe src="https://codesandbox.io/embed/vue-i18n-sandbox-0i1i9?fontsize=14&hidenavigation=1&theme=dark" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" title="vue-i18n-sandbox" allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin" ></iframe> ## 參考資料 - [[筆記] 使用 react-intl 在 React 實作多語系功能 i18n, internationalization](https://pjchender.blogspot.com/2019/07/react-intl-react-i18n.html) - [Vue I18n 實作多國語系 by Lynn](https://clhuang224.github.io/TechBlog/2020/03/15/20200315-vue-i18n/) - [vue-i18n-sandbox](https://github.com/kuanhsuh/vue-i18n-sandbox) ## 其他套件 [vue-i18n](http://kazupon.github.io/vue-i18n/introduction.html)