Browse Source

2023-10-6

zhang 1 year ago
parent
commit
f2d3c90347
40 changed files with 16159 additions and 926 deletions
  1. 77 0
      components/footer/footer.vue
  2. 35 0
      components/footer/list.js
  3. 25 0
      libs/i18n/index.js
  4. 918 0
      libs/i18n/lang/cn.json
  5. 973 0
      libs/i18n/lang/en.json
  6. 916 0
      libs/i18n/lang/tw.json
  7. 4 2
      main.js
  8. 25 11
      pages.json
  9. 5 0
      pages/index/index.vue
  10. 5 8
      pages/index/pledge.vue
  11. 0 119
      pages/information/information.vue
  12. 0 229
      pages/pledge/pledge.vue
  13. 0 554
      pages/user/user.vue
  14. 1645 0
      plugin/vue-i18n/CHANGELOG.md
  15. 20 0
      plugin/vue-i18n/LICENSE
  16. 73 0
      plugin/vue-i18n/README.md
  17. 160 0
      plugin/vue-i18n/decls/i18n.js
  18. 30 0
      plugin/vue-i18n/decls/module.js
  19. 2151 0
      plugin/vue-i18n/dist/vue-i18n.common.js
  20. 2104 0
      plugin/vue-i18n/dist/vue-i18n.esm.browser.js
  21. 0 0
      plugin/vue-i18n/dist/vue-i18n.esm.browser.min.js
  22. 2149 0
      plugin/vue-i18n/dist/vue-i18n.esm.js
  23. 2157 0
      plugin/vue-i18n/dist/vue-i18n.js
  24. 5 0
      plugin/vue-i18n/dist/vue-i18n.min.js
  25. 176 0
      plugin/vue-i18n/package.json
  26. 101 0
      plugin/vue-i18n/src/components/interpolation.js
  27. 70 0
      plugin/vue-i18n/src/components/number.js
  28. 112 0
      plugin/vue-i18n/src/directive.js
  29. 33 0
      plugin/vue-i18n/src/extend.js
  30. 114 0
      plugin/vue-i18n/src/format.js
  31. 1065 0
      plugin/vue-i18n/src/index.js
  32. 40 0
      plugin/vue-i18n/src/install.js
  33. 139 0
      plugin/vue-i18n/src/mixin.js
  34. 302 0
      plugin/vue-i18n/src/path.js
  35. 169 0
      plugin/vue-i18n/src/util.js
  36. 276 0
      plugin/vue-i18n/types/index.d.ts
  37. 34 0
      plugin/vue-i18n/vetur/attributes.json
  38. 20 0
      plugin/vue-i18n/vetur/tags.json
  39. 30 2
      store/index.js
  40. 1 1
      uni.scss

+ 77 - 0
components/footer/footer.vue

@@ -0,0 +1,77 @@
+<template>
+	<view class="footer flex p-y-xs2 bg-tab-nav">
+		<view class="flex-fill" :class="{ 'router-link-active': tab == item.tel }"
+			v-for="item in navList" :key="item.tel" @click="tabChange(item.tel)">
+			<view class="icon">
+				<img class="h-15" v-if="tab == item.tel" :src="item.activeIcon" alt="" />
+				<img class="h-15" v-else :src="item.icon" alt="" />
+			</view>
+			<view class="fn-12">{{ $t(item.label) }}</view>
+		</view>
+	</view>
+</template>
+<script>
+	import {
+		navList
+	} from "./list.js";
+	export default {
+		props: {
+			tab: {
+				type: String,
+				default: "index",
+			},
+		},
+		data() {
+			return {
+				navList: navList(this),
+			};
+		},
+		created() {
+			// console.log(navList,'navList');
+		},
+		methods: {
+			tabChange(v) {
+				uni.switchTab({
+					url: "/pages/index/" + v,
+				});
+				// console.log(v);
+				// console.log(this.$router);
+			},
+		},
+	};
+</script>
+<style lang="scss" scoped>
+	.flex-fill{
+		text-align: center;
+		line-height: 1;
+	}
+	.p-y-xs2 {
+		padding: 5px 10px;
+	}
+	.h-15{
+		height: 20px;
+		width: 20px;
+	}
+	.footer {
+		box-shadow:  0px -7px 20px 0px rgba(37, 37, 48, 0.83);
+		position: fixed;
+		bottom: 0;
+		width: 100%;
+		z-index: 999 !important;
+		// height: 102rpx;
+		color: rgba(#fff, 0.3);
+		justify-content: space-around !important;
+	}
+	.fn-12{
+		margin-top: 4px;
+		font-size: 10px;
+	}
+	.router-link-active {
+		// color: $theme-1;
+		color:#FEB041;
+	}
+
+	.bg-tab-nav {
+		background-color: #000000;
+	}
+</style>

+ 35 - 0
components/footer/list.js

@@ -0,0 +1,35 @@
+export function navList(that) {
+  return [
+    {
+      label: "base.d0",
+      tel: "index",
+      icon: "static/tabBar/shouye.png",
+      activeIcon: "static/tabBar/shouye-home.png",
+    },
+   
+    {
+      label: "base.a3",
+      tel: "pledge",
+      icon: "static/tabBar/baoya.png",
+      activeIcon: "static/tabBar/baoya-home.png",
+    },
+	{
+	  label: "exchange.a0",
+	  tel: "entertainment",
+	  icon: "static/tabBar/huyu.png",
+	  activeIcon: "static/tabBar/huyu-home.png",
+	},
+    {
+      label: "exchange.a2",
+      tel: "information",
+      icon: "static/tabBar/zixun.png",
+      activeIcon: "static/tabBar/zixun-home.png",
+    },
+    {
+      label: "base.d2",
+      tel: "user",
+      icon: "static/tabBar/my.png",
+      activeIcon: "static/tabBar/my-home.png",
+    },
+  ];
+}

+ 25 - 0
libs/i18n/index.js

@@ -0,0 +1,25 @@
+import vue from "vue";
+import VueI18n from "vue-i18n";
+vue.use(VueI18n)
+
+// 获取语言
+const requireComponent = require.context(
+    // 其组件目录的相对路径
+    './lang',
+    // 是否查询其子目录
+    true,
+    // 匹配基础组件文件名的正则表达式
+    /[a-zA-Z]\w+\.(json)$/
+)
+let messages = new Object();
+requireComponent.keys().forEach(fileName => {
+    // 获取组件的PascalCase命名
+    const componentName = fileName.split('/').pop().replace(/\.\w+$/, '');
+    messages[componentName] = requireComponent(fileName);
+})
+// 语言注入
+let i18n = new VueI18n({
+    locale: uni.getStorageSync('lang')||'tw',
+    messages: messages
+})
+export default i18n;

+ 918 - 0
libs/i18n/lang/cn.json

@@ -0,0 +1,918 @@
+{
+	"home":{
+		"k1": "最新价格",
+		"b0": "24H涨跌幅",
+		"b8": "名称",
+		"d0": "首页"
+	},
+	"add": {
+		"kt": "Airdrop",
+		"ck": "deposit",
+		"a1": "选择付款方式",
+		"a2": "Line",
+		"a3":"付款数量",
+		"a4":"认购数量",
+		"a5":"信用评分"
+	},
+	"miao": {
+		"a1": "秒合约",
+		"a2": "做多",
+		"a3": "做空",
+		"a4": "选择到期时间",
+		"a5": "买入数量",
+		"a6": "手续费",
+		"a7": "可用USDT",
+		"a8": "下单成功",
+		"b1": "购买记录",
+		"b2": "做多",
+		"b3": "做空",
+		"b4": "下单价(元)",
+		"b5": "交易金额",
+		"b6": "预计收益率",
+		"b7": "交易周期",
+		"b8": "结束价",
+		"b9": "超时反馈",
+		"b10": "倒计时"
+	},
+	"flash": {
+		"a1": "闪兑",
+		"a2": "从",
+		"a3": "可用",
+		"a4": "至",
+		"a5": "询价",
+		"b1": "订单确认",
+		"b2": "兑换",
+		"b3": "收到",
+		"b4": "支付渠道",
+		"b5": "现货钱包",
+		"b6": "类型",
+		"b7": "市价",
+		"b8": "汇率",
+		"b9": "确认",
+		"c1": "余额不足,请充值",
+		"c2": "返回",
+		"c3": "刷新",
+		"c4": "请输入正确兑换金额",
+		"c5": "兑换币种异常",
+		"c6": "兑换成功",
+		"d1": "兑换记录",
+		"d2": "支出",
+		"d3": "到账"
+	},
+	"contribution": {
+		"title": "捐款",
+		"a1": "爱心公益!捐款你我做起!",
+		"a2": "呼吁广大用户发挥爱心及激发人道主义为乌克兰加油并进行捐款,用爱心为战争画上句号,使乌克兰早日重建家园。DWF交易所收到的捐款资金将全数净捐给国际红十字委员会、Guzema Foundation、Serhiy Prytula Foundation。盼望地球村携手合作共创美好的和平世界。",
+		"a3": "DWF将平台净利手续费1%捐出,您捐赠的金额DWF交易所将1:1的USDT返送至您的交易所钱包!为乌克兰加油!",
+		"a4": "扫描二维码完成付款",
+		"a5": "复制地址",
+		"a6": "目前捐款金额",
+		"a7": "本期捐款截止",
+		"a8": "未捐款",
+		"a9": "已捐款",
+		"b1": "捐款订单",
+		"b2": "尊贵的用户谢谢您的爱心与支持 DWF慈善基金团队正在审核您的汇款资金 并在一个小时内返还您的捐款金额 如有任何问题请立即咨询线上客服",
+		"b3": "确认",
+		"b4": "详情视频",
+		"c1": "捐款记录",
+		"c2": "订单号",
+		"c3": "提交时间",
+		"c4": "捐款方式",
+		"c5": "地址",
+		"c6": "捐款金额",
+		"d1": "详情",
+		"e1":"已捐款金额",
+		"e2":"请输入金额"
+	},
+	"common": {
+		"error1": "您的账号异常,请联系客服人员",
+		"D": "日",
+		"M": "月",
+		"Y": "年",
+		"add": "添加",
+		"address": "地址",
+		"all": "所有",
+		"amout": "数量",
+		"cancel": "取消",
+		"check": "审核",
+		"code": "验证码",
+		"confirm": "确定",
+		"date": "日期",
+		"detail": "详情",
+		"email": "邮箱",
+		"enter": "请输入",
+		"error": "失败",
+		"getCode": "获取验证码",
+		"h": "时",
+		"loadMore": "加载更多",
+		"m": "分",
+		"money": "金额",
+		"more": "更多",
+		"notData": "暂无数据",
+		"notMore": "没有更多了",
+		"phone": "手机",
+		"requestError": "网络繁忙,请稍后再试",
+		"s": "秒",
+		"save": "保存",
+		"select": "请选择",
+		"sendSuccess": "发送成功",
+		"sms": "短信",
+		"submit": "提交",
+		"success": "成功",
+		"tips": "温馨提示",
+		"total": "总额",
+		"type": "类型",
+		"copy": "复制",
+		"light": "白",
+		"dark": "黑",
+		"service": "客服",
+		"toDwon": "是否前往下载页",
+		"a0": "请输入申购码",
+		"a1": "复制成功",
+		"a2": "复制失败",
+		"a3": "申购记录",
+		"a4": "支付金额",
+		"a5": "到账数量",
+		"a6": "账号",
+		"a7": "充值数量",
+		"a8": "支付凭证",
+		"a9": "请输入充值数量",
+		"b0": "请上传支付凭证",
+		"b1": "购买{amount}枚{name}代币可获{rate}%奖励",
+		"b2": "申购活动",
+		"cancelButtonText": "取消",
+		"confirmButtonText": "确认"
+	},
+	"base": {
+		"a0": "标题",
+		"a1": "返回",
+		"a2": "更多",
+		"a3": "行情",
+		"a4": "期权",
+		"a5": "打新专区",
+		"a6": "会员",
+		"a7": "学院",
+		"a8": "交易对",
+		"a9": "最新价",
+		"b0": "涨跌幅",
+		"b1": "点击登录",
+		"b2": "欢迎来到",
+		"b3": "请登录",
+		"b4": "升级",
+		"b5": "充币",
+		"b6": "提币",
+		"b7": "推广",
+		"b8": "抵扣手续费",
+		"b9": "可用",
+		"c0": "购买",
+		"c1": "我的委托",
+		"c2": "身份认证",
+		"c3": "安全中心",
+		"c4": "消息通知",
+		"c5": "提币地址",
+		"c6": "设置",
+		"c7": "自选",
+		"c8": "添加成功",
+		"c9": "取消成功",
+		"d0": "首页",
+		"d1": "交易",
+		"d2": "资产",
+		"d3": "请输入搜索关键词",
+		"d4": "全部",
+		"d5": "主板",
+		"d6": "总资产折合",
+		"d7": "资金账户",
+		"d8": "划转",
+		"d9": "搜索币种",
+		"e0": "隐藏",
+		"e1": "余额资产",
+		"e2": "冻结",
+		"e3": "折合",
+		"e4": "合约账户",
+		"e5": "合约折合",
+		"e6": "矿工等级",
+		"e7": "矿工",
+		"e8": "APP",
+		"e9": "签到",
+		"f0": "立即签到",
+		"f1": "每天签到获得",
+		"f2": "连续签到7天 则额外赠送",
+		"f3": "买币",
+		"f4": "ETH Layer2",
+		"f5": "邀请奖励",
+		"f6": "奖励自动派送",
+		"f7": "如果中断签到 则不可获得奖励",
+		"f8": "24H量",
+		"f9": "捐款",
+		"g1": "闪兑",
+		"g2": "关于我们",
+		"g3": "版本6.0.7",
+		"g4": "帮助中心",
+		"g5": "未绑定",
+		"g6": "语言切换",
+		"g7": "交易对",
+		"g8": "价格",
+		"g9": "涨幅",
+		"h0": "已绑定",
+		"h1": "维护更新中",
+		"h2": "永续合约"
+	},
+	"aboutUs": {
+		"a0": "关于我们",
+		"a1": "和"
+	},
+	"accountSettings": {
+		"a0": "账号设置",
+		"a1": "头像",
+		"a2": "昵称",
+		"a3": "主账号",
+		"a4": "手机号",
+		"a5": "解绑",
+		"a6": "绑定",
+		"a7": "邮箱绑定",
+		"a8": "切换账户",
+		"a9": "退出登录",
+		"b0": "修改昵称",
+		"b1": "请输入昵称",
+		"b2": "语言"
+	},
+	"assets": {
+		"a0": "提币地址管理",
+		"a1": "地址簿可以用来管理您的常用地址,往地址簿中存在的地址发起提币时,无需进行多重校验。",
+		"a2": "已支持自动提币,使用{name}提币时,只允许网地址簿中存在的地址发起提币。",
+		"a3": "删除地址",
+		"a4": "添加地址",
+		"a5": "请选择要删除的地址",
+		"a6": "是否删除当前选中地址",
+		"a7": "流水",
+		"a8": "总额",
+		"a9": "可用",
+		"b0": "冻结",
+		"b1": "资金账户",
+		"b2": "合约账户",
+		"b3": "杠杆账户",
+		"b4": "理财账户",
+		"b5": "请输入搜索关键词",
+		"b6": "提币",
+		"b7": "请选择链类型",
+		"b8": "提币地址",
+		"b9": "请输入地址",
+		"b10": "请输入搜索关键词",
+		"c0": "数量",
+		"c1": "余额",
+		"c2": "请输入数量",
+		"c3": "全部",
+		"c4": "手续费",
+		"c5": "请仔细检查并输入正确的提币钱包地址。",
+		"c6": "发送不对应的数字货币到钱包地址会造成永久性的损失。",
+		"c7": "提币手续费将从提币数量中扣除。",
+		"c8": "提币记录",
+		"c9": "时间",
+		"d0": "状态",
+		"d1": "审核中",
+		"d2": "成功",
+		"d3": "失败",
+		"d4": "查看更多",
+		"d5": "提交成功,正在审核",
+		"d6": "编辑",
+		"d7": "添加",
+		"d8": "地址",
+		"d9": "请输入或粘贴地址",
+		"e0": "备注",
+		"e1": "请输入备注",
+		"e2": "请填写地址",
+		"e3": "请填写备注",
+		"e4": "操作成功",
+		"e5": "充币",
+		"e6": "扫描上方二维码获取充币地址",
+		"e7": "充币地址",
+		"e8": "充币数量",
+		"e9": "请输入充币数量",
+		"f0": "此地址是您最新的充值地址,当系统收到充值时,将进行自动入账。",
+		"f1": "转账需要由整个区块链网络进行确认,到达{num}个网络确认时,您的{name}将被自动存入账户中。",
+		"f2": "个网络确认时,您的",
+		"f3": "请只发送{name}到此地址,发送其他数字货币到此地址会造成永久性的损失。",
+		"f4": "充币记录",
+		"g1": "地址划转",
+		"g2": "银行卡汇款",
+		"g3": "信用卡支付",
+		"g4": "复制地址",
+		"h1":"请输入带有国家代码的电话号码"
+	},
+	"auth": {
+		"a0": "身份认证",
+		"a1": "实名认证",
+		"a2": "未认证",
+		"a3": "已认证",
+		"a4": "高级认证",
+		"a5": "审核中",
+		"a6": "认证失败",
+		"a7": "国籍",
+		"a8": "请选择国籍",
+		"a9": "真实姓名",
+		"b0": "请输入真实姓名",
+		"b1": "证件号码",
+		"b2": "请输入证件号码",
+		"b3": "确认",
+		"b4": "认证成功",
+		"b5": "请上传证件正面照片",
+		"b6": "请上传证件背面",
+		"b7": "请上传手持证件照",
+		"b8": "确保照片清晰无水印,且上半身完整",
+		"b9": "文件尺寸过大,不得超过",
+		"c0": "文件类型错误",
+		"c1": "上传成功",
+		"c2": "请上传证件背面照",
+		"c3": "请上传证件正面照",
+		"c4": "上传成功,请等待审核"
+	},
+	"exchange": {
+		"a0": "币币",
+		"a1": "申购",
+		"a2": "合约",
+		"a3": "交易",
+		"a4": "当前委托",
+		"a5": "历史委托",
+		"a6": "添加成功",
+		"a7": "取消成功",
+		"a8": "发行总量",
+		"a9": "流通总量",
+		"b0": "发行价格",
+		"b1": "发行时间",
+		"b2": "白皮书地址",
+		"b3": "官网地址",
+		"b4": "简介",
+		"b5": "买",
+		"b6": "卖",
+		"b7": "委托价",
+		"b8": "类型",
+		"b9": "限价交易",
+		"c0": "市价交易",
+		"c1": "已成交",
+		"c2": "总计",
+		"c3": "买入",
+		"c4": "卖出",
+		"c5": "数量",
+		"c6": "在最佳市场价格成交",
+		"c7": "总价",
+		"c8": "可用数量",
+		"c9": "总值",
+		"d0": "登录",
+		"d1": "分时图",
+		"d2": "价格",
+		"d3": "最新成交",
+		"d4": "时间",
+		"d5": "方向",
+		"d6": "限价",
+		"d7": "市价",
+		"d8": "请输入价格",
+		"d9": "请输入数量",
+		"e0": "请输入总价",
+		"e1": "下单成功",
+		"e2": "平均价格",
+		"e3": "最高",
+		"e4": "最低",
+		"e5": "量",
+		"e6": "买卖盘",
+		"e7": "币种信息",
+		"e8": "分钟",
+		"e9": "小时",
+		"e10": "分钟",
+		"f0": "天",
+		"f1": "周",
+		"f2": "月",
+		"f3": "买价",
+		"f4": "卖价",
+		"f5": "币币交易",
+		"f6": "请输入搜索关键词",
+		"f7": "交易对",
+		"f8": "最新价",
+		"f9": "涨跌幅",
+		"g0": "自选",
+		"g1": "我的委托",
+		"g2": "撤销委托",
+		"g3": "操作",
+		"g4": "撤销",
+		"g5": "是否撤销当前委托",
+		"g6": "撤销成功",
+		"g7":"分时"
+	},
+	"option": {
+		"a0": "期权",
+		"a1": "距离交割",
+		"a2": "看多",
+		"a3": "看空",
+		"a4": "收益率",
+		"a5": "购买",
+		"a6": "多",
+		"a7": "空",
+		"a8": "当前",
+		"a9": "下期",
+		"b0": "看平",
+		"b1": "涨幅选择",
+		"b2": "收益率",
+		"b3": "购买数量",
+		"b4": "请输入数量",
+		"b5": "余额",
+		"b6": "预计收益",
+		"b7": "立即购买",
+		"b8": "涨",
+		"b9": "平",
+		"c0": "跌",
+		"c1": "购买成功",
+		"c2": "详情",
+		"c3": "订单号",
+		"c4": "开盘价",
+		"c5": "收盘价",
+		"c6": "买入时间",
+		"c7": "买入数量",
+		"c8": "购买类型",
+		"c9": "状态",
+		"d0": "交割结果",
+		"d1": "结算数量",
+		"d2": "交割时间",
+		"d3": "查看更多",
+		"d4": "购买期权",
+		"d5": "等待交割",
+		"d6": "我的交割",
+		"d7": "交割记录",
+		"d8": "分钟",
+		"d9": "小时",
+		"d10": "分时",
+		"e0": "天",
+		"e1": "周",
+		"e2": "月",
+		"e3": "方向",
+		"e4": "涨跌幅",
+		"e5":"请输入1000~6000",
+		"e6":"请输入10000-30000",
+		"e7":"请输入60000-100000",
+		"e8":"请输入200000-300000",
+		"e9":"请输入600000-1000000",
+		"e10":"请输入超过3,000,000"
+		
+	},
+	"purchase": {
+		"a0": "发行价",
+		"a1": "申购币种",
+		"a2": "预计上线时间",
+		"a3": "开始申购时间",
+		"a4": "结束申购时间",
+		"a5": "申购",
+		"a6": "请选择申购币种",
+		"a7": "购买数量",
+		"a8": "请输入申购数量",
+		"a9": "全部",
+		"b0": "立即申购",
+		"b1": "申购周期",
+		"b2": "项目预热",
+		"b3": "开始申购",
+		"b4": "结束申购",
+		"b5": "公布结果",
+		"b6": "项目详情",
+		"b7": "是否使用",
+		"b8": "购买",
+		"b9": "申购成功",
+		"d1":"付款方式",
+		"d2":"请输入正确的金额"
+	},
+	"reg": {
+		"a0": "手机注册",
+		"a1": "邮箱注册",
+		"a2": "手机",
+		"a3": "请输入手机号",
+		"a4": "邮箱",
+		"a5": "请输入邮箱号",
+		"a6": "验证码",
+		"a7": "请输入验证码",
+		"a8": "密码",
+		"a9": "请输入密码",
+		"b0": "确认密码",
+		"b1": "请确认密码",
+		"b2": "推荐人",
+		"b3": "请输入推荐人",
+		"b4": "选填",
+		"b5": "您已同意",
+		"b6": "用户协议",
+		"b7": "并了解我们的",
+		"b8": "隐私协议",
+		"b9": "注册",
+		"c0": "已有账号?",
+		"c1": "立即登录",
+		"c2": "请阅读并同意协议",
+		"c3": "请填写手机号",
+		"c4": "请填写邮箱号",
+		"c5": "注册成功"
+	},
+	"safe": {
+		"a0": "解绑",
+		"a1": "绑定",
+		"a2": "邮箱",
+		"a3": "邮箱号",
+		"a4": "请输入邮箱号",
+		"a5": "邮箱验证码",
+		"a6": "请输入验证码",
+		"a7": "验证码",
+		"a8": "解绑成功",
+		"a9": "绑定成功",
+		"b0": "忘记登录密码",
+		"b1": "账号",
+		"b2": "请输入手机/邮箱号",
+		"b3": "新密码",
+		"b4": "请输入新密码",
+		"b5": "确认密码",
+		"b6": "请确认密码",
+		"b7": "确认修改",
+		"b8": "请输入正确的邮箱号",
+		"b9": "谷歌验证器",
+		"c0": "操作方法:下载并打开谷歌验证器,扫描下方二维码或手动输入秘钥添加验证令牌。",
+		"c1": "复制密钥",
+		"c2": "我已经妥善保存密钥,丢失后将不可找回。",
+		"c3": "下一步",
+		"c4": "短信验证码",
+		"c5": "谷歌验证码",
+		"c6": "确认绑定",
+		"c7": "安全中心",
+		"c8": "登录密码",
+		"c9": "修改",
+		"d0": "设置",
+		"d1": "交易密码",
+		"d2": "手机",
+		"d3": "修改成功",
+		"d4": "手机号",
+		"d5": "请输入手机号",
+		"d6": "请输入短信验证码",
+		"d7": "关闭",
+		"d8": "开启",
+		"d9": "验证",
+		"e0": "短信",
+		"e1": "关闭成功",
+		"e2": "开启成功",
+		"e3": "确认",
+		"e4": "设置成功",
+		"f1":"密码和确认密码不匹配",
+		"f2":"验证码错误"
+	},
+	"transfer": {
+		"a0": "划转记录",
+		"a1": "成功",
+		"a2": "数量",
+		"a3": "方向",
+		"a4": "账户资产",
+		"a5": "合约账户",
+		"a6": "杠杆账户",
+		"a7": "理财账户",
+		"a8": "划转",
+		"a9": "从",
+		"b0": "至",
+		"b1": "划转币种",
+		"b2": "余额",
+		"b3": "全部",
+		"b4": "划转成功"
+	},
+	"notice": {
+		"a0": "详情",
+		"a1": "消息通知",
+		"a2": "公告",
+		"a3": "消息"
+	},
+	"invite": {
+		"a0": "尊享交易返佣邀请好友",
+		"a1": "合伙人",
+		"a2": "尊享交易返佣",
+		"a3": "普通用户",
+		"a4": "我的身份",
+		"a5": "尊享身份",
+		"a6": "我的邀请码",
+		"a7": "复制邀请二维码",
+		"a8": "复制邀请链接",
+		"a9": "我的推广",
+		"a10": "邀请码",
+		"b0": "推广总人数",
+		"b1": "人",
+		"b2": "总收益折合",
+		"b3": "推广记录",
+		"b4": "直接邀请",
+		"b5": "返佣记录",
+		"b6": "等级",
+		"b7": "级别设定",
+		"b8": "晋升条件",
+		"b9": "分红权益",
+		"c0": "昵称",
+		"c1": "推广人数",
+		"c2": "收益折合",
+		"c3": "邀请记录",
+		"c4": "返佣记录",
+		"c5": "等级权益说明",
+		"c6": "等级",
+		"c7": "权益",
+		"c8": "说明",
+		"c9": "我的权益"
+	},
+	"help": {
+		"a0": "详情",
+		"a1": "学院",
+		"a2": "分类"
+	},
+	"login": {
+		"a0": "邮箱号",
+		"a1": "请输入邮箱号",
+		"a2": "密码",
+		"a3": "请输入密码",
+		"a4": "登录",
+		"a5": "忘记密码",
+		"a6": "没有账号",
+		"a7": "立即注册",
+		"a8": "手机",
+		"a9": "邮箱",
+		"b0": "完成"
+	},
+	"contract": {
+		"title": "合约",
+		"a": "合约流水",
+		"a0": "开仓",
+		"a1": "持仓",
+		"a2": "委托",
+		"a3": "历史",
+		"a4": "合约交易",
+		"a5": "开通成功",
+		"a6": "交易类型",
+		"a7": "已成交",
+		"a8": "委托总量",
+		"a9": "成交均价",
+		"b0": "平仓均价",
+		"b1": "保证金",
+		"b2": "手续费",
+		"b3": "状态",
+		"b4": "操作",
+		"b5": "撤单",
+		"b6": "已撤销",
+		"b7": "未成交",
+		"b8": "部分成交",
+		"b9": "全部成交",
+		"c0": "买入",
+		"c1": "平空",
+		"c2": "卖出",
+		"c3": "平多",
+		"c4": "温馨提示",
+		"c5": "是否撤销当前订单",
+		"c6": "撤销成功",
+		"c7": "盈亏",
+		"c8": "分享",
+		"c9": "委托详情",
+		"d0": "暂无数据",
+		"d1": "价格",
+		"d2": "数量",
+		"d3": "成交时间",
+		"d4": "用户权益",
+		"d5": "未实现盈亏",
+		"d6": "风险率",
+		"d7": "市价",
+		"d8": "张",
+		"d9": "占用保证金",
+		"e0": "买入(做多)",
+		"e1": "可开多",
+		"e2": "卖出(做空)",
+		"e3": "可开空",
+		"e4": "可用",
+		"e5": "划转",
+		"e6": "资金费率",
+		"e7": "距离结算",
+		"e8": "多",
+		"e9": "空",
+		"f0": "资金划转",
+		"f1": "计算器",
+		"f2": "关于合约",
+		"f3": "风险保障基金",
+		"f4": "资金费用历史",
+		"f5": "普通委托",
+		"f6": "市价委托",
+		"f7": "是否以",
+		"f8": "的价格",
+		"f9": "倍杠杆开仓",
+		"g0": "开多",
+		"g1": "开空",
+		"g2": "委托成功",
+		"g3": "仅显示当前合约",
+		"g4": "可平",
+		"g5": "委托",
+		"g6": "开仓平均价",
+		"g7": "结算基准价",
+		"g8": "预估强平价",
+		"g9": "已结算收益",
+		"h0": "收益率",
+		"h1": "止盈",
+		"h2": "止损",
+		"h3": "平仓",
+		"h4": "市价全平",
+		"h5": "止盈止损",
+		"h6": "平",
+		"h7": "请输入平仓价格",
+		"h8": "限价",
+		"h9": "请输入平仓数量",
+		"i0": "可平",
+		"i1": "开仓均价",
+		"i2": "最新成交价",
+		"i3": "请输入价格",
+		"i4": "止盈触发价",
+		"i5": "市价至",
+		"i6": "时将触发止盈委托,成交后预计盈亏",
+		"i7": "止损触发价",
+		"i8": "时将触发止损委托,成交后预计盈亏",
+		"i9": "确定",
+		"j0": "平仓成功",
+		"j1": "是否市价全平",
+		"j2": "全平",
+		"j3": "成功",
+		"j4": "设置成功",
+		"j5": "神机妙算,无可匹敌",
+		"j6": "做",
+		"j7": "平仓价格",
+		"j8": "数字资产交易平台",
+		"j9": "当{name1}遇上{name2} {name3}的火热飞升之路",
+		"k0": "开仓价格",
+		"k1": "最新价格",
+		"k2": "扫码了解更多",
+		"k3": "结算盈亏",
+		"k4": "截图成功,已保存到本地",
+		"k5": "截图失败",
+		"k6": "长按截图",
+		"k7": "一键平仓",
+		"k8": "一键反向",
+		"k9": "是否一键平仓",
+		"l0": "平仓成功",
+		"l1": "是否一键反向",
+		"l2": "反向成功",
+		"l3": "平空",
+		"l4": "平多"
+	},
+	"otc": {
+		"a0": "发布广告",
+		"a1": "订单",
+		"a2": "交易币种",
+		"a3": "我的订单",
+		"a4": "我的广告",
+		"a5": "购买",
+		"a6": "出售",
+		"a7": "总数",
+		"a8": "剩余",
+		"a9": "限量",
+		"b0": "单价",
+		"b1": "支付方式",
+		"b2": "操作",
+		"b3": "总量",
+		"b4": "请选择支付方式",
+		"b5": "请输入数量",
+		"b6": "下单",
+		"b7": "支付宝",
+		"b8": "微信",
+		"b9": "银行卡",
+		"c0": "下单成功",
+		"c1": "状态",
+		"c2": "广告编号",
+		"c3": "总价",
+		"c4": "数量",
+		"c5": "发布时间",
+		"c6": "下架",
+		"c7": "已撤销",
+		"c8": "交易中",
+		"c9": "已完成",
+		"d0": "温馨提示",
+		"d1": "是否下架当前广告",
+		"d2": "确定",
+		"d3": "取消",
+		"d4": "撤销成功",
+		"d5": "法币账户",
+		"d6": "冻结",
+		"d7": "支付宝账号",
+		"d8": "请输入账号",
+		"d9": "姓名",
+		"e0": "请输入姓名",
+		"e1": "付款码",
+		"e2": "绑定",
+		"e3": "微信账号",
+		"e4": "银行名称",
+		"e5": "请输入银行名称",
+		"e6": "开户支行",
+		"e7": "请输入开户支行",
+		"e8": "银行卡号",
+		"e9": "请输入银行卡号",
+		"f0": "编辑成功",
+		"f1": "添加成功",
+		"f2": "卖出",
+		"f3": "买入",
+		"f4": "订单详情",
+		"f5": "订单号",
+		"f6": "账号",
+		"f7": "开户银行",
+		"f8": "剩余时间",
+		"f9": "分",
+		"g0": "秒",
+		"g1": "上传支付凭证",
+		"g2": "确认付款",
+		"g3": "取消订单",
+		"g4": "确认收款",
+		"g5": "未到账",
+		"g6": "是否取消当前订单",
+		"g7": "订单已取消",
+		"g8": "确认当前已付款",
+		"g9": "操作成功",
+		"h0": "确认收款后将挂卖资产将自动划转",
+		"h1": "确认未收到款项后,此订单将自动进入申诉",
+		"h2": "出售订单",
+		"h3": "购买订单",
+		"h4": "广告购买订单",
+		"h5": "广告出售订单",
+		"h6": "时间",
+		"h7": "详情",
+		"h8": "全部",
+		"h9": "已关闭",
+		"i0": "待支付",
+		"i1": "待确认",
+		"i2": "申诉中",
+		"i3": "广告类型",
+		"i4": "请选择交易类型",
+		"i5": "请选择交易币种",
+		"i6": "价格",
+		"i7": "请输入价格",
+		"i8": "最低价",
+		"i9": "请输入最低价",
+		"j0": "最高价",
+		"j1": "请输入最高价",
+		"j2": "备注",
+		"j3": "请输入备注",
+		"j4": "发布",
+		"j5": "发布成功",
+		"j6": "收款方式",
+		"j7": "最低量",
+		"j8": "最高量",
+		"j9": "请输入最低交易量",
+		"k0": "请输入最高交易量"
+	},
+	"pledge": {
+		"introduce": "项目介绍",
+		"funcname": "质押挖矿",
+		"detail": "订单详情",
+		"join": "参与节点",
+		"biz": "质押币种",
+		"cycle": "周期",
+		"rate": "浮动日利率",
+		"zynum": "数量",
+		"ordernum": "订单编号",
+		"profit": "预估收益",
+		"create_time": "创建时间",
+		"end_time": "结束时间",
+		"record": "订单记录",
+		"bzkyzc": "币种可用资产",
+		"zdyxt": "自定义选填",
+		"ljzy": "加入节点",
+		"goorder": "是否查看订单",
+		"income": "收益中",
+		"completed": "已完成",
+		"maxnum": "最大数量",
+		"minnum": "最小数量",
+		"note": "注",
+		"qtxhlfwndsz": "请填写范围内的数值",
+		"a1": "开始质押",
+		"a2": "质押金额",
+		"a3": "当前汇率",
+		"a4": "质押需要支付",
+		"a5": "请确保账户余额充足",
+		"a6": "提交",
+		"a7": "邀请更多好友解锁次数",
+		"a8": "邀请好友解锁次数",
+		"a9": "邀请",
+		"b1": "个好友",
+		"b2": "参与质押即可解锁一次",
+		"b3": "邀请好友",
+		"b4": "取消",
+		"c1":"ETH Layer 2",
+		"c2":"节点生涯",
+		"c3":"ETH Layer 2是一种透过节点算力实现真正挖矿技术的智能合约。以太坊的共识算法从工作证明转变为权益证明的第一步。通过权益证明,更多技术用户可以运行自己的验证节点并质押他们的USDT并获得收益。使用以太坊主网的将以金融机构、鲸鱼、Layer 2协议等机构和大户为主,更多普通用户将选择在Layer 2进行链上交易。参与Layer 2扩容方案的投资者能共享节省下来的燃料费,共同创造更美好的生态。",
+		"c4":"节点优势",
+		"c5":"高交互、低成本",
+		"c6":"可扩容、低延迟",
+		"c7":"公信力高",
+		"c8":"每日发放",
+		"c9":"去中心透明化",
+		"d1":"100%资金安全保障",
+		"d2":"全年收益不间断",
+		"d3":"节点奖励计算",
+		"d4":"参与用户在平台加入了100000 USDT的小型矿机节点,周期为30天,每日产出根据浮动日利率进行计算。假设当日最低浮动利率为0.35%,最高浮动利率为0.38%",
+		"d5":"最低: 100000 USDT * 0.35% = 350 USDT",
+		"d6":"最高:100000 USDT * 0.38% = 380 USDT",
+		"d7":"即30天后可以获得10500~11400 USDT的节点奖励。节点奖励每日发放,发放的奖励可以随时存取,智能合约到期后本金将自动转入您的资产账户中。",
+		"d8":"合约违约条款",
+		"d9":"如用户需要将进行中的智能合约解除并提取本金,则会产生一笔违约费用",
+		"e1":"违约费用=违约结算比例*剩余天数*资金金额",
+		"e2":"举例:该参与节点的违约结算比例为0.5%,剩馀5天合约到期,资金比例为1000,则违约金= 1000*5天*0.5%=25 USDT,实际退还资金为1000 USDT-25 USDT=975 USDT",
+		"e3":"进入ETH Layer 2",
+		"e4":"节点选择",
+		"e5":"单笔限额",
+		"e6":"智能合约节点",
+		"e7":"浮动利率",
+		"e8":"算力",
+		"e9":"预计节点奖励",
+		"f1":"实际收益"
+	}
+}

+ 973 - 0
libs/i18n/lang/en.json

@@ -0,0 +1,973 @@
+{
+	"home":{
+		"k1": "Latest Price",
+		"b0": "24H Rise and fall",
+		"b8": "Type",
+		"d0": "Home"
+	},
+	"add": {
+		"kt": "Airdrop",
+		"ck": "deposit",
+		"a1": "Select payment method",
+		"a2": "Line",
+		"a3":"Payment amount",
+		"a4":"Quantity Purchased",
+		"a5":"Credit Rating"
+	},
+	"miao": {
+		"a1": "Quick Futures",
+		"a2": "Long",
+		"a3": "Short",
+		"a4": "Select due time",
+		"a5": "Buy Amount",
+		"a6": "Fee",
+		"a7": "Available USDT",
+		"a8": "Order placed successfully",
+		"b1": "Order History",
+		"b2": "Long",
+		"b3": "Short",
+		"b4": "Order Price ($)",
+		"b5": "Transaction Amount",
+		"b6": "Profit (%)",
+		"b7": "Time Period",
+		"b8": "Closing Price",
+		"b9": "Profit or loss",
+		"b10": "Countdown"
+	},
+	"flash": {
+		"a1": "Convert",
+		"a2": "From",
+		"a3": "Available",
+		"a4": "To",
+		"a5": "Preview Conversion",
+		"b1": "Order Confirmation",
+		"b2": "Convert",
+		"b3": "Receive",
+		"b4": "Payment Method",
+		"b5": "Spot Wallet",
+		"b6": "Type",
+		"b7": "Market Price",
+		"b8": "Estimated",
+		"b9": "Confirm",
+		"c1": "Insufficient balance, please deposit",
+		"c2": "Back",
+		"c3": "Refresh",
+		"c4": "Please enter the correct exchange amount",
+		"c5": "Currency conversion error",
+		"c6": "Conversion success",
+		"d1": "Conversion History",
+		"d2": "Pay",
+		"d3": "Receive"
+	},
+	"contribution": {
+		"title": "Donation",
+		"a1": "Love for the public! Donation starts from you and me!",
+		"a2": "We call on all users to show their love and inspire humanitarianism to cheer for Ukraine and make donations to bring the war to an end with love, so that Ukraine can rebuild their home as soon as possible. All funds received from DWF exchange will be donated to the International Committee of the Red Cross, Guzema Foundation and Serhiy Prytula Foundation. We hope that the global village will work together to create a better and peaceful world.",
+		"a3": "DWF will donate 1% of the platform's net profit handling fee, the amount you donate DWF exchange will send 1:1 USDT back to your exchange wallet! Pray for Ukraine!",
+		"a4": "Scan for Donation",
+		"a5": "Copy address",
+		"a6": "Current donation amount",
+		"a7": "Current donation deadline",
+		"a8": "No Donation",
+		"a9": "Donated",
+		"b1": "Donation Order",
+		"b2": "Dear User Thank you for your love and support DWF Charity Fund team is reviewing your remittance funds and will return your donation amount within one hour. If you have any questions, please consult our online customer service immediately",
+		"b3": "Confirm",
+		"b4": "Donation Videos",
+		"c1": "Donation History",
+		"c2": "Order Number",
+		"c3": "Date of donation",
+		"c4": "Donation Method",
+		"c5": "Address",
+		"c6": "Amount of donation",
+		"d1": "Details",
+		"e1":"Donated amount",
+		"e2":"Please enter the amount"
+	},
+	"common": {
+		"error1": "Your account is abnormal, please contact customer service",
+		"D": "Day",
+		"M": "Month",
+		"Y": "Year",
+		"add": "Add",
+		"address": "Address",
+		"all": "All",
+		"amout": "Amount",
+		"cancel": "Cancel",
+		"check": "Check",
+		"code": "Verification Code",
+		"confirm": "Confirm",
+		"date": "Date",
+		"detail": "Detail",
+		"email": "Mailbox",
+		"enter": "Please enter",
+		"error": "Failed",
+		"getCode": "Get Verification Code",
+		"h": "Hour",
+		"loadMore": "Load More",
+		"m": "Minute",
+		"money": "Amount",
+		"more": "More",
+		"notData": "No data temporarily",
+		"notMore": "No More",
+		"phone": "Mobile",
+		"requestError": "The network is busy, please try again later",
+		"s": "second",
+		"save": "Save",
+		"select": "Please select",
+		"sendSuccess": "Send successfully",
+		"sms": "SMS",
+		"submit": "Submit",
+		"success": "Success",
+		"tips": "Note",
+		"total": "Total",
+		"type": "Type",
+		"copy": "Copy",
+		"light": "light",
+		"dark": "dark",
+		"service": "Customer Service",
+		"toDwon": "Do you want to go to the download page",
+		"a0": "Please enter the purchase code",
+		"a1": "Copy succeeded",
+		"a2": "copy failed",
+		"a3": "Presale History",
+		"a4": "Payment amount",
+		"a5": "Quantity received",
+		"a6": "account number",
+		"a7": "Recharge quantity",
+		"a8": "Payment voucher",
+		"a9": "Please input recharge quantity",
+		"b0": "Please upload the payment voucher",
+		"b1": "purchase{amount}Pieces{name}Token available{rate}%reward",
+		"b2": "Subscription activities",
+		"cancelButtonText": "Cancel",
+		"confirmButtonText": "Confirm"
+	},
+	"base": {
+		"a0": "Title",
+		"a1": "Return",
+		"a2": "More",
+		"a3": "Quotes",
+		"a4": "Options",
+		"a5": "Tap a new zone",
+		"a6": "Member",
+		"a7": "College",
+		"a8": "Trading Pair",
+		"a9": "Latest Price",
+		"b0": "Rise and fall",
+		"b1": "Click to log in",
+		"b2": "Welcome to",
+		"b3": "Please log in",
+		"b4": "Upgrade",
+		"b5": "Deposit",
+		"b6": "Withdraw",
+		"b7": "Referral",
+		"b8": "Deduct the handling fee",
+		"b9": "Available",
+		"c0": "Buy",
+		"c1": "My Order",
+		"c2": "Identity Verification",
+		"c3": "Security",
+		"c4": "Notifications",
+		"c5": "Address Book",
+		"c6": "Account",
+		"c7": "Favourites",
+		"c8": "Added successfully",
+		"c9": "Cancelled successfully",
+		"d0": "Home",
+		"d1": "Transaction",
+		"d2": "Assets",
+		"d3": "Please enter search keywords",
+		"d4": "All",
+		"d5": "Motherboard",
+		"d6": "Total assets converted",
+		"d7": "Spot Account",
+		"d8": "Transfer",
+		"d9": "Search Pair",
+		"e0": "Hide",
+		"e1": "Balance Assets",
+		"e2": "Frozen/Locked",
+		"e3": "Est. Value",
+		"e4": "Futures Account",
+		"e5": "Contract conversion",
+		"e6": "Miner Level",
+		"e7": "Miner",
+		"e8": "APP",
+		"e9": "Sign in",
+		"f0": "Sign in now",
+		"f1": "Check in every day",
+		"f2": "If you check in for 7 consecutive days, you will get extra gifts",
+		"f3": "buy crypto",
+		"f4": "ETH Layer2",
+		"f5": "Referral",
+		"f6": "Reward automatic delivery",
+		"f7": "If you break the contract, you will not be rewarded",
+		"f8": "24H Turnover",
+		"f9": "Charitable Fund",
+		"g1": "Convert",
+		"g2": "About Us",
+		"g3": "Version 6.0.7",
+		"g4": "Help Center",
+		"g5": "Unbound",
+		"g6": "Language",
+		"g7": "Pair",
+		"g8": "Last Price",
+		"g9": "Change",
+		"h0": "Bound",
+		"h1": "Maintenance updating",
+		"h2": "Perpetual contract"
+	},
+	"aboutUs": {
+		"a0": "About Us",
+		"a1": "and"
+	},
+	"accountSettings": {
+		"a0": "My Profile",
+		"a1": "Profile Photo",
+		"a2": "Nickname",
+		"a3": "Main Account",
+		"a4": "Phone",
+		"a5": "Untie",
+		"a6": "Binding",
+		"a7": "Email",
+		"a8": "Change Account",
+		"a9": "Logout",
+		"b0": "Modify Nickname",
+		"b1": "Please enter a nickname",
+		"b2": "Language"
+	},
+	"assets": {
+		"a0": "Add Management",
+		"a1": "The address book can be used to manage your frequently used addresses. There is no need to perform multiple verifications when initiating withdrawals from addresses in the address book.",
+		"a2": "automatic withdrawal is supported. When using {name} to withdraw, only addresses in the web address book are allowed to initiate withdrawals.",
+		"a3": "Delete Address",
+		"a4": "Add Address",
+		"a5": "Please select the address to delete",
+		"a6": "Whether to delete the currently selected address",
+		"a7": "Statement",
+		"a8": "Total",
+		"a9": "Available",
+		"b0": "Freeze",
+		"b1": "Funding Account",
+		"b2": "Contract Account",
+		"b3": "Margin Account",
+		"b4": "Wealth Management Account",
+		"b5": "Search currency",
+		"b6": "Withdrawal",
+		"b7": "Please select the chain type",
+		"b8": "Receiving Address",
+		"b9": "Please enter address",
+		"b10": "Search Cryptocurrency",
+		"c0": "Amount",
+		"c1": "Balance",
+		"c2": "Please enter amount",
+		"c3": "Max",
+		"c4": "Fee",
+		"c5": "Please double check and enter the correct wallet address for withdrawal.",
+		"c6": "Sending non-corresponding digital currency to the wallet address will cause permanent loss.",
+		"c7": "Withdrawal fees will be deducted from the amount of withdrawals.",
+		"c8": "Withdrawal Record",
+		"c9": "Time",
+		"d0": "Status",
+		"d1": "Under review",
+		"d2": "Success",
+		"d3": "Failed",
+		"d4": "See more",
+		"d5": "Submitted successfully, under review",
+		"d6": "Edit",
+		"d7": "Add",
+		"d8": "Withdrawal Address",
+		"d9": "Please enter or paste the address",
+		"e0": "Note",
+		"e1": "Please enter a note",
+		"e2": "Please enter the address",
+		"e3": "Please enter note(Optional)",
+		"e4": "Operation successful",
+		"e5": "Deposit",
+		"e6": "Scan for Deposit",
+		"e7": "coin deposit address",
+		"e8": "Amount of Deposit",
+		"e9": "Please enter the deposit amount",
+		"f0": "This address is your latest deposit address. When the system receives deposit, it will be automatically credited to the account.",
+		"f1": "The transfer needs to be confirmed by the entire blockchain network. When it reaches {num} network confirmations, your {name} will be automatically deposit into the account.",
+		"f2": "When a network is confirmed, yours",
+		"f3": "Please only send {name} to this address, sending other digital currencies to this address will cause permanent loss.",
+		"f4": "Deposit History",
+		"g1": "Wallet Address Transfer",
+		"g2": "Bank Card Transfer",
+		"g3": "Credit Card Payments",
+		"g4": "Copy Address",
+		"h1":"The number with the country code"
+	},
+	"auth": {
+		"a0": "Identity Verification",
+		"a1": "Personal Information",
+		"a2": "Unverified",
+		"a3": "Verified",
+		"a4": "Photo Identification",
+		"a5": "Under review",
+		"a6": "Authentication failed",
+		"a7": "Country of nationality",
+		"a8": "Please select nationality",
+		"a9": "Full Name",
+		"b0": "Consistent with your government ID",
+		"b1": "ID or Passport Number",
+		"b2": "Enter number without spaces",
+		"b3": "Confirm",
+		"b4": "Authentication successful",
+		"b5": "Please upload the front photo of the ID",
+		"b6": "Please upload the back of the ID",
+		"b7": "Please upload a selfie of yourself holding your ID",
+		"b8": "Make sure the photo is clear without watermark, and the upper body is intact",
+		"b9": "The file size is too large and must not exceed",
+		"c0": "File type error",
+		"c1": "Uploaded successfully",
+		"c2": "Please upload a photo of the back of your ID",
+		"c3": "Please upload the front photo of your ID",
+		"c4": "Uploaded successfully, please wait for review"
+	},
+	"exchange": {
+		"a0": "Spot",
+		"a1": "Crypto Presale",
+		"a2": "Futures",
+		"a3": "Transaction",
+		"a4": "Current Orders",
+		"a5": "Order History",
+		"a6": "Added successfully",
+		"a7": "Cancelled successfully",
+		"a8": "Total Issued",
+		"a9": "Total Circulation",
+		"b0": "Issue Price",
+		"b1": "Release time",
+		"b2": "White Paper Address",
+		"b3": "Official website address",
+		"b4": "Introduction",
+		"b5": "Buy",
+		"b6": "Sell",
+		"b7": "Order Price",
+		"b8": "Type",
+		"b9": "Limit Price Trading",
+		"c0": "Market Trading",
+		"c1": "Closed",
+		"c2": "Total",
+		"c3": "Buy",
+		"c4": "Sell",
+		"c5": "Amount",
+		"c6": "Sold at the best market price",
+		"c7": "Total Price",
+		"c8": "Available",
+		"c9": "Total Value",
+		"d0": "Login",
+		"d1": "Chart",
+		"d2": "Price",
+		"d3": "Trade",
+		"d4": "Time",
+		"d5": "Direction",
+		"d6": "Limit Price",
+		"d7": "Market Price",
+		"d8": "Please enter the price",
+		"d9": "Please enter the amount",
+		"e0": "Please enter the total price",
+		"e1": "Order successfully placed",
+		"e2": "Average Price",
+		"e3": "High",
+		"e4": "Low",
+		"e5": "amount",
+		"e6": "Orderbook",
+		"e7": "Currency Information",
+		"e8": "Minutes",
+		"e9": "Hour",
+		"e10": "Minute",
+		"f0": "Day",
+		"f1": "Week",
+		"f2": "Month",
+		"f3": "Buy Price",
+		"f4": "Sell Price",
+		"f5": "Currency Trading",
+		"f6": "Search crypto, pairs, and contracts",
+		"f7": "Pair",
+		"f8": "Last Price",
+		"f9": "Change",
+		"g0": "Favourites",
+		"g1": "My Order",
+		"g2": "Order Cancellation",
+		"g3": "Operation",
+		"g4": "Cancel",
+		"g5": "Whether to cancel the current order",
+		"g6": "Undo successfully",
+		"g7":"Time"
+	},
+	"option": {
+		"a0": "Options",
+		"a1": "Deadline",
+		"a2": "Call Options",
+		"a3": "Put Options",
+		"a4": "Yield",
+		"a5": "Buy",
+		"a6": "Multi",
+		"a7": "Empty",
+		"a8": "Current",
+		"a9": "Next Issue",
+		"b0": "Vol",
+		"b1": "Increase selection",
+		"b2": "Profit",
+		"b3": "Purchase amount",
+		"b4": "Please enter the amount",
+		"b5": "Balance",
+		"b6": "Estimated Income",
+		"b7": "Buy Now",
+		"b8": "Call",
+		"b9": "Vol",
+		"c0": "Put",
+		"c1": "Successful purchase",
+		"c2": "Details",
+		"c3": "Transaction Number",
+		"c4": "Opening Price",
+		"c5": "Closing Price",
+		"c6": "Deal Time",
+		"c7": "Buy Amount",
+		"c8": "Purchase Type",
+		"c9": "Status",
+		"d0": "Delivery Result",
+		"d1": "Settlement Amount",
+		"d2": "Delivery Time",
+		"d3": "View more",
+		"d4": "Buy Options",
+		"d5": "Deliveries in process",
+		"d6": "My delivered",
+		"d7": "Delivery History",
+		"d8": "Minutes",
+		"d9": "Hour",
+		"d10": "Time",
+		"e0": "Day",
+		"e1": "Week",
+		"e2": "Month",
+		"e3": "Direction",
+		"e4": "Rise and fall",
+		"e5":"Please input 1000-6000",
+		"e6":"Please input 10000-30000",
+		"e7":"Please input 60000-100000",
+		"e8":"Please input 200000-300000",
+		"e9":"Please input 600000-1000000",
+		"e10":"Over 3,000,000"
+	},
+	"purchase": {
+		"a0": "Presale Rate",
+		"a1": "Payment Currency",
+		"a2": "Launch Date",
+		"a3": "Presale Start Time",
+		"a4": "Presale End Time",
+		"a5": "Crypto Presale",
+		"a6": "Please select the purchase currency",
+		"a7": "Purchase amount",
+		"a8": "Please enter the purchase amount",
+		"a9": "Max",
+		"b0": "BUY NOW",
+		"b1": "Presale stage",
+		"b2": "In preparation",
+		"b3": "Presale Start",
+		"b4": "Presale End",
+		"b5": "Results Announcement",
+		"b6": "Description",
+		"b7": "Whether to use",
+		"b8": "for purchase",
+		"b9": "Subscription is successful",
+		"d1": "Payment methods",
+		"d2": "Please enter the correct amount"
+	},
+	"reg": {
+		"a0": "Register by Phone Number",
+		"a1": "Register by Email",
+		"a2": "Mobile",
+		"a3": "Please enter your phone number",
+		"a4": "Email",
+		"a5": "Please enter your Email",
+		"a6": "Verification Code",
+		"a7": "Please enter the verification code",
+		"a8": "Password",
+		"a9": "Please enter a password",
+		"b0": "Confirm Password",
+		"b1": "Please confirm your password",
+		"b2": "Referral ID",
+		"b3": "Please enter your referrer ID",
+		"b4": "Optional",
+		"b5": "I have read and agree to the",
+		"b6": "User Agreement",
+		"b7": "and",
+		"b8": "Privacy Agreement",
+		"b9": "Register",
+		"c0": "Already have a DWF’s account?",
+		"c1": "Login",
+		"c2": "Please read and agree to the agreement",
+		"c3": "Please fill in the phone number",
+		"c4": "Please fill in the mailbox number",
+		"c5": "Registered successfully"
+	},
+	"safe": {
+		"a0": "Remove",
+		"a1": "Bind",
+		"a2": "Email",
+		"a3": "Mailbox Number",
+		"a4": "Please enter the mailbox number",
+		"a5": "Email Verification Code",
+		"a6": "Please enter the verification code",
+		"a7": "Verification Code",
+		"a8": "Unbind successfully",
+		"a9": "Binding successful",
+		"b0": "Forgot password",
+		"b1": "Phone number or email address",
+		"b2": "Please enter your phone number or email address",
+		"b3": "New Password",
+		"b4": "Please enter a new password",
+		"b5": "Confirm Password",
+		"b6": "Please confirm your password",
+		"b7": "Change Password",
+		"b8": "Please enter the correct email number",
+		"b9": "Google Authenticator",
+		"c0": "How to do: Download and open Google Authenticator, scan the QR code below or manually enter the secret key to add a verification token.",
+		"c1": "Copy key",
+		"c2": "I have stored the key properly, and it will not be retrieved if it is lost.",
+		"c3": "Next",
+		"c4": "SMS verification code",
+		"c5": "Google Verification Code",
+		"c6": "Confirm binding",
+		"c7": "Security",
+		"c8": "Login Password",
+		"c9": "Modify",
+		"d0": "Settings",
+		"d1": "Transaction Password",
+		"d2": "Phone Number",
+		"d3": "Modified successfully",
+		"d4": "Mobile Number",
+		"d5": "Please enter your phone number",
+		"d6": "Please enter the SMS verification code",
+		"d7": "Close",
+		"d8": "Open",
+		"d9": "Verify",
+		"e0": "SMS",
+		"e1": "Closed successfully",
+		"e2": "Open successfully",
+		"e3": "Confirm",
+		"e4": "Set up successfully",
+		"f1":"Password & Confirm Password don’t match",
+		"f2":"Wrong verification code"
+	},
+	"transfer": {
+		"a0": "Transfer History",
+		"a1": "Success",
+		"a2": "Amount",
+		"a3": "Direction",
+		"a4": "Spot Account",
+		"a5": "Futures Account",
+		"a6": "Margin Account",
+		"a7": "Wealth Management Account",
+		"a8": "Transfer",
+		"a9": "From",
+		"b0": "To",
+		"b1": "Transfer Amount",
+		"b2": "Balance",
+		"b3": "Max",
+		"b4": "Transfer successfully"
+	},
+	"notice": {
+		"a0": "Details",
+		"a1": "Notifications",
+		"a2": "Announcements",
+		"a3": "Message"
+	},
+	"invite": {
+		"a0": "Referral",
+		"a1": "Partnership",
+		"a2": "Exclusive trading rebate",
+		"a3": "Ordinary Member",
+		"a4": "My Identity",
+		"a5": "Exclusive Identity",
+		"a6": "My Referral Code",
+		"a7": "Copy QR code",
+		"a8": "Copy Link",
+		"a9": "My Referral",
+		"a10": "Referral Code",
+		"b0": "Referrals",
+		"b1": "People",
+		"b2": "Commissions",
+		"b3": "Referrals Details",
+		"b4": "Direct invitation",
+		"b5": "Earnings Details",
+		"b6": "Level",
+		"b7": "Level Setting",
+		"b8": "Promotion Conditions",
+		"b9": "Dividend Rights",
+		"c0": "nickname",
+		"c1": "Number of Promotions",
+		"c2": "Earnings equivalent",
+		"c3": "Invitation Record",
+		"c4": "Rebate Record",
+		"c5": "Class rights description",
+		"c6": "Level",
+		"c7": "Equity",
+		"c8": "Description",
+		"c9": "My rights"
+	},
+	"help": {
+		"a0": "Details",
+		"a1": "University",
+		"a2": "Classification",
+		"a3": "MOOMPY BUY",
+		"a4": "1.Click Deposit in your DWF account",
+		"a5": "2.Select TRC20, copy the arrow address.",
+		"a6": "Select the currency",
+		"a7": "1.Open the “Buy / Sell Crypto” tab.",
+		"a8": "2.Choose what you want to do: “Buy” or “Sell.”",
+		"a9": "3.Select currencies involved in the exchange.",
+		"b0": "4.Type in the amount you wish to spend in the “You send” field. ",
+		"b1": "5.ChangeNOW will automatically calculate the estimated final amount with the best exchange rate.",
+		"b2": "6.If everything is OK, click on the “Buy” / “Sell” button. You will proceed to the next step",
+		"b3": "1.Enter the amount and choose your country's legal currency.",
+		"b4": "2.Choose USDT-TRC20",
+		"b5": "3.Copy your DWF account TRC20 address, then fill it in.Click Next",
+		"b6": "Confirm",
+		"b7": "Check all the information carefully and click on “Confirm”. You will be redirected to a secure payment company webpage to proceed with the payment.",
+		"b8": "Next, a “redirecting” widget to the page of the selected provider will appear.",
+		"b9": "Pay with a card",
+		"c0": "Once you’ve been redirected, you’ll need to fill in your credit card and contact details and process your payment. Please note that your card must meet specific requirements:",
+		"c1": "1.Your card is a Visa or a MasterCard;",
+		"c2": "2.Your card is eligible for international transactions;",
+		"c3": "3.You are enrolled in the 3DSecure program;",
+		"c4": "4.You have enough money in the account to complete the transaction.",
+		"c5": "Verification",
+		"c6": "Our fiat-to-crypto providers require our customers to pass their verification process.",
+		"c7": "First, you will need to verify your phone number and your email.",
+		"c8": "Later, you will be asked to submit an identifying document legal in your country (such as a passport, driving license, or ID card).",
+		"c9": "Simplex may also ask you to send a selfie with the card used in the payment. Make sure that your selfie follows these requirements:",
+		"d0": "1.The first 4 and last 4 digits on the card are visible;",
+		"d1": "2.Your face is clearly visible;",
+		"d2": "3.Your name on the card is clearly readable;",
+		"d3": "4.It’s taken in a well-lit area.",
+		"d4": "Receive your coins",
+		"d5": "Once your payment is completed, you will be redirected to ChangeNOW.",
+		"d6": "ChangeNOW will finish the exchange process and send your coins to you in a few minutes. You can track your progress on your exchange page - learn how to do that here. https://support.changenow.io/hc/en-us/articles/360011502720",
+		"d7": "After the exchange is complete, you can check it in your DWF account.",
+		"f0": "CHAINBITS BUY",
+		"f1": "1.Click Deposit in your DWF account",
+		"f2": "2.Select TRC20, copy the arrow address.",
+		"f3": "When you click buy, you will be taken to our checkout, where you can select the typo and amount of cryptocurrency you wish to purchase. Additionally, you will be able to select the purchasing method - either with a card.",
+		"f4": "1.Enter the amount and choose your country's legal currency.",
+		"f5": "2.Choose USDT-TRC20",
+		"f6": "3.Copy your DWF account TRC20 address, then fill it in.",
+		"f7": "After selecting the desired amounts and pressing continue, you will be prompted to the next page, where you will be required to enter your card details, such as full card number, full name, CVV (security) code expiry date. Later on, you will be asked to enter your personal details such as the billing address - address, city, zip/postal code, country and then the contact details - your email, date of birth and phone number.",
+		"f8": "In this page, you will also see the exact amount of cryptocurrency you will receive with all of the fees already applied to it.",
+		"f9": "Once the information is submitted, if everything is entered accordingly - no special symbols, only Latin alphabet used, the phone is in the international format - you should be able to press “PAY NOW”.",
+		"g0": "Please be informed that by pressing “PAY NOW” you agree with the terms and conditions of our services, the cryptocurrency amount you will receive and confirm that the details you have entered are correct. ",
+		"g1": "After pressing “PAY NOW”, the verification process will begin.",
+		"g2": "During the verification process, you will need to verify your email by entering a 4 digit code that will be sent to the email address provided. After the email is verified, you may be asked to submit your identity document and enter its details in the document upload page. ",
+		"g3": "You might also be asked to upload a selfie with the card - photo or video - as proof of card ownership.",
+		"g4": "If all of these steps are successfully completed, your payment will be approved and the coins will be sent to the wallet address that was used in the transaction. It will reflect in your DWF wallet as soon as it is confirmed on the Blockchain.",
+		"h0": "Change NOW Simplex",
+		"h1": "PURCHASE",
+		"h2": "CRYPTOCURRENCY ONLINE",
+		"h3": "SUPPORT CREDIT CARD OR DEBIT CARD",
+		"h4": "trusted by 5m+ people",
+		"h5": "trustpilot",
+		"h6": "Purchase Tutorial"
+	},
+	"login": {
+		"a0": "Email",
+		"a1": "Please enter your email number",
+		"a2": "Password",
+		"a3": "Please enter a password",
+		"a4": "Login",
+		"a5": "Forgot Password",
+		"a6": "No account",
+		"a7": "Register Now",
+		"a8": "Mobile",
+		"a9": "Email",
+		"b0": "Done"
+	},
+	"contract": {
+		"title": "TXT Futures",
+		"a": "Assets",
+		"a0": "Futures",
+		"a1": "Positions",
+		"a2": "Open Orders",
+		"a3": "Order History",
+		"a4": "Futures",
+		"a5": "Opened successfully",
+		"a6": "Transaction Type",
+		"a7": "Closed",
+		"a8": "Order Total",
+		"a9": "Average Transaction Price",
+		"b0": "Order Price",
+		"b1": "Margin",
+		"b2": "Fee",
+		"b3": "Type",
+		"b4": "Status",
+		"b5": "Cancel order",
+		"b6": "Cancelled",
+		"b7": "Unsold",
+		"b8": "Partial deal",
+		"b9": "Full deal",
+		"c0": "Long",
+		"c1": "Close",
+		"c2": "Short",
+		"c3": "Close",
+		"c4": "Note",
+		"c5": "Whether to cancel the current order",
+		"c6": "Undo successfully",
+		"c7": "Profit and Loss",
+		"c8": "Share",
+		"c9": "Delegation Details",
+		"d0": "No more",
+		"d1": "Price",
+		"d2": "Amount",
+		"d3": "Deal time",
+		"d4": "Futures Balance",
+		"d5": "Unrealized profit and loss",
+		"d6": "Risk Rate",
+		"d7": "Market Price",
+		"d8": "cont",
+		"d9": "Cost (The estimated margin required)",
+		"e0": "Market-long",
+		"e1": "Available",
+		"e2": "Market-short",
+		"e3": "Available",
+		"e4": "Available",
+		"e5": "Transfer",
+		"e6": "Fund Rate",
+		"e7": "Distance settlement",
+		"e8": "Long",
+		"e9": "Short",
+		"f0": "Funds Transfer",
+		"f1": "Calculator",
+		"f2": "About the contract",
+		"f3": "Risk Protection Fund",
+		"f4": "Fund Expense History",
+		"f5": "Limit",
+		"f6": "Market",
+		"f7": "Whether to use",
+		"f8": "The price",
+		"f9": "Open position with double leverage",
+		"g0": "Long",
+		"g1": "Short",
+		"g2": "Success",
+		"g3": "Only display the current futures",
+		"g4": "Amountable to level",
+		"g5": "Delegated Freeze",
+		"g6": "Average opening price",
+		"g7": "Settlement Base Price",
+		"g8": "Estimated Strong Parity",
+		"g9": "Settled income",
+		"h0": "Yield",
+		"h1": "Stop Profit",
+		"h2": "Stop Loss",
+		"h3": "Close Position",
+		"h4": "The market price is flat",
+		"h5": "Stop Profit Stop Loss",
+		"h6": "Close",
+		"h7": "Please enter the closing price",
+		"h8": "Limit Price",
+		"h9": "Please enter the closing amount",
+		"i0": "Available to close",
+		"i1": "Average opening price",
+		"i2": "Latest Transaction Price",
+		"i3": "Please enter the price",
+		"i4": "Take Profit Trigger Price",
+		"i5": "Market price to",
+		"i6": "Take profit order will be triggered at the time, and profit and loss is expected after the transaction",
+		"i7": "Stop Loss Trigger Price",
+		"i8": "A stop loss order will be triggered at the time, and profit and loss is expected after the transaction",
+		"i9": "Confirm",
+		"j0": "Successfully closed position",
+		"j1": "Whether the market price is flat",
+		"j2": "Quan Ping",
+		"j3": "Success",
+		"j4": "Setup successful",
+		"j5": "Magic calculation, unmatched",
+		"j6": "Do",
+		"j7": "Close price",
+		"j8": "Digital asset trading platform",
+		"j9": "When {name1} meets {name2} {name3}’s fiery road to ascendance",
+		"k0": "Opening price",
+		"k1": "Latest Price",
+		"k2": "Scan the code to learn more",
+		"k3": "Settlement profit and loss",
+		"k4": "The screenshot is successful and has been saved locally",
+		"k5": "Screenshot failed",
+		"k6": "Long press to take screenshot",
+		"k7": "Quick Close",
+		"k8": "Quick conversion",
+		"k9": "Whether to use a quick close position",
+		"l0": "Success",
+		"l1": "Whether to use quick conversion",
+		"l2": "Reverse success",
+		"l3": "Close"
+	},
+	"otc": {
+		"a0": "Post an ad",
+		"a1": "Order",
+		"a2": "Trading currency",
+		"a3": "My Order",
+		"a4": "My Ads",
+		"a5": "Buy",
+		"a6": "Sale",
+		"a7": "Total",
+		"a8": "Remaining",
+		"a9": "Limited",
+		"b0": "Unit Price",
+		"b1": "Payment Method",
+		"b2": "Operation",
+		"b3": "Total",
+		"b4": "Please choose a payment method",
+		"b5": "Please enter the quantity",
+		"b6": "Place an order",
+		"b7": "Alipay",
+		"b8": "WeChat",
+		"b9": "Bank Card",
+		"c0": "Order successfully placed",
+		"c1": "Status",
+		"c2": "Advertisement Number",
+		"c3": "Total Price",
+		"c4": "Quantity",
+		"c5": "Release time",
+		"c6": "Remove",
+		"c7": "Cancelled",
+		"c8": "In transaction",
+		"c9": "Completed",
+		"d0": "Note",
+		"d1": "Whether to remove the current ad",
+		"d2": "OK",
+		"d3": "Cancel",
+		"d4": "Undo successfully",
+		"d5": "Fiat currency account",
+		"d6": "Freeze",
+		"d7": "Alipay Account",
+		"d8": "Please enter the account number",
+		"d9": "Name",
+		"e0": "Please enter your name",
+		"e1": "Payment Code",
+		"e2": "Binding",
+		"e3": "WeChat Account",
+		"e4": "Bank Name",
+		"e5": "Please enter the bank name",
+		"e6": "Account Opening Branch",
+		"e7": "Please enter the account opening branch",
+		"e8": "Bank Card Number",
+		"e9": "Please enter the bank card number",
+		"f0": "Edited successfully",
+		"f1": "Added successfully",
+		"f2": "Sell",
+		"f3": "Buy",
+		"f4": "Order Details",
+		"f5": "Order Number",
+		"f6": "Account",
+		"f7": "Account Bank",
+		"f8": "Remaining time",
+		"f9": "Min",
+		"g0": "Second",
+		"g1": "Upload payment voucher",
+		"g2": "Confirm payment",
+		"g3": "Cancel order",
+		"g4": "Confirm Payment",
+		"g5": "Unpaid account",
+		"g6": "Whether to cancel the current order",
+		"g7": "Order has been cancelled",
+		"g8": "Confirm the current payment",
+		"g9": "Operation successful",
+		"h0": "After the payment is confirmed, the listed assets will be automatically transferred",
+		"h1": "After confirming that the payment has not been received, this order will automatically enter the appeal",
+		"h2": "Sell Order",
+		"h3": "Purchase Order",
+		"h4": "Advertising Purchase Order",
+		"h5": "Advertising Sale Order",
+		"h6": "Time",
+		"h7": "Details",
+		"h8": "All",
+		"h9": "Closed",
+		"i0": "Pending Payment",
+		"i1": "To be confirmed",
+		"i2": "Appealing",
+		"i3": "Ad Type",
+		"i4": "Please select transaction type",
+		"i5": "Please select the transaction currency",
+		"i6": "Price",
+		"i7": "Please enter the price",
+		"i8": "Lowest Price",
+		"i9": "Please enter the lowest price",
+		"j0": "Highest price",
+		"j1": "Please enter the highest price",
+		"j2": "Remarks",
+		"j3": "Please enter a note",
+		"j4": "Release",
+		"j5": "Posted successfully",
+		"j6": "Payment method",
+		"j7": "Minimum Quantity",
+		"j8": "Maximum amount",
+		"j9": "Please enter the minimum transaction volume",
+		"k0": "Please enter the highest transaction volume"
+	},
+	"pledge": {
+		"introduce": "Project Description",
+		"funcname": "Mining",
+		"detail": "Order details",
+		"join": "Join in",
+		"biz": "Currency",
+		"cycle": "Operation Cycle",
+		"rate": "Variable Rate",
+		"zynum": "Amount",
+		"ordernum": "Order No",
+		"profit": "Estimated Revenue",
+		"create_time": "Start time",
+		"end_time": "End time",
+		"record": "Order History",
+		"bzkyzc": "Available Assets",
+		"zdyxt": "(Optional)",
+		"ljzy": "Join Node",
+		"goorder": "View order",
+		"income": "In Progress",
+		"completed": "Completed",
+		"maxnum": "Maximum quantity",
+		"minnum": "Minimum quantity",
+		"note": "notes",
+		"qtxhlfwndsz": "Please fill in the values within the range",
+		"a1": "Start of pledge",
+		"a2": "Staking Amount",
+		"a3": "Current exchange rate",
+		"a4": "The pledge needs to be paid",
+		"a5": "Please ensure that the account balance is sufficient",
+		"a6": "Submit",
+		"a7": "Invite more friends to unlock",
+		"a8": "Number of times to invite friends to unlock",
+		"a9": "invitation",
+		"b1": "Friends",
+		"b2": "You can unlock once by participating in pledge",
+		"b3": "Invite friends",
+		"b4": "cancel",
+		"c1": "ETH Layer 2",
+		"c2": "Node Ecology",
+		"c3": "ETH Layer 2 is a smart contract that implements true mining technology through nodal hashrate. It is the first step in the transformation of Ethernet's consensus algorithm from proof of work to proof of interest. Through proof of stake, more users of the technology can run their own verified nodes and pledge their USDT for revenue. The main Ethernet network will be used mainly by financial institutions, whales, Layer 2 protocols and other institutions and large users, while more general users will choose to trade on the chain in Layer 2. Investors participating in the Layer 2 scaling solution will be able to share the Gas Fee savings and create a better ecosystem together." ,
+		"c4": "Node Advantages",
+		"c5": "Highly interactive, low cost",
+		"c6": "Expandable, low delay",
+		"c7": "High credibility",
+		"c8": "Daily Release",
+		"c9": "Decentralised and transparent",
+		"d1": "100% security of funds",
+		"d2": "Uninterrupted returns throughout the year",
+		"d3": "Node Revenue Calculation",
+		"d4": "The user joins a 100,000 USDT Small Mining Machine on the platform for 30 days, with daily output calculated based on daily Hashrate. Assuming a minimum floating rate of 0.4% and a maximum floating rate of 0.41% for the day.",
+		"d5": "Mix: 100,000 USDT* 0.4% = 400 USDT",
+		"d6": "Max: 100,000 USDT* 0.41% = 410 USDT",
+		"d7": "This means that after 30 days you will receive between 12,000~12,300 in rewards. The node rewards are paid daily and the rewards paid can be accessed at any time. The principal will be automatically transferred to your asset account after the smart contract expires." ,
+		"d8": "Clauses on Default",
+		"d9": "If the user needs to cancel an active smart contract and withdraw the principal, a default fee will be incurred.",
+		"e1": "Default Fee = Default Settlement Ratio * Days Remaining * Amount of Capital",
+		"e2": "Example: The default settlement percentage for the participating node is 0.5%, 5 days left for the contract to expire and the funding percentage is 1000, then the default fee = 1000*5 days*0.5%=25 USDT, the actual refunded funds are 1000 USDT-25 USDT=975 USDT",
+		"e3": "Enter ETH Layer 2",
+		"e4": "Node Types",
+		"e5": "Amount Range",
+		"e6": "Smart Contracts",
+		"e7": "Variable Rate",
+		"e8": "Hashrate",
+		"e9": "Estimate Node Reward",
+		"f1": "Actual revenue"
+	}
+}

+ 916 - 0
libs/i18n/lang/tw.json

@@ -0,0 +1,916 @@
+{
+	"home":{
+		"k1": "最新價格",
+		"b0": "24H漲跌幅",
+		"b8": "名稱",
+		"d0": "首頁"
+	},
+	"add": {
+		"ck": "存款",
+		"kt":"空投",
+		"a1": "選擇支付方式",
+		"a2": "Line",
+		"a3":"付款數量",
+		"a4":"認購數量",
+		"a5":"信用評分"
+	},
+	"miao": {
+		"a1": "秒合約",
+		"a2": "做多",
+		"a3": "做空",
+		"a4": "選擇到期時間",
+		"a5": "買入數量",
+		"a6": "手續費",
+		"a7": "可用USDT",
+		"a8": "下單成功",
+		"b1": "購買記錄",
+		"b2": "做多",
+		"b3": "做空",
+		"b4": "下單價格(元)",
+		"b5": "交易金額",
+		"b6": "預計收益率",
+		"b7": "交易週期",
+		"b8": "結束價格",
+		"b9": "逾期回報",
+		"b10": "倒數計時"
+	},
+	"flash": {
+		"a1": "閃兌",
+		"a2": "從",
+		"a3": "可用",
+		"a4": "至",
+		"a5": "詢價",
+		"b1": "訂單確認",
+		"b2": "兌換",
+		"b3": "收到",
+		"b4": "支付管道",
+		"b5": "現貨錢包",
+		"b6": "類型",
+		"b7": "市價",
+		"b8": "匯率",
+		"b9": "確認",
+		"c1": "餘額不足,請儲值",
+		"c2": "返回",
+		"c3": "刷新",
+		"c4": "請輸入正確兌換金額",
+		"c5": "兌換幣種異常",
+		"c6": "兌換成功",
+		"d1": "兌換記錄",
+		"d2": "支出",
+		"d3": "到賬"
+	},
+	"contribution": {
+		"title": "捐款",
+		"a1": "愛心公益! 捐款你我做起!",
+		"a2": "呼籲廣大用戶發揮愛心及激發人道主義為烏克蘭加油並進行捐款,用愛心為戰爭畫上句號,使烏克蘭早日重建家園。DWF交易所收到的捐款資金將全數淨捐給國際紅十字委員會、Guzema Foundation、Serhiy Prytula Foundation。盼望地球村攜手合作共創美好的和平世界。",
+		"a3": "DWF將平台淨利手續費1%捐出,您捐贈的金額DWF交易所將1:1的USDT返送至您的交易所錢包!為烏克蘭加油!",
+		"a4": "掃描二維碼完成付款",
+		"a5": "複製地址",
+		"a6": "現時捐款金額",
+		"a7": "本期捐款截止",
+		"a8": "未捐款",
+		"a9": "已捐款",
+		"b1": "捐款訂單",
+		"b2": "尊貴的用戶謝謝您的愛心與支持 DWF慈善基金團隊正在審核您的匯款資金 並在一個小時內返還您的捐款金額 如有任何問題請立即諮詢線上客服",
+		"b3": "確認",
+		"b4": "詳情視頻",
+		"c1": "捐款記錄",
+		"c2": "訂單號",
+		"c3": "提交時間",
+		"c4": "捐款管道",
+		"c5": "地址",
+		"c6": "捐款金額",
+		"d1": "詳情",
+		"e1":"已捐款金額",
+		"e2":"請輸入金額"
+	},
+	"common": {
+		"error1": "您的賬號異常,請聯繫客服人員",
+		"D": "日",
+		"M": "月",
+		"Y": "年",
+		"add": "添加",
+		"address": "地址",
+		"all": "所有",
+		"amout": "數量",
+		"cancel": "取消",
+		"check": "審核",
+		"code": "驗證碼",
+		"confirm": "確定",
+		"date": "日期",
+		"detail": "詳情",
+		"email": "郵箱",
+		"enter": "請輸入",
+		"error": "失敗",
+		"getCode": "獲取驗證碼",
+		"h": "時",
+		"loadMore": "加載更多",
+		"m": "分",
+		"money": "金額",
+		"more": "更多",
+		"notData": "暫無數據",
+		"notMore": "沒有更多了",
+		"phone": "手機",
+		"requestError": "網絡繁忙,請稍後再試",
+		"s": "秒",
+		"save": "保存",
+		"select": "請選擇",
+		"sendSuccess": "發送成功",
+		"sms": "短信",
+		"submit": "提交",
+		"success": "成功",
+		"tips": "溫馨提示",
+		"total": "總額",
+		"type": "類型",
+		"copy": "複製",
+		"light": "白",
+		"dark": "黑",
+		"service": "客服",
+		"toDwon": "是否前往下載頁",
+		"a0": "請輸入申購碼",
+		"a1": "複製成功",
+		"a2": "複製失敗",
+		"a3": "申購記錄",
+		"a4": "支付金額",
+		"a5": "到賬數量",
+		"a6": "帳號",
+		"a7": "充值數量",
+		"a8": "支付憑證",
+		"a9": "請輸入充值數量",
+		"b0": "請上傳支付憑證",
+		"b1": "購買{amount}枚{name}代幣可獲{rate}%獎勵",
+		"b2": "申購活動",
+		"cancelButtonText": "取消",
+		"confirmButtonText": "確認"
+	},
+	"base": {
+		"a0": "標題",
+		"a1": "返回",
+		"a2": "更多",
+		"a3": "行情",
+		"a4": "期權",
+		"a5": "打新專區",
+		"a6": "會員",
+		"a7": "學院",
+		"a8": "交易對",
+		"a9": "最新價",
+		"b0": "漲跌幅",
+		"b1": "點擊登錄",
+		"b2": "歡迎來到",
+		"b3": "請登錄",
+		"b4": "升級",
+		"b5": "充幣",
+		"b6": "提幣",
+		"b7": "推廣",
+		"b8": "抵扣手續費",
+		"b9": "可用",
+		"c0": "購買",
+		"c1": "我的委託",
+		"c2": "身份認證",
+		"c3": "安全中心",
+		"c4": "消息通知",
+		"c5": "提幣地址",
+		"c6": "設置",
+		"c7": "自選",
+		"c8": "添加成功",
+		"c9": "取消成功",
+		"d0": "首頁",
+		"d1": "交易",
+		"d2": "資產",
+		"d3": "請輸入搜索關鍵詞",
+		"d4": "全部",
+		"d5": "主板",
+		"d6": "總資產折合",
+		"d7": "資金賬戶",
+		"d8": "劃轉",
+		"d9": "搜索幣種",
+		"e0": "隱藏",
+		"e1": "餘額資產",
+		"e2": "凍結",
+		"e3": "折合",
+		"e4": "合約賬戶",
+		"e5": "合約折合",
+		"e6": "礦工等級",
+		"e7": "礦工",
+		"e8": "APP",
+		"e9": "簽到",
+		"f0": "立即簽到",
+		"f1": "每天簽到獲得",
+		"f2": "連續簽到7天則額外贈送",
+		"f3": "買幣",
+		"f4": "ETH Layer2",
+		"f5": "邀請獎勵",
+		"f6": "獎勵自動派送",
+		"f7": "如果中斷簽到 則不可獲得獎勵",
+		"f8": "24H量",
+		"f9": "捐款",
+		"g1": "閃兌",
+		"g2": "關於我們",
+		"g3": "版本6.0.7",
+		"g4": "幫助中心",
+		"g5": "未綁定",
+		"g6": "語言切換",
+		"g7": "交易對",
+		"g8": "價格",
+		"g9": "漲幅",
+		"h0": "已綁定",
+		"h1": "維護更新中",
+		"h2": "永續合約"
+	},
+	"aboutUs": {
+		"a0": "關於我們",
+		"a1": "和"
+	},
+	"accountSettings": {
+		"a0": "賬號設置",
+		"a1": "頭像",
+		"a2": "暱稱",
+		"a3": "主賬號",
+		"a4": "手機號",
+		"a5": "解綁",
+		"a6": "綁定",
+		"a7": "郵箱綁定",
+		"a8": "切換賬戶",
+		"a9": "退出登錄",
+		"b0": "修改暱稱",
+		"b1": "請輸入暱稱",
+		"b2": "語言"
+	},
+	"assets": {
+		"a0": "提幣地址管理",
+		"a1": "地址簿可以用來管理您的常用地址,往地址簿中存在的地址發起提幣時,無需進行多重校驗。",
+		"a2": "已支持自動提幣,使用{name}提幣時,只允許網地址簿中存在的地址發起提幣。",
+		"a3": "刪除地址",
+		"a4": "添加地址",
+		"a5": "請選擇要刪除的地址",
+		"a6": "是否刪除當前選中地址",
+		"a7": "流水",
+		"a8": "總額",
+		"a9": "可用",
+		"b0": "凍結",
+		"b1": "資金賬戶",
+		"b2": "合約賬戶",
+		"b3": "槓桿賬戶",
+		"b4": "理財賬戶",
+		"b5": "請輸入搜索關鍵詞",
+		"b6": "提幣",
+		"b7": "請選擇鏈類型",
+		"b8": "提幣地址",
+		"b9": "請輸入地址",
+		"b10": "請輸入搜索關鍵詞",
+		"c0": "數量",
+		"c1": "餘額",
+		"c2": "請輸入數量",
+		"c3": "全部",
+		"c4": "手續費",
+		"c5": "請仔細檢查並輸入正確的提幣錢包地址。",
+		"c6": "發送不對應的數字貨幣到錢包地址會造成永久性的損失。",
+		"c7": "提幣手續費將從提幣數量中扣除。",
+		"c8": "提幣記錄",
+		"c9": "時間",
+		"d0": "狀態",
+		"d1": "審核中",
+		"d2": "成功",
+		"d3": "失敗",
+		"d4": "查看更多",
+		"d5": "提交成功,正在審核",
+		"d6": "編輯",
+		"d7": "添加",
+		"d8": "地址",
+		"d9": "請輸入或粘貼地址",
+		"e0": "備註",
+		"e1": "請輸入備註",
+		"e2": "請填寫地址",
+		"e3": "請填寫備註",
+		"e4": "操作成功",
+		"e5": "充幣",
+		"e6": "掃描上方二維碼獲取充幣地址",
+		"e7": "充幣地址",
+		"e8": "充幣數量",
+		"e9": "請輸入充幣數量",
+		"f0": "此地址是您最新的充值地址,當系統收到充值時,將進行自動入賬。",
+		"f1": "轉賬需要由整個區塊鍊網絡進行確認,到達{num}個網絡確認時,您的{name}將被自動存入賬戶中。",
+		"f2": "個網絡確認時,您的",
+		"f3": "請只發送{name}到此地址,發送其他數字貨幣到此地址會造成永久性的損失。",
+		"f4": "充幣記錄",
+		"g1": "地址劃轉",
+		"g2": "銀行卡匯款",
+		"g3": "信用卡支付",
+		"g4": "複製地址",
+		"h1":"請輸入帶有國家代碼的電話號碼"
+	},
+	"auth": {
+		"a0": "身份認證",
+		"a1": "實名認證",
+		"a2": "未認證",
+		"a3": "已認證",
+		"a4": "高級認證",
+		"a5": "審核中",
+		"a6": "認證失敗",
+		"a7": "國籍",
+		"a8": "請選擇國籍",
+		"a9": "真實姓名",
+		"b0": "請輸入真實姓名",
+		"b1": "證件號碼",
+		"b2": "請輸入證件號碼",
+		"b3": "確認",
+		"b4": "認證成功",
+		"b5": "請上傳證件正面照片",
+		"b6": "請上傳證件背面",
+		"b7": "請上傳手持證件照",
+		"b8": "確保照片清晰無水印,且上半身完整",
+		"b9": "文件尺寸過大,不得超過",
+		"c0": "文件類型錯誤",
+		"c1": "上傳成功",
+		"c2": "請上傳證件背面照",
+		"c3": "請上傳證件正面照",
+		"c4": "上傳成功,請等待審核"
+	},
+	"exchange": {
+		"a0": "幣幣",
+		"a1": "申購",
+		"a2": "合約",
+		"a3": "交易",
+		"a4": "當前委託",
+		"a5": "歷史委託",
+		"a6": "添加成功",
+		"a7": "取消成功",
+		"a8": "發行總量",
+		"a9": "流通總量",
+		"b0": "發行價格",
+		"b1": "發行時間",
+		"b2": "白皮書地址",
+		"b3": "官網地址",
+		"b4": "簡介",
+		"b5": "買",
+		"b6": "賣",
+		"b7": "委託價",
+		"b8": "類型",
+		"b9": "限價交易",
+		"c0": "市價交易",
+		"c1": "已成交",
+		"c2": "總計",
+		"c3": "買入",
+		"c4": "賣出",
+		"c5": "數量",
+		"c6": "在最佳市場價格成交",
+		"c7": "總價",
+		"c8": "可用數量",
+		"c9": "總值",
+		"d0": "登錄",
+		"d1": "分時圖",
+		"d2": "價格",
+		"d3": "最新成交",
+		"d4": "時間",
+		"d5": "方向",
+		"d6": "限價",
+		"d7": "市價",
+		"d8": "請輸入價格",
+		"d9": "請輸入數量",
+		"e0": "請輸入總價",
+		"e1": "下單成功",
+		"e2": "平均價格",
+		"e3": "最高",
+		"e4": "最低",
+		"e5": "量",
+		"e6": "買賣盤",
+		"e7": "幣種信息",
+		"e8": "分鐘",
+		"e9": "小時",
+		"e10": "分鐘",
+		"f0": "天",
+		"f1": "週",
+		"f2": "月",
+		"f3": "買價",
+		"f4": "賣價",
+		"f5": "幣幣交易",
+		"f6": "請輸入搜索關鍵詞",
+		"f7": "交易對",
+		"f8": "最新價",
+		"f9": "漲跌幅",
+		"g0": "自選",
+		"g1": "我的委託",
+		"g2": "撤銷委託",
+		"g3": "操作",
+		"g4": "撤銷",
+		"g5": "是否撤銷當前委託",
+		"g6": "撤銷成功",
+		"g7":"分時"
+	},
+	"option": {
+		"a0": "期權",
+		"a1": "距離交割",
+		"a2": "看多",
+		"a3": "看空",
+		"a4": "收益率",
+		"a5": "購買",
+		"a6": "多",
+		"a7": "空",
+		"a8": "當前",
+		"a9": "下期",
+		"b0": "看平",
+		"b1": "漲幅選擇",
+		"b2": "收益率",
+		"b3": "購買數量",
+		"b4": "請輸入數量",
+		"b5": "餘額",
+		"b6": "預計收益",
+		"b7": "立即購買",
+		"b8": "漲",
+		"b9": "平",
+		"c0": "跌",
+		"c1": "購買成功",
+		"c2": "詳情",
+		"c3": "訂單號",
+		"c4": "開盤價",
+		"c5": "收盤價",
+		"c6": "買入時間",
+		"c7": "買入數量",
+		"c8": "購買類型",
+		"c9": "狀態",
+		"d0": "交割結果",
+		"d1": "結算數量",
+		"d2": "交割時間",
+		"d3": "查看更多",
+		"d4": "購買期權",
+		"d5": "等待交割",
+		"d6": "我的交割",
+		"d7": "交割記錄",
+		"d8": "分鐘",
+		"d9": "小時",
+		"d10": "分時",
+		"e0": "天",
+		"e1": "週",
+		"e2": "月",
+		"e3": "方向",
+		"e4": "漲跌幅",
+		"e5":"請輸入1000~6000",
+		"e6":"請輸入10000-30000",
+		"e7":"請輸入60000-100000",
+		"e8":"請輸入200000-300000",
+		"e9":"請輸入600000-1000000",
+		"e10":"請輸入超過3,000,000"
+	},
+	"purchase": {
+		"a0": "發行價",
+		"a1": "申購幣種",
+		"a2": "預計上線時間",
+		"a3": "開始申購時間",
+		"a4": "結束申購時間",
+		"a5": "申購",
+		"a6": "請選擇申購幣種",
+		"a7": "購買數量",
+		"a8": "請輸入申購數量",
+		"a9": "全部",
+		"b0": "立即申購",
+		"b1": "申購週期",
+		"b2": "項目預熱",
+		"b3": "開始申購",
+		"b4": "結束申購",
+		"b5": "公佈結果",
+		"b6": "項目詳情",
+		"b7": "是否使用",
+		"b8": "購買",
+		"b9": "申購成功",
+		"d1":"付款方式",
+		"d2":"請輸入正確的金額"
+	},
+	"reg": {
+		"a0": "手機註冊",
+		"a1": "郵箱註冊",
+		"a2": "手機",
+		"a3": "請輸入手機號",
+		"a4": "郵箱",
+		"a5": "請輸入郵箱號",
+		"a6": "驗證碼",
+		"a7": "請輸入驗證碼",
+		"a8": "密碼",
+		"a9": "請輸入密碼",
+		"b0": "確認密碼",
+		"b1": "請確認密碼",
+		"b2": "推薦人",
+		"b3": "請輸入推薦人",
+		"b4": "選填",
+		"b5": "您已同意",
+		"b6": "用戶協議",
+		"b7": "並了解我們的",
+		"b8": "隱私協議",
+		"b9": "註冊",
+		"c0": "已有賬號?",
+		"c1": "立即登錄",
+		"c2": "請閱讀並同意協議",
+		"c3": "請填寫手機號",
+		"c4": "請填寫郵箱號",
+		"c5": "註冊成功"
+	},
+	"safe": {
+		"a0": "解綁",
+		"a1": "綁定",
+		"a2": "郵箱",
+		"a3": "郵箱號",
+		"a4": "請輸入郵箱號",
+		"a5": "郵箱驗證碼",
+		"a6": "請輸入驗證碼",
+		"a7": "驗證碼",
+		"a8": "解綁成功",
+		"a9": "綁定成功",
+		"b0": "忘記登錄密碼",
+		"b1": "賬號",
+		"b2": "請輸入手機/郵箱號",
+		"b3": "新密碼",
+		"b4": "請輸入新密碼",
+		"b5": "確認密碼",
+		"b6": "請確認密碼",
+		"b7": "確認修改",
+		"b8": "請輸入正確的郵箱號",
+		"b9": "谷歌驗證器",
+		"c0": "操作方法:下載並打開谷歌驗證器,掃描下方二維碼或手動輸入秘鑰添加驗證令牌。",
+		"c1": "複製密鑰",
+		"c2": "我已經妥善保存密鑰,丟失後將不可找回。",
+		"c3": "下一步",
+		"c4": "短信驗證碼",
+		"c5": "谷歌驗證碼",
+		"c6": "確認綁定",
+		"c7": "安全中心",
+		"c8": "登錄密碼",
+		"c9": "修改",
+		"d0": "設置",
+		"d1": "交易密碼",
+		"d2": "手機",
+		"d3": "修改成功",
+		"d4": "手機號",
+		"d5": "請輸入手機號",
+		"d6": "請輸入短信驗證碼",
+		"d7": "關閉",
+		"d8": "開啟",
+		"d9": "驗證",
+		"e0": "短信",
+		"e1": "關閉成功",
+		"e2": "開啟成功",
+		"e3": "確認",
+		"e4": "設置成功",
+		"f1":"密碼和確認密碼不匹配",
+		"f2":"驗證碼錯誤"
+	},
+	"transfer": {
+		"a0": "劃轉記錄",
+		"a1": "成功",
+		"a2": "數量",
+		"a3": "方向",
+		"a4": "資金賬戶",
+		"a5": "合約賬戶",
+		"a6": "槓桿賬戶",
+		"a7": "理財賬戶",
+		"a8": "劃轉",
+		"a9": "從",
+		"b0": "至",
+		"b1": "劃轉幣種",
+		"b2": "餘額",
+		"b3": "全部",
+		"b4": "劃轉成功"
+	},
+	"notice": {
+		"a0": "詳情",
+		"a1": "消息通知",
+		"a2": "公告",
+		"a3": "消息"
+	},
+	"invite": {
+		"a0": "邀請好友",
+		"a1": "合夥人",
+		"a2": "尊享交易返佣",
+		"a3": "普通用戶",
+		"a4": "我的身份",
+		"a5": "尊享身份",
+		"a6": "我的邀請碼",
+		"a7": "複製邀請二維碼",
+		"a8": "複製邀請鏈接",
+		"a9": "我的推廣",
+		"a10":"邀請碼",
+		"b0": "推廣總人數",
+		"b1": "人",
+		"b2": "總收益折合",
+		"b3": "推廣記錄",
+		"b4": "直接邀請",
+		"b5": "返佣記錄",
+		"b6": "等級",
+		"b7": "級別設定",
+		"b8": "晉升條件",
+		"b9": "分紅權益",
+		"c0": "暱稱",
+		"c1": "推廣人數",
+		"c2": "收益折合",
+		"c3": "邀請記錄",
+		"c4": "返佣記錄",
+		"c5": "等級權益說明",
+		"c6": "等級",
+		"c7": "權益",
+		"c8": "說明",
+		"c9": "我的權益"
+	},
+	"help": {
+		"a0": "詳情",
+		"a1": "學院",
+		"a2": "分類"
+	},
+	"login": {
+		"a0": "郵箱號",
+		"a1": "請輸入郵箱號",
+		"a2": "密碼",
+		"a3": "請輸入密碼",
+		"a4": "登錄",
+		"a5": "忘記密碼",
+		"a6": "沒有賬號",
+		"a7": "立即註冊",
+		"a8": "手機",
+		"a9": "郵箱",
+		"b0": "完成"
+	},
+	"contract": {
+		"title": "合約",
+		"a": "合約流水",
+		"a0": "開倉",
+		"a1": "持倉",
+		"a2": "委託",
+		"a3": "歷史",
+		"a4": "合約交易",
+		"a5": "開通成功",
+		"a6": "交易類型",
+		"a7": "已成交",
+		"a8": "委託總量",
+		"a9": "成交均價",
+		"b0": "平倉均價",
+		"b1": "保證金",
+		"b2": "手續費",
+		"b3": "狀態",
+		"b4": "操作",
+		"b5": "撤單",
+		"b6": "已撤銷",
+		"b7": "未成交",
+		"b8": "部分成交",
+		"b9": "全部成交",
+		"c0": "買入",
+		"c1": "平空",
+		"c2": "賣出",
+		"c3": "平多",
+		"c4": "溫馨提示",
+		"c5": "是否撤銷當前訂單",
+		"c6": "撤銷成功",
+		"c7": "盈虧",
+		"c8": "分享",
+		"c9": "委託詳情",
+		"d0": "暫無數據",
+		"d1": "價格",
+		"d2": "數量",
+		"d3": "成交時間",
+		"d4": "用戶權益",
+		"d5": "未實現盈虧",
+		"d6": "風險率",
+		"d7": "市價",
+		"d8": "張",
+		"d9": "佔用保證金",
+		"e0": "買入(做多)",
+		"e1": "可開多",
+		"e2": "賣出(做空)",
+		"e3": "可開空",
+		"e4": "可用",
+		"e5": "劃轉",
+		"e6": "資金費率",
+		"e7": "距離結算",
+		"e8": "多",
+		"e9": "空",
+		"f0": "資金劃轉",
+		"f1": "計算器",
+		"f2": "關於合約",
+		"f3": "風險保障基金",
+		"f4": "資金費用歷史",
+		"f5": "普通委託",
+		"f6": "市價委託",
+		"f7": "是否以",
+		"f8": "的價格",
+		"f9": "倍槓桿開倉",
+		"g0": "開多",
+		"g1": "開空",
+		"g2": "委託成功",
+		"g3": "僅顯示當前合約",
+		"g4": "可平量",
+		"g5": "委託凍結",
+		"g6": "開倉平均價",
+		"g7": "結算基準價",
+		"g8": "預估強平價",
+		"g9": "已結算收益",
+		"h0": "收益率",
+		"h1": "止盈",
+		"h2": "止損",
+		"h3": "平倉",
+		"h4": "市價全平",
+		"h5": "止盈止損",
+		"h6": "平",
+		"h7": "請輸入平倉價格",
+		"h8": "限價",
+		"h9": "請輸入平倉數量",
+		"i0": "可平",
+		"i1": "開倉均價",
+		"i2": "最新成交價",
+		"i3": "請輸入價格",
+		"i4": "止盈觸發價",
+		"i5": "市價至",
+		"i6": "時將觸發止盈委託,成交後預計盈虧",
+		"i7": "止損觸發價",
+		"i8": "時將觸發止損委託,成交後預計盈虧",
+		"i9": "確定",
+		"j0": "平倉成功",
+		"j1": "是否市價全平",
+		"j2": "全平",
+		"j3": "成功",
+		"j4": "設置成功",
+		"j5": "神機妙算,無可匹敵",
+		"j6": "做",
+		"j7": "平倉價格",
+		"j8": "數字資產交易平台",
+		"j9": "當1遇上2 3的火熱飛升之路",
+		"k0": "開倉價格",
+		"k1": "最新價格",
+		"k2": "掃碼了解更多",
+		"k3": "結算盈虧",
+		"k4": "截圖成功,已保存到本地",
+		"k5": "截圖失敗",
+		"k6": "長按截圖",
+		"k7": "一鍵平倉",
+		"k8": "一鍵反向",
+		"k9": "是否一鍵平倉",
+		"l0": "平倉成功",
+		"l1": "是否一鍵反向",
+		"l2": "反向成功",
+		"l3": "平空"
+	},
+	"otc": {
+		"a0": "發布廣告",
+		"a1": "訂單",
+		"a2": "交易幣種",
+		"a3": "我的訂單",
+		"a4": "我的廣告",
+		"a5": "購買",
+		"a6": "出售",
+		"a7": "總數",
+		"a8": "剩餘",
+		"a9": "限量",
+		"b0": "單價",
+		"b1": "支付方式",
+		"b2": "操作",
+		"b3": "總量",
+		"b4": "請選擇支付方式",
+		"b5": "請輸入數量",
+		"b6": "下單",
+		"b7": "支付寶",
+		"b8": "微信",
+		"b9": "銀行卡",
+		"c0": "下單成功",
+		"c1": "狀態",
+		"c2": "廣告編號",
+		"c3": "總價",
+		"c4": "數量",
+		"c5": "發佈時間",
+		"c6": "下架",
+		"c7": "已撤銷",
+		"c8": "交易中",
+		"c9": "已完成",
+		"d0": "溫馨提示",
+		"d1": "是否下架當前廣告",
+		"d2": "確定",
+		"d3": "取消",
+		"d4": "撤銷成功",
+		"d5": "法幣賬戶",
+		"d6": "凍結",
+		"d7": "支付寶賬號",
+		"d8": "請輸入賬號",
+		"d9": "姓名",
+		"e0": "請輸入姓名",
+		"e1": "付款碼",
+		"e2": "綁定",
+		"e3": "微信賬號",
+		"e4": "銀行名稱",
+		"e5": "請輸入銀行名稱",
+		"e6": "開戶支行",
+		"e7": "請輸入開戶支行",
+		"e8": "銀行卡號",
+		"e9": "請輸入銀行卡號",
+		"f0": "編輯成功",
+		"f1": "添加成功",
+		"f2": "賣出",
+		"f3": "買入",
+		"f4": "訂單詳情",
+		"f5": "訂單號",
+		"f6": "賬號",
+		"f7": "開戶銀行",
+		"f8": "剩餘時間",
+		"f9": "分",
+		"g0": "秒",
+		"g1": "上傳支付憑證",
+		"g2": "確認付款",
+		"g3": "取消訂單",
+		"g4": "確認收款",
+		"g5": "未到賬",
+		"g6": "是否取消當前訂單",
+		"g7": "訂單已取消",
+		"g8": "確認當前已付款",
+		"g9": "操作成功",
+		"h0": "確認收款後將掛賣資產將自動劃轉",
+		"h1": "確認未收到款項後,此訂單將自動進入申訴",
+		"h2": "出售訂單",
+		"h3": "購買訂單",
+		"h4": "廣告購買訂單",
+		"h5": "廣告出售訂單",
+		"h6": "時間",
+		"h7": "詳情",
+		"h8": "全部",
+		"h9": "已關閉",
+		"i0": "待支付",
+		"i1": "待確認",
+		"i2": "申訴中",
+		"i3": "廣告類型",
+		"i4": "請選擇交易類型",
+		"i5": "請選擇交易幣種",
+		"i6": "價格",
+		"i7": "請輸入價格",
+		"i8": "最低價",
+		"i9": "請輸入最低價",
+		"j0": "最高價",
+		"j1": "請輸入最高價",
+		"j2": "備註",
+		"j3": "請輸入備註",
+		"j4": "發布",
+		"j5": "發布成功",
+		"j6": "收款管道",
+		"j7": "最低量",
+		"j8": "最高量",
+		"j9": "請輸入最低交易量",
+		"k0": "請輸入最高交易量"
+	},
+	"pledge": {
+		"introduce":"項目介紹",
+		"funcname":"質押挖礦",
+		"detail":"訂單詳情",
+		"join":"參與節點",
+		"biz":"質押幣種",
+		"cycle":"週期",
+		"rate":"浮動日利率",
+		"zynum":"數量",
+		"ordernum":"訂單編號",
+		"profit":"預估收益",
+		"create_time":"創建時間",
+		"end_time":"結束時間",
+		"record":"訂單記錄",
+		"bzkyzc":"幣種可用資產",
+		"zdyxt":"自定義選填",
+		"ljzy":"加入節點",
+		"goorder":"是否查看訂單",
+		"income":"收益中",
+		"completed":"已完成",
+		"maxnum":"最大數量",
+		"minnum":"最小數量",
+		"note":"注",
+		"qtxhlfwndsz":"請填寫範圍內的數值",
+		"a1":"開始質押",
+		"a2":"質押金額",
+		"a3":"當前匯率",
+		"a4":"質押需要支付",
+		"a5":"請確保帳戶餘額充足",
+		"a6":"提交",
+		"a7":"邀請更多好友解鎖次數",
+		"a8":"邀請好友解鎖次數",
+		"a9":"邀請",
+		"b1":"個好友",
+		"b2":"參與質押即可解鎖一次",
+		"b3":"邀請好友",
+		"b4":"取消",
+		"c1":"ETH Layer 2",
+		"c2":"節點生態",
+		"c3":"ETH Layer 2是一種透過節點算力實現真正挖礦技術的智能合約。以太坊的共識算法從工作證明轉變為權益證明的第一步。通過權益證明,更多技術用戶可以運行自己的驗證節點並質押他們的USDT並獲得收益。使用以太坊主網的將以金融機構、鯨魚、Layer 2協議等機構和大戶為主,更多普通用戶將選擇在Layer 2進行鏈上交易。參與Layer 2擴容方案的投資者能共享節省下來的燃料費,共同創造更美好的生態。",
+		"c4":"節點優勢",
+		"c5":"高交互、低成本",
+		"c6":"可擴容、低延遲",
+		"c7":"公信力高",
+		"c8":"每日發放",
+		"c9":"去中心透明化",
+		"d1":"100%資金安全保障",
+		"d2":"全年收益不間斷",
+		"d3":"節點獎勵計算",
+		"d4":"參與用戶在平台加入了100000 USDT的小型礦機節點,週期為30天,每日產出根據浮動日利率進行計算。假設當日最低浮動利率為0.35%,最高浮動利率為0.38%",
+		"d5":"最低: 100000 USDT* 0.35% = 350 USDT",
+		"d6":"最高:100000 USDT* 0.38% = 380 USDT",
+		"d7":"即30天后可以獲得10500~11400 USDT的節點獎勵。節點獎勵每日發放,發放的獎勵可以隨時存取,智能合約到期後本金將自動轉入您的資產賬戶中。",
+		"d8":"合約違約條款",
+		"d9":"如用戶需要將進行中的智能合約解除並提取本金,則會產生一筆違約費用",
+		"e1":"違約費用=違約結算比例*剩餘天數*資金金額",
+		"e2":"舉例:該參與節點的違約結算比例為0.5%,剩馀5天合約到期,資金比例為1000,則違約金= 1000*5天*0.5%=25 USDT,實際退還資金為1000 USDT-25 USDT=975 USDT",
+		"e3":"進入ETH Layer 2",
+		"e4":"節點選擇",
+		"e5":"單筆限額",
+		"e6":"智能合約節點",
+		"e7":"浮動利率",
+		"e8":"算力",
+		"e9":"預計節點獎勵",
+		"f1":"實際收益"
+	}
+}

+ 4 - 2
main.js

@@ -1,6 +1,7 @@
 import Vue from 'vue'
 import store from './store'
 import App from './App'
+import i18n from './libs/i18n/index.js'
 /**
  *  所有测试用数据均存放于根目录json.js
  *  
@@ -30,15 +31,16 @@ const prePage = ()=>{
 	return prePage.$vm;
 }
 
-
 Vue.config.productionTip = false
 Vue.prototype.$fire = new Vue();
+Vue.prototype._i18n = i18n;
 Vue.prototype.$store = store;
 Vue.prototype.$api = {msg, prePage};
 
 App.mpType = 'app'
 
 const app = new Vue({
-    ...App
+    ...App,
+	i18n
 })
 app.$mount()

+ 25 - 11
pages.json

@@ -35,9 +35,12 @@
 					"navigationStyle": "custom"
 				}
 		},
+<<<<<<< HEAD
 		
 		
 		
+=======
+>>>>>>> 5484fdcffd2d98e5c349c7b62d17099d3096b743
 		{
 			"path": "pages/public/register",
 			"style": {
@@ -83,19 +86,12 @@
 			}
 		},
 		
-		
-		
-		
-		
 		{
 			"path": "pages/set/set",
 			"style": {
 				"navigationBarTitleText": "设置"
 			}
 		},
-		
-		
-		
 		{
 			"path": "pages/set/phone",
 			"style": {
@@ -163,10 +159,6 @@
 				}
 			}
 		},
-		
-		
-		
-		
 		{
 			"path": "pages/money/paySuccess",
 			"style": {
@@ -354,36 +346,58 @@
 		"selectedColor": "#FEB041 ",
 		"borderStyle": "black",
 		"backgroundColor": "#000000",
+<<<<<<< HEAD
 		"list": [{
 			    // "visible":false,
+=======
+		"list": [
+			{
+				"visible":false,
+>>>>>>> 5484fdcffd2d98e5c349c7b62d17099d3096b743
 				"pagePath": "pages/index/index",
 				"iconPath": "static/tabBar/shouye.png",
 				"selectedIconPath": "static/tabBar/shouye-home.png",
 				"text": "首頁"
 			},
 			{
+<<<<<<< HEAD
 				// "visible":false,
+=======
+				"visible":false,
+>>>>>>> 5484fdcffd2d98e5c349c7b62d17099d3096b743
 				"pagePath": "pages/index/pledge",
 				"iconPath": "static/tabBar/baoya.png",
 				"selectedIconPath": "static/tabBar/baoya-home.png",
 				"text": "質押"
 			},
 			{
+<<<<<<< HEAD
 				// "visible":false,
+=======
+				"visible":false,
+>>>>>>> 5484fdcffd2d98e5c349c7b62d17099d3096b743
 				"pagePath": "pages/index/entertainment",
 				"iconPath": "static/tabBar/huyu.png",
 				"selectedIconPath": "static/tabBar/huyu-home.png",
 				"text": "互娛"
 			},
 			{
+<<<<<<< HEAD
 				// "visible":false,
+=======
+				"visible":false,
+>>>>>>> 5484fdcffd2d98e5c349c7b62d17099d3096b743
 				"pagePath": "pages/index/information",
 				"iconPath": "static/tabBar/zixun.png",
 				"selectedIconPath": "static/tabBar/zixun-home.png",
 				"text": "資訊"
 			},
 			{
+<<<<<<< HEAD
 				// "visible":false,
+=======
+				"visible":false,
+>>>>>>> 5484fdcffd2d98e5c349c7b62d17099d3096b743
 				"pagePath": "pages/index/user",
 				"iconPath": "static/tabBar/my.png",
 				"selectedIconPath": "static/tabBar/my-home.png",

+ 5 - 0
pages/index/index.vue

@@ -62,11 +62,16 @@
 				</text>
 			</view>
 		</view>
+		<taber tab='index'></taber>
 	</view>
 </template>
 <script>
 	import { mapState, mapActions } from "vuex";
+	import taber from "@/components/footer/footer.vue";
 	export default {
+		components: {
+			taber
+		},
 		data() {
 			return {
 				indicatorDots: true,

+ 5 - 8
pages/index/pledge.vue

@@ -101,14 +101,16 @@
 				</view>
 			</view>
 		</view>
-		<view class="aa">
-			
-		</view>
+		<taber tab='pledge'></taber>
 	</view>
 </template>
 
 <script>
+	import taber from "@/components/footer/footer.vue";
 	export default {
+		components: {
+			taber
+		},
 		data() {
 			return {};
 		},
@@ -221,9 +223,4 @@
 	.r3{
 		margin-top: 50rpx;
 	}
-	.aa {
-		width: 750rpx;
-		height: 20rpx;
-		background-color: #000000;
-	}
 </style>

+ 0 - 119
pages/information/information.vue

@@ -1,119 +0,0 @@
-<template>
-	<view class="content">
-		<view class="list" @click="navigator">
-			<image class="img" src="../../static/img/zixun1.png" mode=""></image>
-			<view class="text">
-				互娛遊戲玩法介紹
-			</view>
-		</view>
-		<view class="">xian</view>
-		<view class="list" @click="navigatorT"> 
-			<image class="img" src="../../static/img/zixun2.png" mode=""></image>
-			<view class="text">
-				互娛遊戲推廣計劃
-			</view>
-		</view>
-		<view class="">xian</view>
-		<view class="list" @click="navigatorY">
-			<image class="img" src="../../static/img/zixun3.png" mode=""></image>
-			<view class="text">
-				互娛遊戲舉例
-			</view>
-		</view>
-		<view class="">xian</view>
-		<view class="list" @click="navigatorH">
-			<image class="img" src="../../static/img/zixun4.png" mode=""></image>
-			<view class="text">
-				互娛共享
-			</view>
-		</view>
-		<view class="">xian</view>
-		
-		<view class="tit">
-			項目亮點
-		</view>
-		<image class="img" src="../../static/img/zixun5.png" mode="" ></image>
-	</view>
-</template>
-
-<script>
-	export default {
-		data() {
-			return {};
-		},
-		methods: {
-			navigator() {
-				uni.navigateTo({
-					url: '/pages/introduce/introduce'
-				})
-			},
-			navigatorT() {
-				uni.navigateTo({
-					url: '/pages/promotion/promotion'
-				})
-			},
-			navigatorY() {
-				uni.navigateTo({
-					url: '/pages/game/game'
-				})
-			},
-			navigatorH() {
-				uni.switchTab({
-					url: '/pages/entertainment/entertainment'
-				})
-			},
-		}
-	};
-</script>
-
-<style lang="scss">
-.content{
-	width: 750rpx;
-	height: 1800rpx;
-	background-color: #000000;
-}
-
-.list {
-	height: 180rpx;
-	display: flex;
-	justify-content: start;
-	.img {
-		margin-left: 30rpx;
-		margin-top: 20rpx;
-		width: 200rpx;
-		height: 160rpx;
-	}
-	.text {
-		margin-left: 15rpx;
-		margin-top: 30rpx;
-		// width: 237rpx;
-		height: 29rpx;
-		font-size: 30rpx;
-		font-family: PingFang SC;
-		font-weight: bold;
-		color: #FFFFFF;
-		line-height: 39rpx;
-	}
-}
-	
-	
-
-.tit {
-	margin-top: 40rpx;
-	margin-left: 279rpx;
-	// width: 191rpx;
-	height: 46rpx;
-	font-size: 49rpx;
-	font-family: PingFang SC;
-	font-weight: 500;
-	color: #FFFFFF;
-	line-height: 21rpx;
-}
-
-.img {
-	margin-top: 26rpx;
-	margin-left: 11rpx;
-	width: 728rpx;
-	height: 538rpx;
-}
-</style>

+ 0 - 229
pages/pledge/pledge.vue

@@ -1,229 +0,0 @@
-<template>
-	<view class="all">
-		<view class="top">
-			<text>互娛共享</text>
-		</view>
-		<view class="img">
-			<image
-				src="../../static/img/zhiya2.png"
-				mode=""
-				style="width: 696rpx; height: 254rpx"></image>
-		</view>
-		<view @click="navigator"
-			class="my"
-			flex>
-			<image
-				src="../../static/img/zhiya3.png"
-				mode=""
-				style="
-					width: 40rpx;
-					height: 40rpx;
-					margin-left: 50rpx;
-					margin-top: 23rpx;
-					margin-bottom: 22rpx;
-				"></image>
-			<view>我的質押</view>
-			<image
-				class="right"
-				src="../../static/img/zhiya1.png"
-				style="width: 16rpx; height: 26rpx"
-				mode=""></image>
-		</view>
-		<view class="buttom" flex v-for="item in 12">
-			<view class="le" @click="nav">
-				<view
-					class="le1"
-					style="
-						height: 32rpx;
-						font-size: 33rpx;
-						font-weight: 800;
-						color: #ffffff;
-						line-height: 43rpx;
-					">
-					質押投資一
-				</view>
-				<view
-					class="le1"
-					style="
-						height: 19rpx;
-						font-size: 20rpx;
-						font-family: PingFang SC;
-						font-weight: 800;
-						color: #feb041;
-						line-height: 43rpx;
-					">
-					20U起投 | 1天
-				</view>
-				<view
-					class="le1"
-					style="
-						height: 19rpx;
-						font-size: 20rpx;
-						font-family: PingFang SC;
-						font-weight: 800;
-						color: #feb041;
-						line-height: 43rpx;
-					">
-					總額:1234534.3456U
-				</view>
-				<view class="le2">
-					<button
-						style="
-							width: 308rpx;
-							height: 16rpx;
-							background: #ebebeb;
-							opacity: 0.38;
-							border-radius: 8rpx;
-							margin-top: 50rpx;
-						"></button>
-					<p style="">42.94%</p>
-				</view>
-			</view>
-			<view class="ri">
-				<view class="r1"> 1.00% </view>
-				<view class="r2"> 日均收益率 </view>
-				<view class="r3">
-					<view style="background: #feb041; border-radius: 6rpx; width: 139rpx; height: 44rpx;">
-						<text
-							style="
-							padding-top: 23rpx;
-							margin-left: 20rpx;
-							    text-align: center;
-								width: 82rpx;
-								height: 20rpx;
-								font-size: 21rpx;
-								font-family: PingFang SC;
-								font-weight: 800;
-								color: #191a1f;
-							"
-							>立即加入</text>
-						</view>
-				</view>
-			</view>
-		</view>
-		<view class="aa">
-			
-		</view>
-	</view>
-</template>
-
-<script>
-	export default {
-		data() {
-			return {};
-		},
-		methods: {
-			navigator() {
-				uni.navigateTo({
-					url: '/pages/myPledge/myPledge'
-				})
-			},
-			nav() {
-				uni.navigateTo({
-					url: '/pages/zyXingqing/zyXingqing'
-				})
-			}
-		}
-	};
-</script>
-
-<style lang="scss">
-	.all {
-		width: 750rpx;
-		height: 100%;
-		background-color: #000000;
-	}
-	.top {
-		// margin-top: 77rpx;
-		padding-top: 40rpx;
-		margin-left: 305rpx;
-		height: 34rpx;
-		font-size: 36rpx;
-		font-family: PingFang SC;
-		font-weight: bold;
-		color: #ffffff;
-		line-height: 55rpx;
-	}
-
-	.img {
-		margin-left: 27rpx;
-		margin-top: 58rpx;
-	}
-	.my {
-		margin-top: 23rpx;
-		background-color: #191a1f;
-		display: flex;
-
-		view {
-			flex-grow: 1;
-			font-size: 30rpx;
-			font-family: PingFang SC;
-			font-weight: bold;
-			color: #ffffff;
-			padding-left: 20rpx;
-			padding-top: 20rpx;
-		}
-
-		.right {
-			width: 16rpx;
-			height: 26rpx;
-			margin-top: 26rpx;
-		}
-	}
-
-	.buttom {
-		display: flex;
-		justify-content: space-between;
-		width: 696rpx;
-		height: 252rpx;
-		background: #191a1f;
-		border-radius: 18rpx;
-		margin-left: 28rpx;
-		margin-top: 20rpx;
-		margin-bottom: 8rpx;
-	}
-	.le1 {
-		margin-left: 28rpx;
-		margin-top: 24rpx;
-	}
-	.le2 {
-		margin-left: 25rpx;
-
-		p {
-			height: 17rpx;
-			font-size: 21rpx;
-			font-family: PingFang SC;
-			font-weight: 500;
-			color: #999999;
-			line-height: 43rpx;
-		}
-	}
-	
-	.r1 {
-		margin-top: 35rpx;
-		height: 36rpx;
-		font-size: 47rpx;
-		font-family: PingFang SC;
-		font-weight: 800;
-		color: #FF0102;
-		line-height: 43rpx;
-	}
-	.r2 {
-		margin-top: 25rpx;
-		height: 20rpx;
-		font-size: 21rpx;
-		font-family: PingFang SC;
-		font-weight: 500;
-		color: #999999;
-		line-height: 43rpx;
-	}
-	
-	.r3{
-		margin-top: 50rpx;
-	}
-	.aa {
-		width: 750rpx;
-		height: 20rpx;
-		background-color: #000000;
-	}
-</style>

+ 0 - 554
pages/user/user.vue

@@ -1,554 +0,0 @@
-<template>
-	<view class="container">
-		<view class="top">
-			<view class="my">我的</view>
-			<view class="userinfo">
-				<view class="img">
-					<image class="image" src="../../static/error/missing-face.png" mode=""></image>
-				</view>
-				<view class="info">
-					<view>
-						<text class="infor" style="margin-left: -160rpx;">v790d7v...v469874561</text>
-					</view>
-					<view >
-						<image class="in" style="margin-left: -160rpx; margin-top: 15rpx;" src="../../static/shouye/huiyuan.png" mode=""></image>
-					</view>
-				</view>
-				<view class="" >
-					<image @click="showY" class="inf" src="../../static/shouye/userinfo.png" mode=""></image>
-				</view>
-			</view>
-		</view>
-		<view class="aaa"></view>
-		<!-- 余额 -->
-		<view class="body">
-			<view v-if="show" class="yue">
-				<view class="te">
-					餘額
-				</view>
-				<view class="tex">
-					12356.00
-				</view>
-				<view class="btn">
-					<button class="btn1" @click="navigator"> <text>充值</text> </button>
-					<button class="btn1" @click="navigatorT"> <text>提現</text> </button>
-				</view>
-			</view>
-			
-			<view v-else class="yue1">
-				<view class="tj">統計表</view>
-				<view class="ljcz">
-					<view class="lj">累計充值</view>
-					<view class="ljsu">0.000</view>
-				</view>
-				<view class="ljcz">
-					<view class="lj1">累計提現</view>
-					<view class="ljsu1">0.000</view>
-				</view>
-				<view class="ljcz">
-					<view class="lj1">累計收益</view>
-					<view class="ljsu1">0.000</view>
-				</view>
-				<view class="ljcz">
-					<view class="lj1">個人交易總量</view>
-					<view class="ljsu1">0.000</view>
-				</view>
-				<view class="ljcz">
-					<view class="lj1">團隊交易總量</view>
-					<view class="ljsu1">0.000</view>
-				</view>
-			</view>
-			
-		<!-- 列表 -->
-		<view class="gj">
-			我的工具
-		</view>
-		
-		<view class="user-list flex" @click="navTo('/pages/user/team')">
-			<image src="../../static/shouye/yue.png" mode="" class="left-img"></image>
-			<view class="">
-				餘額明細       
-			</view>
-			<image src="../../static/icon/back.png" mode="" class="right-img"></image>
-		</view>
-		<!-- 额外添加 -->
-		<view class="user-list flex" @click="navTo('/pages/user/shareQrCode')">
-			<image src="../../static/shouye/money.png" mode="" class="left-img"></image>
-			<view class="">
-				互娛記錄
-			</view>
-			<image src="../../static/icon/back.png" mode="" class="right-img"></image>
-		</view>
-		<!-- 额外添加 -->
-		<view class="user-list flex" @click="navTo('/pages/tabulation/tabulation')">
-			<image src="../../static/shouye/liebiao.png" mode="" class="left-img"></image>
-			<view class="">
-				會員列表
-			</view>
-			<image src="../../static/icon/back.png" mode="" class="right-img"></image>
-		</view>
-		<view class="user-list flex" @click="navTo('/pages/user/favorites')">
-			<image src="../../static/shouye/liebiao.png" mode="" class="left-img"></image>
-			<view class="">
-				分享鏈接
-			</view>
-			<image src="../../static/icon/back.png" mode="" class="right-img"></image>
-		</view>
-		<view class="user-list flex" @click="openKf()">
-			<image src="../../static/shouye/liuyan.png" mode="" class="left-img"></image>
-			<view class="">
-				在線留言
-			</view>
-			<image src="../../static/icon/back.png" mode="" class="right-img"></image>
-		</view>
-		<view class="user-list flex" @click="navTo('/pages/transaction/transaction')">
-			<image src="../../static/shouye/jiaoyi.png" mode="" class="left-img"></image>
-			<view class="">
-				交易密碼
-			</view>
-			<image src="../../static/icon/back.png" mode="" class="right-img"></image>
-		</view>
-		<view class="user-list flex" @click="navTo('/pages/public/login')">
-			<image src="../../static/shouye/tuichu.png" mode="" class="left-img"></image>
-			<view class="">
-			   退出登錄 
-			</view>
-			<image src="../../static/icon/back.png" mode="" class="right-img"></image>
-		</view>
-		<view class="" style="height: 20rpx;">
-		</view>
-		</view>
-		
-		<view class="" style="width: 750rpx; height: 30rpx; background-color: #000;"></view>
-	</view>
-	
-</template>
-<script>
-	import {
-		mapState,
-		mapMutations
-	} from 'vuex';
-	import uniList from '@/components/uni-list/uni-list.vue';
-	import uniListItem from '@/components/uni-list-item/uni-list-item.vue';
-	import {
-		orderData,
-		getUserInfo,
-		// check,
-		// getLevelList
-	} from '@/api/user.js';
-	import {
-		saveUrl,
-		interceptor
-	} from '@/utils/loginUtils.js';
-	let startY = 0,
-		moveY = 0,
-		pageAtTop = true;
-	export default {
-		components: {
-			uniList,
-			uniListItem
-		},
-		data() {
-			return {
-				current: 2,
-				store_name: '',
-				achievement: '',
-				code: '',
-				levelList: [],
-				show: true
-			};
-		},
-		onShow() {
-			// 判断是否已经登录
-			// if (this.hasLogin) {
-			// 	this.loadBaseData();
-			// }
-			this.loadBaseData();
-		},
-		filters: {
-			phone(e) {
-				var subStr1 = e.substr(0, 3);
-				var subStr2 = e.substr(e.length - 4, 4);
-				var subStr = subStr1 + '...' + subStr2;
-				e = subStr;
-				return e;
-			}
-		},
-		onReady() {
-			// 初始化获取页面宽度
-			uni.createSelectorQuery()
-				.select('.container')
-				.fields({
-						size: true
-					},
-					data => {
-						// 计算最多下拉的高度
-						this.userDowm = Math.floor((data.width / 750) * 185);
-						// 计算最大触发修改高度事件
-						this.userMaxDowm = Math.floor((data.width / 750) * 250);
-					}
-				)
-				.exec();
-		},
-		computed: {
-			...mapState('user', ['userInfo', 'orderInfo', 'hasLogin'])
-		},
-		methods: {
-			showY(){
-				this.show = !this.show
-			},
-			navigatorT() {
-				uni.navigateTo({
-					url: '/pages/withdrawal/withdrawal'
-				})
-			},
-			navigator() {
-				uni.navigateTo({
-					url: '/pages/recharge/recharge'
-				})
-			},
-		
-			
-			// ...mapMutations('user', ['setUserInfo']),
-			// sqdl() {
-			// 	if (this.hasLogin) {
-			// 		if (this.userInfo.enroll_status == 1) {
-
-			// 			uni.showModal({
-			// 				title: "提示",
-			// 				content: '您提交的申请正在审核中,请耐心等待审核'
-			// 			})
-			// 		} else {
-			// 			this.navTo('/pages/user/sqdl')
-			// 		}
-			// 	} else {
-			// 		this.navTo('/pages/user/sqdl')
-			// 	}
-			// },
-			// qhx() {
-			// 	check({
-			// 			verify_code: this.code,
-			// 			is_confirm: 1 //1是核销,0是查看
-			// 		})
-			// 		.then(e => {
-			// 			this.$api.msg('核销成功');
-			// 			this.close();
-			// 		})
-			// 		.catch(e => {
-			// 			console.log(e);
-			// 		});
-			// },
-			// sao() {
-			// 	let obj = this;
-
-			// 	// #ifndef H5
-			// 	uni.scanCode({
-			// 		success(e) {
-			// 			obj.code = e.result;
-			// 			obj.$refs.popuphx.open();
-			// 			console.log(obj.$refs.popuphx);
-			// 		}
-			// 	});
-			// 	// #endif
-			// },
-			// comfirm(text) {
-			// 	console.log(text);
-			// 	const result = this.uniCopy(text);
-			// 	if (result === false) {
-			// 		uni.showToast({
-			// 			title: '不支持'
-			// 		});
-			// 	} else {
-			// 		uni.showToast({
-			// 			title: '复制成功',
-			// 			icon: 'none'
-			// 		});
-			// 	}
-			// 	this.$refs.popupkf.close();
-			// },
-			
-			// 加载初始数据
-			loadBaseData() {
-				const obj = this
-				getUserInfo({})
-					.then(({
-						data
-					}) => {
-						obj.setUserInfo(data);
-
-					})
-					.catch(e => {
-						console.log(e);
-					});
-
-			},
-			/**
-			 * 统一跳转接口,拦截未登录路由
-			 * navigator标签现在默认没有转场动画,所以用view
-			 */
-			navTo(url) {
-				console.log(url);
-				if (!this.hasLogin) {
-					// 保存地址
-					saveUrl();
-					// 登录拦截
-					interceptor();
-				} else {
-					uni.navigateTo({
-						url
-					});
-				}
-			},
-			close() {
-				this.$refs.popuphx.close();
-				this.code = '';
-			},
-			
-			// 打开绑定
-			open() {
-				this.$refs.gspass.open();
-			},
-			cast() {
-				set_waiter({
-						uid: this.id
-					})
-					.then(e => {
-						this.$api.msg('绑定成功');
-						this.$refs.gspass.close();
-						this.id = '';
-					})
-					.catch(err => {
-						this.$refs.gspass.close();
-						this.id = '';
-					});
-			},
-			// cancelpass() {
-			// 	this.$refs.gspass.close();
-			// 	this.id = '';
-			// }
-		}
-	};
-</script>
-<style lang="scss">
-	.container {
-		width: 750rpx;
-		height: 100%;
-	}
-	
-	.top {
-		width: 750rpx;
-		height: 327rpx;
-		background-color: #000000;
-	}
-	.my {
-		margin-left: 40rpx;
-		padding-top: 40rpx;
-		height: 45rpx;
-		font-size: 48rpx;
-		font-family: PingFang SC;
-		font-weight: 500;
-		color: #FFFFFF;
-		line-height: 48rpx;
-	}
-	
-	.userinfo {
-		padding-top: 80rpx;
-		display: flex;
-		justify-content: space-between;
-	}
-	
-	.image {
-		margin-left: 40rpx;
-		width: 125rpx;
-		height: 125rpx;
-		
-	}
-	
-	.infor {
-		height: 23rpx;
-		font-size: 30rpx;
-		font-family: PingFang SC;
-		font-weight: 500;
-		color: #FFFFFF;
-		line-height: 48rpx;
-	}
-	.in {
-		width: 128rpx;
-		height: 45rpx;
-	}
-	.inf {
-		margin-top: 25rpx;
-		width: 48rpx;
-		height: 48rpx;
-	}
-
-.aaa {
-	width: 750rpx;
-	height: 20rpx;
-	background-color: #191a1f;
-}
-//  body
-.body {
-	width: 750rpx;
-	height: 1273rpx;
-	background-color: #191a1f;
-}
-.yue {
-	width: 700rpx;
-	height: 283rpx;
-	margin-left: 24rpx;
-	background-color: #000000;
-	
-}
-.yue1 {
-	width: 700rpx;
-	height: 360rpx;
-	margin-left: 24rpx;
-	background-color: #000000;
-}
-.tj {
-	height: 28rpx;
-	font-size: 30rpx;
-	font-family: PingFang SC;
-	font-weight: bold;
-	color: #FFFFFF;
-	margin-left: 307rpx;
-	padding-top: 35rpx;
-}
-.ljcz {
-	display: flex;
-	justify-content: space-between;
-}
-.lj {
-	height: 23rpx;
-	font-size: 24rpx;
-	font-family: PingFang SC;
-	font-weight: 500;
-	color: #FFFFFF;
-	opacity: 0.65;
-	margin-top: 61rpx;
-	margin-left: 31rpx;
-}
-.ljsu {
-	height: 18rpx;
-	font-size: 24rpx;
-	font-family: PingFang SC;
-	font-weight: 500;
-	color: #FFFFFF;
-	margin-top: 63rpx;
-	margin-right: 33rpx;
-}
-.lj1 {
-	height: 23rpx;
-	font-size: 24rpx;
-	font-family: PingFang SC;
-	font-weight: 500;
-	color: #FFFFFF;
-	opacity: 0.65;
-	margin-top: 31rpx;
-	margin-left: 31rpx;
-}
-.ljsu1{
-	height: 18rpx;
-	font-size: 24rpx;
-	font-family: PingFang SC;
-	font-weight: 500;
-	color: #FFFFFF;
-	margin-top: 33rpx;
-	margin-right: 33rpx;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-.te {
-	// margin-top: 40rpx;
-	padding-top: 40rpx;
-	margin-left: 325rpx;
-	height: 25rpx;
-	font-size: 26rpx;
-	font-family: PingFang SC;
-	font-weight: 500;
-	color: #FFFFFF;
-}
-.tex {
-	margin-left: 274rpx;
-	padding-top: 40rpx;
-	height: 37rpx;
-	font-size: 48rpx;
-	font-family: PingFang SC;
-	font-weight: bold;
-	color: #FFFFFF;
-}
-.btn {
-	margin-top: 100rpx;
-	display: flex;
-	justify-content: space-between;
-}
-.btn1 {
-	width: 276rpx;
-	height: 72rpx;
-	background: #FDB242;
-	border-radius: 10rpx;
-}
-
-.gj {
-	margin-top: 50rpx;
-	margin-left: 20rpx;
-	height: 34rpx;
-	font-size: 36rpx;
-	font-family: PingFang SC;
-	font-weight: bold;
-	color: #FFFFFF;
-	line-height: 30rpx;
-}
-
-	.user-list {
-		width: 691rpx;
-		height: 104rpx;
-		background: #191a1f;
-		box-shadow: 0px 0px 20rpx 0px rgba(50, 50, 52, 0.06);
-		border-radius: 28rpx;
-		margin: 20rpx auto;
-		padding: 0 25rpx;
-
-		.left-img {
-			width: 40rpx;
-			height: 40rpx;
-		}
-
-		view {
-			padding-left: 20rpx;
-			flex-grow: 1;
-			font-size: 29rpx;
-			font-weight: bold;
-			color: #5D5D5D;
-		}
-
-		.right-img {
-			width: 13rpx;
-			height: 23rpx;
-		}
-	}
-
-	.sqdl {
-		display: block;
-		width: 689rpx;
-		margin: 20rpx auto 20rpx;
-	}
-</style>

+ 1645 - 0
plugin/vue-i18n/CHANGELOG.md

@@ -0,0 +1,1645 @@
+
+## v8.21.0 (2020-08-13)
+
+#### :star: New Features
+* [#972](https://github.com/kazupon/vue-i18n/pull/972) feat: message function ([@kazupon](https://github.com/kazupon))
+
+#### :pencil: Documentation
+* [#961](https://github.com/kazupon/vue-i18n/pull/961) Update link to Formatter Interface ([@JohJohan](https://github.com/JohJohan))
+
+#### Committers: 3
+- Alexander Sokolov ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
+- Johan ([@JohJohan](https://github.com/JohJohan))
+- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
+
+
+## v8.20.0 (2020-07-30)
+
+#### :star: New Features
+* [#959](https://github.com/kazupon/vue-i18n/pull/959) i18n-n component local components passing ([@kazupon](https://github.com/kazupon))
+* [#928](https://github.com/kazupon/vue-i18n/pull/928) :zap: improvement(interpolation): enable passage of local components to tag prop ([@vhoyer](https://github.com/vhoyer))
+
+#### Committers: 2
+- Vinícius Hoyer ([@vhoyer](https://github.com/vhoyer))
+- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
+
+
+## v8.19.0 (2020-07-25)
+
+#### :star: New Features
+* [#942](https://github.com/kazupon/vue-i18n/pull/942) Add vetur support for tags and attributes ([@phiter](https://github.com/phiter))
+
+#### :pencil: Documentation
+* [#925](https://github.com/kazupon/vue-i18n/pull/925) Added missing quote ([@fschlag](https://github.com/fschlag))
+* [#921](https://github.com/kazupon/vue-i18n/pull/921) Add lost pluralizationRules option to documentation ([@AleksandrSl](https://github.com/AleksandrSl))
+* [#920](https://github.com/kazupon/vue-i18n/pull/920) Make link to API and Guide top level ([@AleksandrSl](https://github.com/AleksandrSl))
+
+#### Committers: 3
+- Aleksandr ([@AleksandrSl](https://github.com/AleksandrSl))
+- Florian Schlag ([@fschlag](https://github.com/fschlag))
+- Phiter Fernandes ([@phiter](https://github.com/phiter))
+
+
+## v8.18.2 (2020-06-08)
+
+#### :zap: Improved Features
+* [#917](https://github.com/kazupon/vue-i18n/pull/917) fix: improve IVueI18n interface ([@kazupon](https://github.com/kazupon))
+
+#### :pencil: Documentation
+* [#902](https://github.com/kazupon/vue-i18n/pull/902) docs: [RU] Translation update ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
+* [#901](https://github.com/kazupon/vue-i18n/pull/901) docs: (zh) inverse $d $n ([@stan-chen](https://github.com/stan-chen))
+
+#### Committers: 4
+- Alexander Sokolov ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
+- Rafał Chłodnicki ([@rchl](https://github.com/rchl))
+- Stanley Chen ([@stan-chen](https://github.com/stan-chen))
+- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
+
+
+## v8.18.1 (2020-05-27)
+
+#### :bug: Bug Fixes
+* [#896](https://github.com/kazupon/vue-i18n/pull/896) Fix flow types and enable flow types testing on CI ([@rchl](https://github.com/rchl))
+
+#### Committers: 1
+- Rafał Chłodnicki ([@rchl](https://github.com/rchl))
+
+
+## v8.18.0 (2020-05-26)
+
+#### :star: New Features
+* [#892](https://github.com/kazupon/vue-i18n/pull/892) Add onComponentInstanceCreated constructor option ([@rchl](https://github.com/rchl))
+
+#### :zap: Improved Features
+* [#890](https://github.com/kazupon/vue-i18n/pull/890) chore: set up linting for typescript definitions ([@rchl](https://github.com/rchl))
+
+#### Committers: 1
+- Rafał Chłodnicki ([@rchl](https://github.com/rchl))
+
+
+## v8.17.7 (2020-05-19)
+
+#### :bug: Bug Fixes
+* [#882](https://github.com/kazupon/vue-i18n/pull/882) fix v-t pluralisation when choice is 0 ([@mikejacoutot](https://github.com/mikejacoutot))
+
+#### Committers: 1
+- [@mikejacoutot](https://github.com/mikejacoutot)
+
+
+## v8.17.6 (2020-05-15)
+
+#### :bug: Bug Fixes
+* [#880](https://github.com/kazupon/vue-i18n/pull/880) Don't delete _i18n in beforeDestroy ([@danimoh](https://github.com/danimoh))
+
+#### :zap: Improved Features
+* [#878](https://github.com/kazupon/vue-i18n/pull/878) Allow component interpolation without root element ([@danimoh](https://github.com/danimoh))
+
+#### :pencil: Documentation
+* [#875](https://github.com/kazupon/vue-i18n/pull/875) Add new 3rd party tool ([@danigayosog](https://github.com/danigayosog))
+* [#872](https://github.com/kazupon/vue-i18n/pull/872) docs: fixes ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
+* [#871](https://github.com/kazupon/vue-i18n/pull/871) update pluralization.md ([@Timibadass](https://github.com/Timibadass))
+
+#### Committers: 4
+- Alexander Sokolov ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
+- Daniel ([@danigayosog](https://github.com/danigayosog))
+- Timi Omoyeni ([@Timibadass](https://github.com/Timibadass))
+- [@danimoh](https://github.com/danimoh)
+
+
+## v8.17.5 (2020-05-10)
+
+#### :bug: Bug Fixes
+* [#869](https://github.com/kazupon/vue-i18n/pull/869) fix: not string method access error ([@kazupon](https://github.com/kazupon))
+
+#### :pencil: Documentation
+* [#867](https://github.com/kazupon/vue-i18n/pull/867) docs: [RU] Translation ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
+* [#865](https://github.com/kazupon/vue-i18n/pull/865) improvement(docs): extend Hot reloading section ([@caugner](https://github.com/caugner))
+
+#### Committers: 3
+- Alexander Sokolov ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
+- Claas Augner ([@caugner](https://github.com/caugner))
+- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
+
+
+## v8.17.4 (2020-04-26)
+
+#### :bug: Bug Fixes
+* [#859](https://github.com/kazupon/vue-i18n/pull/859) fix datetime format cache ([@kazupon](https://github.com/kazupon))
+* [#858](https://github.com/kazupon/vue-i18n/pull/858) fix datetime and number format fallbacking ([@kazupon](https://github.com/kazupon))
+* [#857](https://github.com/kazupon/vue-i18n/pull/857) fix: alternative array includes ([@kazupon](https://github.com/kazupon))
+
+#### Committers: 1
+- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
+
+
+## v8.17.3 (2020-04-19)
+
+#### :zap: Improved Features
+* [#846](https://github.com/kazupon/vue-i18n/pull/846) add key to postTranslation ([@dmitryuk](https://github.com/dmitryuk))
+
+#### :pencil: Documentation
+* [#847](https://github.com/kazupon/vue-i18n/pull/847) docs: Update /api/README.md ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
+
+#### Committers: 2
+- Alexander Dmitryuk ([@dmitryuk](https://github.com/dmitryuk))
+- Alexander Sokolov ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
+
+
+## v8.17.2 (2020-04-18)
+
+#### :zap: Improved Features
+* [#844](https://github.com/kazupon/vue-i18n/pull/844) Use plain object instead of Map, which is not supported in IE9/10 ([@exoego](https://github.com/exoego))
+
+#### Committers: 1
+- TATSUNO Yasuhiro ([@exoego](https://github.com/exoego))
+
+
+## v8.17.1 (2020-04-16)
+
+#### :bug: Bug Fixes
+* [#840](https://github.com/kazupon/vue-i18n/pull/840) fix: altnative endsWidth ([@kazupon](https://github.com/kazupon))
+
+#### :pencil: Documentation
+* [#837](https://github.com/kazupon/vue-i18n/pull/837) Fix typo ([@ninofiliu](https://github.com/ninofiliu))
+
+#### Committers: 2
+- Nino Filiu ([@ninofiliu](https://github.com/ninofiliu))
+- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
+
+
+## v8.17.0 (2020-04-11)
+
+#### :star: New Features
+* [#829](https://github.com/kazupon/vue-i18n/pull/829) #138 Fallback Locale as array for cascading fallbacks ([@mmokross](https://github.com/mmokross))
+
+#### :pencil: Documentation
+* [#834](https://github.com/kazupon/vue-i18n/pull/834) Add capitalize default modifier in doc ([@alexandreDavid](https://github.com/alexandreDavid))
+* [#832](https://github.com/kazupon/vue-i18n/pull/832) fix in examples of "Custom pluralization" ([@Perlover](https://github.com/Perlover))
+
+#### Committers: 4
+- Alexandre David ([@alexandreDavid](https://github.com/alexandreDavid))
+- Kobayashi Kazuhiro ([@kzhrk](https://github.com/kzhrk))
+- Michael Mokroß ([@mmokross](https://github.com/mmokross))
+- Perlover ([@Perlover](https://github.com/Perlover))
+
+
+## v8.16.0 (2020-03-27)
+
+#### :star: New Features
+* [#822](https://github.com/kazupon/vue-i18n/pull/822) post translation hooking feature ([@kazupon](https://github.com/kazupon))
+
+#### Committers: 1
+- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
+
+
+## v8.15.7 (2020-03-25)
+
+#### :bug: Bug Fixes
+* [#819](https://github.com/kazupon/vue-i18n/pull/819) Fixed bug when changing number format runtime ([@slischka](https://github.com/slischka))
+
+#### Committers: 1
+- Jiří Slischka ([@slischka](https://github.com/slischka))
+
+
+## v8.15.6 (2020-03-23)
+
+#### :bug: Bug Fixes
+* [#817](https://github.com/kazupon/vue-i18n/pull/817) Bugfix : 'setLocaleMessage' / 'mergeLocaleMessage' doesn't work if 'warnHtmlInMessage' is set to 'error'  ([@aym3nb](https://github.com/aym3nb))
+
+#### :pencil: Documentation
+* [#816](https://github.com/kazupon/vue-i18n/pull/816) Update fallback.md ([@scoutrul](https://github.com/scoutrul))
+
+#### Committers: 3
+- Anton ([@scoutrul](https://github.com/scoutrul))
+- Aymen Bareche ([@aym3nb](https://github.com/aym3nb))
+- TATSUNO Yasuhiro ([@exoego](https://github.com/exoego))
+
+
+## v8.15.5 (2020-03-07)
+
+#### :star: Features
+* [#787](https://github.com/kazupon/vue-i18n/pull/787) Add a 'capitalize' default modifier for linked message ([@charlesmass](https://github.com/charlesmass))
+
+#### :zap: Improvement Features
+* [#794](https://github.com/kazupon/vue-i18n/pull/794) Support returning 'string' type for customized interpolation ([@sihyeonn](https://github.com/sihyeonn))
+
+#### :pencil: Documentation
+* [#791](https://github.com/kazupon/vue-i18n/pull/791) Revise fallback.md ([@jlebar](https://github.com/jlebar))
+
+#### Committers: 4
+- Justin Lebar ([@jlebar](https://github.com/jlebar))
+- L M ([@charlesmass](https://github.com/charlesmass))
+- Sihyeon Jang ([@sihyeonn](https://github.com/sihyeonn))
+- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
+
+<a name="8.15.4"></a>
+## [8.15.4](https://github.com/kazupon/vue-i18n/compare/v8.15.3...v8.15.4) (2020-02-25)
+
+
+### :bug: Bug Fixes
+
+* **index:** improve formatFallbackMessages code (#779) (#783) by [@masongzhi](https://github.com/masongzhi) ([53895b9](https://github.com/kazupon/vue-i18n/commit/53895b9)))
+
+### :up: Updates
+
+* some fixes ([8a9a950](https://github.com/kazupon/vue-i18n/commit/8a9a950))
+
+
+
+<a name="8.15.3"></a>
+## [8.15.3](https://github.com/kazupon/vue-i18n/compare/v8.15.2...v8.15.3) (2019-12-18)
+
+
+### :zap: Improvements
+
+* **index:** fix mergeLocaleMessage. add changes notification on merging with an empty target object ([#752](https://github.com/kazupon/vue-i18n/issues/752)) by [@jekill](https://github.com/jekill) ([048eac5](https://github.com/kazupon/vue-i18n/commit/048eac5)), closes [#752](https://github.com/kazupon/vue-i18n/issues/752)
+
+
+
+<a name="8.15.2"></a>
+## [8.15.2](https://github.com/kazupon/vue-i18n/compare/v8.15.1...v8.15.2) (2019-12-18)
+
+
+### :bug: Bug Fixes
+
+* **index:** Fix exception when using unit number formatting by [@simonjodet](https://github.com/simonjodet) ([194b801](https://github.com/kazupon/vue-i18n/commit/194b801)), closes [#750](https://github.com/kazupon/vue-i18n/issues/750) [#751](https://github.com/kazupon/vue-i18n/issues/751)
+
+
+
+<a name="8.15.1"></a>
+## [8.15.1](https://github.com/kazupon/vue-i18n/compare/v8.15.0...v8.15.1) (2019-11-27)
+
+
+### :zap: Improvements
+
+* **mixin:** change to custom blocks parse error ([a9858be](https://github.com/kazupon/vue-i18n/commit/a9858be))
+
+
+
+<a name="8.15.0"></a>
+# [8.15.0](https://github.com/kazupon/vue-i18n/compare/v8.14.1...v8.15.0) (2019-10-16)
+
+
+### :star: New Features
+
+* Add constructor option for custom modifiers ([#724](https://github.com/kazupon/vue-i18n/issues/724)) by [@epaezrubio](https://github.com/epaezrubio) ([3217212](https://github.com/kazupon/vue-i18n/commit/3217212)), closes [#724](https://github.com/kazupon/vue-i18n/issues/724)
+
+
+
+<a name="8.14.1"></a>
+## [8.14.1](https://github.com/kazupon/vue-i18n/compare/v8.14.0...v8.14.1) (2019-09-12)
+
+
+### :bug: Bug Fixes
+
+* **path:** fix branket key error ([8d2aba7](https://github.com/kazupon/vue-i18n/commit/8d2aba7))
+* **component:** Fix interpolation component when there are empty text nodes ([547cdd1](https://github.com/kazupon/vue-i18n/commit/547cdd1)) by [@Demivan](https://github.com/Demivan)
+
+
+
+<a name="8.14.0"></a>
+# [8.14.0](https://github.com/kazupon/vue-i18n/compare/v8.13.0...v8.14.0) (2019-08-12)
+
+
+### :star: New Features
+
+* fallback formatting ([#637](https://github.com/kazupon/vue-i18n/issues/637)) by [@sebwas](https://github.com/sebwas) ([bf9929c](https://github.com/kazupon/vue-i18n/commit/bf9929c)), closes [#637](https://github.com/kazupon/vue-i18n/issues/637)
+* support slots syntax for component interpolation ([#685](https://github.com/kazupon/vue-i18n/issues/685)) by [@aavondet](https://github.com/aavondet) ([71ca843](https://github.com/kazupon/vue-i18n/commit/71ca843)), closes [#685](https://github.com/kazupon/vue-i18n/issues/685)
+
+
+
+<a name="8.13.0"></a>
+# [8.13.0](https://github.com/kazupon/vue-i18n/compare/v8.12.0...v8.13.0) (2019-08-09)
+
+
+### :star: New Features
+
+* datetime/number formats fallback warning filter ([46de19e](https://github.com/kazupon/vue-i18n/commit/46de19e)), closes [#558](https://github.com/kazupon/vue-i18n/issues/558)
+* fallback translation warning filter ([69fc798](https://github.com/kazupon/vue-i18n/commit/69fc798))
+* translation missing warning filter ([666dc9d](https://github.com/kazupon/vue-i18n/commit/666dc9d))
+
+
+
+<a name="8.12.0"></a>
+# [8.12.0](https://github.com/kazupon/vue-i18n/compare/v8.11.2...v8.12.0) (2019-07-09)
+
+
+### :star: New Features
+
+* **mixin:** shared locale messages feature ([82543de](https://github.com/kazupon/vue-i18n/commit/82543de))
+
+
+### :zap: Improvements
+
+* **typing:** sharedMessages option type ([6967a15](https://github.com/kazupon/vue-i18n/commit/6967a15))
+
+
+
+<a name="8.11.2"></a>
+## [8.11.2](https://github.com/kazupon/vue-i18n/compare/v8.11.1...v8.11.2) (2019-04-30)
+
+
+### :bug: Bug Fixes
+
+* bug(mixin): fix SSR memory leak by moving subscribeDataChanging calls into beforeMount ([#572](https://github.com/kazupon/vue-i18n/issues/572)) by [@Pindar](https://github.com/Pindar) ([32b5795](https://github.com/kazupon/vue-i18n/commit/32b5795)), closes [#572](https://github.com/kazupon/vue-i18n/issues/572)
+
+
+
+<a name="8.11.1"></a>
+## [8.11.1](https://github.com/kazupon/vue-i18n/compare/v8.11.0...v8.11.1) (2019-04-26)
+
+
+### :bug: Bug Fixes
+
+* fix ES Modules distribution ([bb631a1](https://github.com/kazupon/vue-i18n/commit/bb631a1))
+
+
+
+<a name="8.11.0"></a>
+# [8.11.0](https://github.com/kazupon/vue-i18n/compare/v8.10.0...v8.11.0) (2019-04-26)
+
+
+### :star: New Features
+
+* ES modules for browser ([#561](https://github.com/kazupon/vue-i18n/issues/561)) ([c9b9adf](https://github.com/kazupon/vue-i18n/commit/c9b9adf)), closes [#561](https://github.com/kazupon/vue-i18n/issues/561)
+* HTML locale message warning option ([#567](https://github.com/kazupon/vue-i18n/issues/567)) ([4aecf03](https://github.com/kazupon/vue-i18n/commit/4aecf03)), closes [#567](https://github.com/kazupon/vue-i18n/issues/567)
+
+
+
+<a name="8.10.0"></a>
+# [8.10.0](https://github.com/kazupon/vue-i18n/compare/v8.9.0...v8.10.0) (2019-03-28)
+
+
+### :star: New Features
+
+* **number:** i18n-n functional component ([#541](https://github.com/kazupon/vue-i18n/issues/541)) by [@bponomarenko](https://github.com/bponomarenko) ([b33579d](https://github.com/kazupon/vue-i18n/commit/b33579d)), closes [#541](https://github.com/kazupon/vue-i18n/issues/541)
+* **path:** Keypath should parse if sub path contains spaces. ([#533](https://github.com/kazupon/vue-i18n/issues/533)) by [@exoego](https://github.com/exoego) ([640daaf](https://github.com/kazupon/vue-i18n/commit/640daaf)), closes [#533](https://github.com/kazupon/vue-i18n/issues/533)
+
+
+### :zap: Improvements
+
+* **number:** support data fall through in i18n-n ([#545](https://github.com/kazupon/vue-i18n/issues/545)) ([71cadbf](https://github.com/kazupon/vue-i18n/commit/71cadbf)), closes [#545](https://github.com/kazupon/vue-i18n/issues/545)
+
+
+### :pencil: docs
+
+* **vuepress:** translate documents for chinese ([#536](https://github.com/kazupon/vue-i18n/issues/536)) by [@xuhongbo](https://github.com/xuhongbo) ([ccf29f8](https://github.com/kazupon/vue-i18n/commit/ccf29f8)), closes [#536](https://github.com/kazupon/vue-i18n/issues/536) [#531](https://github.com/kazupon/vue-i18n/issues/531) [#1](https://github.com/kazupon/vue-i18n/issues/1) [#533](https://github.com/kazupon/vue-i18n/issues/533) [#540](https://github.com/kazupon/vue-i18n/issues/540) [#541](https://github.com/kazupon/vue-i18n/issues/541) [#1](https://github.com/kazupon/vue-i18n/issues/1) [#2](https://github.com/kazupon/vue-i18n/issues/2)
+
+
+<a name="8.9.0"></a>
+# [8.9.0](https://github.com/kazupon/vue-i18n/compare/v8.8.2...v8.9.0) (2019-03-08)
+
+
+### :bug: Bug Fixes
+
+* **index:** Fix [#515](https://github.com/kazupon/vue-i18n/issues/515) empty string not returning true ([#525](https://github.com/kazupon/vue-i18n/issues/525)) by [@kimuraz](https://github.com/kimuraz) ([396c5ca](https://github.com/kazupon/vue-i18n/commit/396c5ca)), closes [#515](https://github.com/kazupon/vue-i18n/issues/515) [#525](https://github.com/kazupon/vue-i18n/issues/525) [#515](https://github.com/kazupon/vue-i18n/issues/515)
+
+
+### :star: New Features
+
+* **index:** add availableLocales (related issue [#193](https://github.com/kazupon/vue-i18n/issues/193), PR [#528](https://github.com/kazupon/vue-i18n/issues/528)) by [@exoego](https://github.com/exoego) ([8f75b1f](https://github.com/kazupon/vue-i18n/commit/8f75b1f)), closes [#193](https://github.com/kazupon/vue-i18n/issues/193) [#528](https://github.com/kazupon/vue-i18n/issues/528) [#193](https://github.com/kazupon/vue-i18n/issues/193) [#193](https://github.com/kazupon/vue-i18n/issues/193) [#193](https://github.com/kazupon/vue-i18n/issues/193) [#193](https://github.com/kazupon/vue-i18n/issues/193)
+
+
+### :zap: Improvements
+
+* **flowtype:** Fix missing type declarations in flow type ([#529](https://github.com/kazupon/vue-i18n/issues/529)) by [@exoego](https://github.com/exoego) ([4173764](https://github.com/kazupon/vue-i18n/commit/4173764)), closes [#529](https://github.com/kazupon/vue-i18n/issues/529)
+
+
+
+<a name="8.8.2"></a>
+## [8.8.2](https://github.com/kazupon/vue-i18n/compare/v8.8.1...v8.8.2) (2019-02-17)
+
+
+### :bug: Bug Fixes
+
+* **mixin:** fix memory leak ([135058d](https://github.com/kazupon/vue-i18n/commit/135058d)), closes [#514](https://github.com/kazupon/vue-i18n/issues/514)
+
+
+
+<a name="8.8.1"></a>
+## [8.8.1](https://github.com/kazupon/vue-i18n/compare/v8.8.0...v8.8.1) (2019-02-10)
+
+
+### :bug: Bug Fixes
+
+* **index:** fixed [#478](https://github.com/kazupon/vue-i18n/issues/478) ([#518](https://github.com/kazupon/vue-i18n/issues/518)) by [@stroncium](https://github.com/stroncium) ([469edd9](https://github.com/kazupon/vue-i18n/commit/469edd9)), closes [#478](https://github.com/kazupon/vue-i18n/issues/478) [#518](https://github.com/kazupon/vue-i18n/issues/518) [#478](https://github.com/kazupon/vue-i18n/issues/478)
+
+
+### :zap: Improvements
+
+* **flowtype:** update typings ([44e04e7](https://github.com/kazupon/vue-i18n/commit/44e04e7))
+* **typescript:** update typings ([dee35b9](https://github.com/kazupon/vue-i18n/commit/dee35b9))
+
+
+
+<a name="8.8.0"></a>
+# [8.8.0](https://github.com/kazupon/vue-i18n/compare/v8.7.0...v8.8.0) (2019-01-29)
+
+
+### :bug: Bug Fixes
+
+* **index:** fix flat path based key issue ([bed9c39](https://github.com/kazupon/vue-i18n/commit/bed9c39)), closes [#349](https://github.com/kazupon/vue-i18n/issues/349)
+* **mixin:** fix beforeDestroy can not find this.$t ([#500](https://github.com/kazupon/vue-i18n/issues/500)) by [@masongzhi](https://github.com/masongzhi) ([311b8f3](https://github.com/kazupon/vue-i18n/commit/311b8f3)), closes [#500](https://github.com/kazupon/vue-i18n/issues/500)
+
+
+### :zap: Improvements
+
+* **directive:** Fix typo on warning message ([#509](https://github.com/kazupon/vue-i18n/issues/509)) by [@kimuraz](https://github.com/kimuraz) ([e879024](https://github.com/kazupon/vue-i18n/commit/e879024)), closes [#509](https://github.com/kazupon/vue-i18n/issues/509)
+* **index:** silence fallback warnings ([#510](https://github.com/kazupon/vue-i18n/issues/510)) by [@SzNagyMisu](https://github.com/SzNagyMisu) ([ddc0c79](https://github.com/kazupon/vue-i18n/commit/ddc0c79)), closes [#510](https://github.com/kazupon/vue-i18n/issues/510) [#139](https://github.com/kazupon/vue-i18n/issues/139)
+
+
+
+<a name="8.7.0"></a>
+# [8.7.0](https://github.com/kazupon/vue-i18n/compare/v8.6.0...v8.7.0) (2019-01-02)
+
+
+### :zap: Improvements
+
+* **directive:** Preserve directive content ([#495](https://github.com/kazupon/vue-i18n/issues/495)) by [@bponomarenko](https://github.com/bponomarenko) ([c29edba](https://github.com/kazupon/vue-i18n/commit/c29edba)), closes [#495](https://github.com/kazupon/vue-i18n/issues/495) [#408](https://github.com/kazupon/vue-i18n/issues/408) [#408](https://github.com/kazupon/vue-i18n/issues/408)
+
+
+
+<a name="8.6.0"></a>
+# [8.6.0](https://github.com/kazupon/vue-i18n/compare/v8.5.0...v8.6.0) (2018-12-25)
+
+
+### :bug: Bug Fixes
+
+* **pluralization:** inherit pluralization rules ⚠ ([#493](https://github.com/kazupon/vue-i18n/issues/493)) by [@Raiondesu](https://github.com/Raiondesu) ([7a23f32](https://github.com/kazupon/vue-i18n/commit/7a23f32)), closes [#493](https://github.com/kazupon/vue-i18n/issues/493)
+
+
+### :zap: Improvements
+
+* **format:** Add the path as argument to the custom formatter ([#489](https://github.com/kazupon/vue-i18n/issues/489)) by [@Raiondesu](https://github.com/Raiondesu) ([b9437ea](https://github.com/kazupon/vue-i18n/commit/b9437ea)), closes [#489](https://github.com/kazupon/vue-i18n/issues/489) [#484](https://github.com/kazupon/vue-i18n/issues/484) [#484](https://github.com/kazupon/vue-i18n/issues/484)
+
+
+
+<a name="8.5.0"></a>
+# [8.5.0](https://github.com/kazupon/vue-i18n/compare/v8.4.0...v8.5.0) (2018-12-17)
+
+
+### :bug: Bug Fixes
+
+* **index:** evaluate availabilities lazily (fix [#477](https://github.com/kazupon/vue-i18n/issues/477)) ([#483](https://github.com/kazupon/vue-i18n/issues/483)) by [@gamtiq](https://github.com/gamtiq) ([b66f02e](https://github.com/kazupon/vue-i18n/commit/b66f02e)), closes [#477](https://github.com/kazupon/vue-i18n/issues/477) [#483](https://github.com/kazupon/vue-i18n/issues/483)
+
+
+### :zap: Improvements
+
+* **index:** Allow pluralization customization via constructor options (closes [#464](https://github.com/kazupon/vue-i18n/issues/464)) ([#482](https://github.com/kazupon/vue-i18n/issues/482)) by [@Raiondesu](https://github.com/Raiondesu) ([ef4b1a6](https://github.com/kazupon/vue-i18n/commit/ef4b1a6)), closes [#464](https://github.com/kazupon/vue-i18n/issues/464) [#482](https://github.com/kazupon/vue-i18n/issues/482) [#464](https://github.com/kazupon/vue-i18n/issues/464) [#464](https://github.com/kazupon/vue-i18n/issues/464) [#464](https://github.com/kazupon/vue-i18n/issues/464) [#464](https://github.com/kazupon/vue-i18n/issues/464) [#451](https://github.com/kazupon/vue-i18n/issues/451)
+* **index:** make silentTranslationWarn work for dates and numbers too ([#481](https://github.com/kazupon/vue-i18n/issues/481)) by [@Raiondesu](https://github.com/Raiondesu) ([402092b](https://github.com/kazupon/vue-i18n/commit/402092b)), closes [#481](https://github.com/kazupon/vue-i18n/issues/481)
+* **types:** typed autocomplete in date and number format options ([#485](https://github.com/kazupon/vue-i18n/issues/485)) by [@Raiondesu](https://github.com/Raiondesu) ([e2e5993](https://github.com/kazupon/vue-i18n/commit/e2e5993)), closes [#485](https://github.com/kazupon/vue-i18n/issues/485)
+
+
+
+<a name="8.4.0"></a>
+# [8.4.0](https://github.com/kazupon/vue-i18n/compare/v8.3.2...v8.4.0) (2018-11-30)
+
+
+### :star: New Features
+
+* **index:** Add linked message formatting ([#467](https://github.com/kazupon/vue-i18n/issues/467)) by [@exoego](https://github.com/exoego) ([776b81b](https://github.com/kazupon/vue-i18n/commit/776b81b)), closes [#467](https://github.com/kazupon/vue-i18n/issues/467)
+
+
+
+<a name="8.3.2"></a>
+## [8.3.2](https://github.com/kazupon/vue-i18n/compare/v8.3.1...v8.3.2) (2018-11-16)
+
+
+### :chart_with_upwards_trend: Performance Fixes
+
+* **index:** Optimize unnecessary capturing. ([#462](https://github.com/kazupon/vue-i18n/issues/462)) by [@exoego](https://github.com/exoego) ([116845e](https://github.com/kazupon/vue-i18n/commit/116845e)), closes [#462](https://github.com/kazupon/vue-i18n/issues/462)
+
+
+
+<a name="8.3.1"></a>
+## [8.3.1](https://github.com/kazupon/vue-i18n/compare/v8.3.0...v8.3.1) (2018-11-08)
+
+
+### :bug: Bug Fixes
+
+* **directive:** fix cannnot update with v-t when had been changed locale message ([4895a2e](https://github.com/kazupon/vue-i18n/commit/4895a2e)), closes [#450](https://github.com/kazupon/vue-i18n/issues/450)
+* **index:** fix merge bug ([1798490](https://github.com/kazupon/vue-i18n/commit/1798490)), closes [#458](https://github.com/kazupon/vue-i18n/issues/458)
+* **missing:** fix vm argument passing ([dc48099](https://github.com/kazupon/vue-i18n/commit/dc48099)), closes [#453](https://github.com/kazupon/vue-i18n/issues/453)
+
+
+### :zap: Improvements
+
+* Optimize path.js and format.js ([#456](https://github.com/kazupon/vue-i18n/issues/456)) by [@exoego](https://github.com/exoego) ([639453c](https://github.com/kazupon/vue-i18n/commit/639453c)), closes [#456](https://github.com/kazupon/vue-i18n/issues/456)
+
+
+
+<a name="8.3.0"></a>
+# [8.3.0](https://github.com/kazupon/vue-i18n/compare/v8.2.1...v8.3.0) (2018-10-29)
+
+
+### :zap: Improvements
+
+* **pluralization:** Extendable pluralization by [@Raiondesu](https://github.com/Raiondesu) ([bbab90b](https://github.com/kazupon/vue-i18n/commit/bbab90b))
+
+
+
+<a name="8.2.1"></a>
+## [8.2.1](https://github.com/kazupon/vue-i18n/compare/v8.2.0...v8.2.1) (2018-10-15)
+
+
+### :bug: Bug Fixes
+
+* **extend:** fix TypeError: Cannot redefine property: $i18n ([#422](https://github.com/kazupon/vue-i18n/issues/422)) by [@HadiChen](https://github.com/HadiChen) ([cb19082](https://github.com/kazupon/vue-i18n/commit/cb19082)), closes [#422](https://github.com/kazupon/vue-i18n/issues/422)
+
+
+### :zap: Improvements
+
+* **index:** Suppress some warnings in production: smaller min.js and performance gain. ([#441](https://github.com/kazupon/vue-i18n/issues/441)) by @	exoego ([43931f5](https://github.com/kazupon/vue-i18n/commit/43931f5)), closes [#441](https://github.com/kazupon/vue-i18n/issues/441)
+
+
+
+<a name="8.2.0"></a>
+# [8.2.0](https://github.com/kazupon/vue-i18n/compare/v8.1.1...v8.2.0) (2018-10-13)
+
+
+### :bug: Bug Fixes
+
+* **index:** Add warning for circular reference in linked message ([#438](https://github.com/kazupon/vue-i18n/issues/438)) by [@exoego](https://github.com/exoego) ([7583485](https://github.com/kazupon/vue-i18n/commit/7583485)), closes [#438](https://github.com/kazupon/vue-i18n/issues/438)
+
+
+### :zap: Improvements
+
+* **index:** Allow escaping link key like @:(foo.bar). ([#437](https://github.com/kazupon/vue-i18n/issues/437)) by [@exoego](https://github.com/exoego) ([acfc458](https://github.com/kazupon/vue-i18n/commit/acfc458)), closes [#437](https://github.com/kazupon/vue-i18n/issues/437)
+* **index:** Pre-defined named arguments for Pluraization ([#440](https://github.com/kazupon/vue-i18n/issues/440)) by [@exoego](https://github.com/exoego) ([e84f0fb](https://github.com/kazupon/vue-i18n/commit/e84f0fb)), closes [#440](https://github.com/kazupon/vue-i18n/issues/440)
+* **path:** Allow non-ascii chars including numbers. ([#436](https://github.com/kazupon/vue-i18n/issues/436)) by [@exoego](https://github.com/exoego) ([a556c58](https://github.com/kazupon/vue-i18n/commit/a556c58)), closes [#436](https://github.com/kazupon/vue-i18n/issues/436)
+
+
+
+<a name="8.1.1"></a>
+## [8.1.1](https://github.com/kazupon/vue-i18n/compare/v8.1.0...v8.1.1) (2018-10-12)
+
+
+### :bug: Bug Fixes
+
+* **build:** fix rollup building issues ([1a1958a](https://github.com/kazupon/vue-i18n/commit/1a1958a))
+* **format:** Should warn as unknown if named format is not closed. ([#435](https://github.com/kazupon/vue-i18n/issues/435)) by [@exoego](https://github.com/exoego) ([d1f6ed0](https://github.com/kazupon/vue-i18n/commit/d1f6ed0)), closes [#435](https://github.com/kazupon/vue-i18n/issues/435)
+* **install:** fix cannot redfine error ([6d5ec61](https://github.com/kazupon/vue-i18n/commit/6d5ec61))
+
+
+### :zap: Improvements
+
+* **package.json:** tree shaking optimization ([38948c5](https://github.com/kazupon/vue-i18n/commit/38948c5))
+
+
+
+<a name="8.1.0"></a>
+# [8.1.0](https://github.com/kazupon/vue-i18n/compare/v8.0.0...v8.1.0) (2018-09-03)
+
+
+### :bug: Bug Fixes
+
+* **install:** add support for Vue.extend vue-i18n instance ([#420](https://github.com/kazupon/vue-i18n/issues/420)) by [@jaredzhu1993](https://github.com/jaredzhu1993) ([a60ea8b](https://github.com/kazupon/vue-i18n/commit/a60ea8b)), closes [#420](https://github.com/kazupon/vue-i18n/issues/420)
+
+
+### :zap: Improvements
+
+* **warnings:** make warning messages clearer ([#396](https://github.com/kazupon/vue-i18n/issues/396)) by [@kimuraz](https://github.com/kimuraz) ([79eee1b](https://github.com/kazupon/vue-i18n/commit/79eee1b)), closes [#396](https://github.com/kazupon/vue-i18n/issues/396)
+
+
+
+<a name="8.0.0"></a>
+# [8.0.0](https://github.com/kazupon/vue-i18n/compare/v7.8.1...v8.0.0) (2018-06-23)
+
+
+### :boom: Breaking changes
+
+* **extend:** fix this context binding ([aa0e831](https://github.com/kazupon/vue-i18n/commit/aa0e831)), closes [#306](https://github.com/kazupon/vue-i18n/issues/306) [#286](https://github.com/kazupon/vue-i18n/issues/286) [#259](https://github.com/kazupon/vue-i18n/issues/259), revert [#260](https://github.com/kazupon/vue-i18n/issues/260)
+
+Note that you need to guarantee this context equal to component instance in lifecycle methods (e.g. in `data` options, `const $t = this.$t.bind(this)`).
+
+```js
+export default {
+  data () {
+    const $t = this.$t.bind(this)
+    return { msg: $t('msg') }
+  }
+}
+```
+
+see the [API docs](https://kazupon.github.io/vue-i18n/api/)
+
+### :bug: Bug Fixes
+
+* bug(directive): fix guard checking at unbind ([c74888c](https://github.com/kazupon/vue-i18n/commit/c74888c)), closes [#340](https://github.com/kazupon/vue-i18n/issues/340)
+
+
+### NOTE
+
+* extend:
+
+
+
+<a name="7.8.1"></a>
+## [7.8.1](https://github.com/kazupon/vue-i18n/compare/v7.8.0...v7.8.1) (2018-06-18)
+
+
+### :bug: Bug Fixes
+
+* **directive:** fix cannot unbind bug ([105888d](https://github.com/kazupon/vue-i18n/commit/105888d)), closes [#377](https://github.com/kazupon/vue-i18n/issues/377)
+
+
+
+<a name="7.8.0"></a>
+# [7.8.0](https://github.com/kazupon/vue-i18n/compare/v7.7.0...v7.8.0) (2018-06-01)
+
+
+### :zap: Improvements
+
+* **typescript:** add type exportings ([a7cb8da](https://github.com/kazupon/vue-i18n/commit/a7cb8da))
+
+
+
+<a name="7.7.0"></a>
+# [7.7.0](https://github.com/kazupon/vue-i18n/compare/v7.6.0...v7.7.0) (2018-05-20)
+
+
+### :zap: Improvements
+
+* **index:** resource reactivity ([887a137](https://github.com/kazupon/vue-i18n/commit/887a137)), closes [#253](https://github.com/kazupon/vue-i18n/issues/253)
+* **typescript:** Fix typings in components ([#344](https://github.com/kazupon/vue-i18n/issues/344)) by [@Demivan](https://github.com/Demivan) ([2402893](https://github.com/kazupon/vue-i18n/commit/2402893)), closes [#344](https://github.com/kazupon/vue-i18n/issues/344)
+
+
+
+<a name="7.6.0"></a>
+# [7.6.0](https://github.com/kazupon/vue-i18n/compare/v7.5.0...v7.6.0) (2018-03-13)
+
+
+### :zap: Improvements
+
+* **index:** support retunable missing handler ([#256](https://github.com/kazupon/vue-i18n/issues/256)) by [@houd1ni](https://github.com/houd1ni) ([9fbe467](https://github.com/kazupon/vue-i18n/commit/9fbe467))
+* **typescript:** update TranslateResult type interface ([dffc678](https://github.com/kazupon/vue-i18n/commit/dffc678))
+
+
+
+<a name="7.5.0"></a>
+# [7.5.0](https://github.com/kazupon/vue-i18n/compare/v7.4.2...v7.5.0) (2018-03-11)
+
+
+### :star: New Features
+
+* **directive:** Add pluralization feature to directive ([#304](https://github.com/kazupon/vue-i18n/issues/304)) by [@SirLamer](https://github.com/SirLamer) ([8378859](https://github.com/kazupon/vue-i18n/commit/8378859))
+
+
+### :zap: Improvements
+
+* **flow:** update TranslateResult type interface ([59f4658](https://github.com/kazupon/vue-i18n/commit/59f4658))
+* **index:** support object localization ([#311](https://github.com/kazupon/vue-i18n/issues/311)) by [@manniL](https://github.com/manniL) ([99e5006](https://github.com/kazupon/vue-i18n/commit/99e5006))
+* **missing:** Add interpolation values to missing handler ([#308](https://github.com/kazupon/vue-i18n/issues/308)) by [@sebwas](https://github.com/sebwas) ([b912d8a](https://github.com/kazupon/vue-i18n/commit/b912d8a))
+* **numberformat:** Explicit number format options ([#305](https://github.com/kazupon/vue-i18n/issues/305)) by [@bponomarenko](https://github.com/bponomarenko) ([aa07450](https://github.com/kazupon/vue-i18n/commit/aa07450))
+
+
+
+<a name="7.4.2"></a>
+## [7.4.2](https://github.com/kazupon/vue-i18n/compare/v7.4.1...v7.4.2) (2018-02-01)
+
+
+### :zap: Improvements
+
+* **index:** Fixes global auto installation ([#291](https://github.com/kazupon/vue-i18n/issues/291)) by [@emileber](https://github.com/emileber) ([2f016ff](https://github.com/kazupon/vue-i18n/commit/2f016ff)), closes [#291](https://github.com/kazupon/vue-i18n/issues/291)
+
+
+
+<a name="7.4.1"></a>
+## [7.4.1](https://github.com/kazupon/vue-i18n/compare/v7.4.0...v7.4.1) (2018-01-25)
+
+
+### :bug: Bug Fixes
+
+* fix cannot react ([2a8ea1c](https://github.com/kazupon/vue-i18n/commit/2a8ea1c)), closes [#261](https://github.com/kazupon/vue-i18n/issues/261)
+
+
+### :zap: Improvements
+
+* **formatter:** interpolate messages without values ([#282](https://github.com/kazupon/vue-i18n/issues/282)) by [@cb8](https://github.com/cb8) ([b792ce2](https://github.com/kazupon/vue-i18n/commit/b792ce2))
+
+
+
+<a name="7.4.0"></a>
+# [7.4.0](https://github.com/kazupon/vue-i18n/compare/v7.3.4...v7.4.0) (2018-01-10)
+
+
+### :star: New Features
+
+* **typescript:** Allow module augmentation ([#273](https://github.com/kazupon/vue-i18n/issues/273)) by [@CKGrafico](https://github.com/CKGrafico) ([4371344](https://github.com/kazupon/vue-i18n/commit/4371344))
+
+
+
+<a name="7.3.4"></a>
+## [7.3.4](https://github.com/kazupon/vue-i18n/compare/v7.3.3...v7.3.4) (2018-01-07)
+
+
+### :bug: Bug Fixes
+
+* **formatter:** Inherit formatter ([#269](https://github.com/kazupon/vue-i18n/issues/269)) by [@podkot](https://github.com/podkot) ([26a33ad](https://github.com/kazupon/vue-i18n/commit/26a33ad))
+
+
+
+<a name="7.3.3"></a>
+## [7.3.3](https://github.com/kazupon/vue-i18n/compare/v7.3.2...v7.3.3) (2017-12-19)
+
+
+### :bug: Bug Fixes
+
+* **extend:** Fix this not found [#259](https://github.com/kazupon/vue-i18n/issues/259) ([#260](https://github.com/kazupon/vue-i18n/issues/260)) by [@lzxb](https://github.com/lzxb) ([c29007e](https://github.com/kazupon/vue-i18n/commit/c29007e)), closes [#259](https://github.com/kazupon/vue-i18n/issues/259) [#260](https://github.com/kazupon/vue-i18n/issues/260)
+* **types:** fix using old export ([#263](https://github.com/kazupon/vue-i18n/issues/263)) by [@jmigual](https://github.com/jmigual) ([b295fee](https://github.com/kazupon/vue-i18n/commit/b295fee)), closes [#263](https://github.com/kazupon/vue-i18n/issues/263)
+
+
+<a name="7.3.2"></a>
+## [7.3.2](https://github.com/kazupon/vue-i18n/compare/v7.3.1...v7.3.2) (2017-10-19)
+
+
+### :zap: Improvements
+
+* **typescript:** fix import problem of vue2.5 because of the types update ([#238](https://github.com/kazupon/vue-i18n/issues/238)) by [@peterchealse](https://github.com/peterchealse) ([cb98347](https://github.com/kazupon/vue-i18n/commit/cb98347)), closes [#238](https://github.com/kazupon/vue-i18n/issues/238)
+
+
+
+<a name="7.3.1"></a>
+## [7.3.1](https://github.com/kazupon/vue-i18n/compare/v7.3.0...v7.3.1) (2017-10-04)
+
+
+### :bug: Bug Fixes
+
+* **directive:** fix cannot locale reactivity ([e1fc12e](https://github.com/kazupon/vue-i18n/commit/e1fc12e)), closes [#227](https://github.com/kazupon/vue-i18n/issues/227)
+
+
+
+<a name="7.3.0"></a>
+# [7.3.0](https://github.com/kazupon/vue-i18n/compare/v7.2.0...v7.3.0) (2017-09-22)
+
+
+### :star: New Features
+
+* **directives:** support v-t custom directive (welcome back!) ([af9a2e7](https://github.com/kazupon/vue-i18n/commit/af9a2e7))
+
+
+### :up: Updates
+
+* **typing:** fix flowtype ([fa06f44](https://github.com/kazupon/vue-i18n/commit/fa06f44))
+
+
+
+<a name="7.2.0"></a>
+# [7.2.0](https://github.com/kazupon/vue-i18n/compare/v7.1.2...v7.2.0) (2017-08-28)
+
+
+### :star: New Features
+
+* **interpolation:** list formatting refactor and places/place feature ([#218](https://github.com/kazupon/vue-i18n/issues/218)) by [@myst729](https://github.com/myst729) ([0f0f3ff](https://github.com/kazupon/vue-i18n/commit/0f0f3ff))
+
+
+
+<a name="7.1.2"></a>
+## [7.1.2](https://github.com/kazupon/vue-i18n/compare/v7.1.1...v7.1.2) (2017-08-25)
+
+
+### :zap: Improvements
+
+* **interpolation:** skip non-element VNode in interpolation ([#211](https://github.com/kazupon/vue-i18n/issues/211)) by [@myst729](https://github.com/myst729) ([6be1756](https://github.com/kazupon/vue-i18n/commit/6be1756))
+
+
+
+<a name="7.1.1"></a>
+## [7.1.1](https://github.com/kazupon/vue-i18n/compare/v7.1.0...v7.1.1) (2017-08-03)
+
+
+### :bug: Bug Fixes
+
+* **mixin:** fix cannot setup VueI18n instance ([13585a4](https://github.com/kazupon/vue-i18n/commit/13585a4)), closes [#203](https://github.com/kazupon/vue-i18n/issues/203)
+
+
+
+<a name="7.1.0"></a>
+# [7.1.0](https://github.com/kazupon/vue-i18n/compare/v7.0.5...v7.1.0) (2017-07-30)
+
+
+### :zap: Improvements
+
+* **custom-block:** support multiple custom blocks ([ab955a5](https://github.com/kazupon/vue-i18n/commit/ab955a5)), closes [#189](https://github.com/kazupon/vue-i18n/issues/189)
+
+
+
+<a name="7.0.5"></a>
+## [7.0.5](https://github.com/kazupon/vue-i18n/compare/v7.0.4...v7.0.5) (2017-07-08)
+
+
+### :bug: Bug Fixes
+
+* **format:** fix cannot collectly parse percent ([fc71eda](https://github.com/kazupon/vue-i18n/commit/fc71eda)), closes [#191](https://github.com/kazupon/vue-i18n/issues/191)
+
+
+
+<a name="7.0.4"></a>
+## [7.0.4](https://github.com/kazupon/vue-i18n/compare/v7.0.3...v7.0.4) (2017-07-01)
+
+
+### :bug: Bug Fixes
+
+* **link:** fix ie traverse custom Array.prototype method ([#188](https://github.com/kazupon/vue-i18n/issues/188)) by [@632781460](https://github.com/632781460) ([d3b308b](https://github.com/kazupon/vue-i18n/commit/d3b308b)), closes [#188](https://github.com/kazupon/vue-i18n/issues/188)
+
+
+### :chart_with_upwards_trend: Performance Fixes
+
+* fix blocking at beforeDestroy ([570b215](https://github.com/kazupon/vue-i18n/commit/570b215)), closes [#187](https://github.com/kazupon/vue-i18n/issues/187)
+
+
+
+<a name="7.0.3"></a>
+## [7.0.3](https://github.com/kazupon/vue-i18n/compare/v7.0.2...v7.0.3) (2017-06-13)
+
+
+### :bug: Bug Fixes
+
+* **fallback:** fix cannot fallabck localization ([694e6f2](https://github.com/kazupon/vue-i18n/commit/694e6f2)), closes [#176](https://github.com/kazupon/vue-i18n/issues/176)
+* **fallback:** fix fallback locale issue ([d9ceddc](https://github.com/kazupon/vue-i18n/commit/d9ceddc)), closes [#174](https://github.com/kazupon/vue-i18n/issues/174)
+* **linked:** fix cannot fallback linked localization ([0c572f3](https://github.com/kazupon/vue-i18n/commit/0c572f3)), closes [#172](https://github.com/kazupon/vue-i18n/issues/172)
+
+
+
+<a name="7.0.2"></a>
+## [7.0.2](https://github.com/kazupon/vue-i18n/compare/v7.0.1...v7.0.2) (2017-06-10)
+
+
+### :bug: Bug Fixes
+
+* **sfc:** fix cannot parse custom block locale messages ([32eb3a7](https://github.com/kazupon/vue-i18n/commit/32eb3a7)), closes [#173](https://github.com/kazupon/vue-i18n/issues/173)
+
+
+
+<a name="7.0.1"></a>
+## [7.0.1](https://github.com/kazupon/vue-i18n/compare/v7.0.0...v7.0.1) (2017-06-04)
+
+
+### :bug: Bug Fixes
+
+* fix cannat single file component translation ([687d406](https://github.com/kazupon/vue-i18n/commit/687d406)), closes [#169](https://github.com/kazupon/vue-i18n/issues/169)
+* fix cannnot resolve linked localization with component interpolation ([c973619](https://github.com/kazupon/vue-i18n/commit/c973619)), closes [#171](https://github.com/kazupon/vue-i18n/issues/171)
+* fix datetime and number fallback localization ([be9e1bd](https://github.com/kazupon/vue-i18n/commit/be9e1bd)), closes [#168](https://github.com/kazupon/vue-i18n/issues/168)
+* fix linked translation with using hyphen or underscore keypath ([6e9f151](https://github.com/kazupon/vue-i18n/commit/6e9f151)), closes [#170](https://github.com/kazupon/vue-i18n/issues/170)
+
+
+<a name="7.0.0"></a>
+# [7.0.0](https://github.com/kazupon/vue-i18n/compare/v7.0.0-rc.1...v7.0.0) (2017-05-29)
+
+:tada: :tada: :tada:
+
+See the [docs](https://kazupon.github.io/vue-i18n/en/)
+
+
+### :star: New Features
+
+* **datetime localization:**
+    * [documentation](https://github.com/kazupon/vue-i18n/blob/dev/gitbook/en/datetime.md)
+    * [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/datetime)
+* **number localization:**
+    * [documentation](https://github.com/kazupon/vue-i18n/blob/dev/gitbook/en/number.md)
+    * [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/number)
+* **component interpolation:**
+    * [documentation](https://github.com/kazupon/vue-i18n/blob/dev/gitbook/en/interpolation.md)
+    * [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/interpolation)
+* **typescript:**
+    * [type definitions](https://github.com/kazupon/vue-i18n/blob/dev/types/index.d.ts)
+
+
+### :chart_with_upwards_trend: Performance Fixes
+
+* fix translation performance issue ([6032a51](https://github.com/kazupon/vue-i18n/commit/6032a51))
+
+
+### :zap: Improvements
+
+* **path:** tweak for ssr
+
+
+### :boom: Breaking changes
+
+* **format:** re-impelement formatter
+* **formatter:** change method nam
+* **flowtype:** fix locale message related type changing and remove underscore type
+
+
+### :bug: Bug Fixes
+
+* **examples:** fix ssr demo ([059034f](https://github.com/kazupon/vue-i18n/commit/059034f))
+* **pluralization:** fix default choice ([240cfed](https://github.com/kazupon/vue-i18n/commit/240cfed))
+
+
+<a name="7.0.0-rc.1"></a>
+# [7.0.0-rc.1](https://github.com/kazupon/vue-i18n/compare/v7.0.0-beta.4...v7.0.0-rc.1) (2017-05-26)
+
+
+### :chart_with_upwards_trend: Performance Fixes
+
+* fix translation performance issue ([6032a51](https://github.com/kazupon/vue-i18n/commit/6032a51)), closes [#165](https://github.com/kazupon/vue-i18n/issues/165)
+
+
+### :up: Updates
+
+* **flowtype:** remove unneccesary type ([eb60156](https://github.com/kazupon/vue-i18n/commit/eb60156))
+
+
+
+<a name="7.0.0-beta.4"></a>
+# [7.0.0-beta.4](https://github.com/kazupon/vue-i18n/compare/v7.0.0-beta.3...v7.0.0-beta.4) (2017-05-23)
+
+
+### :bug: Bug Fixes
+
+* **pluralization:** fix default choice ([240cfed](https://github.com/kazupon/vue-i18n/commit/240cfed)), closes [#164](https://github.com/kazupon/vue-i18n/issues/164)
+
+
+
+<a name="7.0.0-beta.3"></a>
+# [7.0.0-beta.3](https://github.com/kazupon/vue-i18n/compare/v7.0.0-beta.2...v7.0.0-beta.3) (2017-05-15)
+
+### :up: Updates
+
+* bring back from bug fix ([95be4ea](https://github.com/kazupon/vue-i18n/commit/95be4ea))
+
+
+<a name="7.0.0-beta.2"></a>
+# [7.0.0-beta.2](https://github.com/kazupon/vue-i18n/compare/v7.0.0-beta.1...v7.0.0-beta.2) (2017-05-14)
+
+
+### :zap: Improvements
+
+* **path:** tweak for ssr ([eb21921](https://github.com/kazupon/vue-i18n/commit/eb21921))
+* **typescript:** change custom formatter method name ([c5f043f](https://github.com/kazupon/vue-i18n/commit/c5f043f))
+
+
+
+<a name="7.0.0-beta.1"></a>
+# [7.0.0-beta.1](https://github.com/kazupon/vue-i18n/compare/v6.1.1...v7.0.0-beta.1) (2017-05-11)
+
+### :star: New Features
+
+* **datetime localization:** add datetime localization ([3282075](https://github.com/kazupon/vue-i18n/commit/3282075))
+    * [documentation](https://github.com/kazupon/vue-i18n/blob/dev/gitbook/en/datetime.md)
+    * [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/datetime)
+* **number localization:** add number localization ([87ee7b3](https://github.com/kazupon/vue-i18n/commit/87ee7b3))
+    * [documentation](https://github.com/kazupon/vue-i18n/blob/dev/gitbook/en/number.md)
+    * [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/number)
+* **component interpolation:** ([23f7d34](https://github.com/kazupon/vue-i18n/commit/23f7d34)), closes [#145](https://github.com/kazupon/vue-i18n/issues/145) [#144](https://github.com/kazupon/vue-i18n/issues/144) [#37](https://github.com/kazupon/vue-i18n/issues/37)
+    * [documentation](https://github.com/kazupon/vue-i18n/blob/dev/gitbook/en/interpolation.md)
+    * [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/interpolation)
+* **typescript:** add TypeScript type definitions ([#161](https://github.com/kazupon/vue-i18n/issues/161)) by [@aicest](https://github.com/aicest) ([61cebca](https://github.com/kazupon/vue-i18n/commit/61cebca))
+    * [type definitions](https://github.com/kazupon/vue-i18n/blob/dev/types/index.d.ts)
+
+
+### :boom: Breaking changes
+
+* **format:** re-impelement formatter ([a8c046d](https://github.com/kazupon/vue-i18n/commit/a8c046d))
+* **formatter:** change method name ([6eed51c](https://github.com/kazupon/vue-i18n/commit/6eed51c))
+* **flowtype:** fix locale message related type changing ([c30d576](https://github.com/kazupon/vue-i18n/commit/c30d576))
+
+
+### :bug: Bug Fixes
+
+* **examples:** fix ssr demo ([059034f](https://github.com/kazupon/vue-i18n/commit/059034f)), closes [#151](https://github.com/kazupon/vue-i18n/issues/151)
+
+
+<a name="6.1.3"></a>
+## [6.1.3](https://github.com/kazupon/vue-i18n/compare/v6.1.1...v6.1.3) (2017-05-15)
+
+
+### :bug: Bug Fixes
+
+* fix memory leaks ([95be4ea](https://github.com/kazupon/vue-i18n/commit/95be4ea)), closes [#162](https://github.com/kazupon/vue-i18n/issues/162)
+
+
+
+<a name="6.1.2"></a>
+## [6.1.2](https://github.com/kazupon/vue-i18n/compare/v6.1.1...v6.1.2) (2017-05-15)
+
+
+<a name="6.1.1"></a>
+## [6.1.1](https://github.com/kazupon/vue-i18n/compare/v6.1.0...v6.1.1) (2017-04-19)
+
+
+### :bug: Bug Fixes
+
+* **te:** Fix `te()` that always uses `this.locale`, even when `locale` supplied ([#147](https://github.com/kazupon/vue-i18n/issues/147)) by [@aicest](https://github.com/aicest) ([bf15eeb](https://github.com/kazupon/vue-i18n/commit/bf15eeb)), closes [#147](https://github.com/kazupon/vue-i18n/issues/147)
+
+
+
+<a name="6.1.0"></a>
+# [6.1.0](https://github.com/kazupon/vue-i18n/compare/v6.0.0...v6.1.0) (2017-04-14)
+
+
+### :star: New Features
+
+* **api:** add 'mergeLocaleMessage' method ([ef21621](https://github.com/kazupon/vue-i18n/commit/ef21621)), closes [#131](https://github.com/kazupon/vue-i18n/issues/131)
+* **silent:** add silent translation missing option ([29b3a17](https://github.com/kazupon/vue-i18n/commit/29b3a17)), closes [#139](https://github.com/kazupon/vue-i18n/issues/139)
+
+
+### :zap: Improvements
+
+* change to method from computed property ([9135a59](https://github.com/kazupon/vue-i18n/commit/9135a59)), closes [#141](https://github.com/kazupon/vue-i18n/issues/141)
+
+
+
+<a name="6.0.0"></a>
+# [6.0.0](https://github.com/kazupon/vue-i18n/compare/v6.0.0-beta.1...v6.0.0) (2017-04-05)
+
+:tada: :tada: :tada:
+
+See the [docs](https://kazupon.github.io/vue-i18n/en/)
+
+### :zap: Improvements
+
+- Server-Side Rendering: [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/ssr)
+- Custom formatter: [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/formatting/custom)
+
+
+### :star: NEW Features
+
+- Single File Components: [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/sfc)
+
+
+### :boom: Breaking changes
+
+- API
+- Dynamic locale <sup>DEPRECATED</sup>
+
+
+<a name="6.0.0-beta.1"></a>
+# [6.0.0-beta.1](https://github.com/kazupon/vue-i18n/compare/v6.0.0-alpha.6...v6.0.0-beta.1) (2017-03-22)
+
+
+### :boom: Breaking changes
+
+* change `fallbackRoot` and `sync` option default `true` value ([0890b44](https://github.com/kazupon/vue-i18n/commit/0890b44))
+* remove messages settter, and add getLocaleMessage API ([0f0914d](https://github.com/kazupon/vue-i18n/commit/0f0914d))
+
+
+### :bug: Bug Fixes
+
+* **mixin:** fix computed props errors ([a6b7e37](https://github.com/kazupon/vue-i18n/commit/a6b7e37))
+
+
+### :up: Updates
+
+* **flowtype:** argument names ([cf14425](https://github.com/kazupon/vue-i18n/commit/cf14425))
+
+
+### :zap: Improvements
+
+* **fallbackLocale:** support reactivity ([ed758be](https://github.com/kazupon/vue-i18n/commit/ed758be))
+* **warn:** suppress warning messages for production ([6e417d2](https://github.com/kazupon/vue-i18n/commit/6e417d2))
+
+
+
+<a name="6.0.0-alpha.6"></a>
+# [6.0.0-alpha.6](https://github.com/kazupon/vue-i18n/compare/v6.0.0-alpha.5...v6.0.0-alpha.6) (2017-03-16)
+
+
+### :star: New Features
+
+* add 'setLocaleMessage' API ([8b71eda](https://github.com/kazupon/vue-i18n/commit/8b71eda))
+
+
+
+<a name="6.0.0-alpha.5"></a>
+# [6.0.0-alpha.5](https://github.com/kazupon/vue-i18n/compare/v6.0.0-alpha.3...v6.0.0-alpha.5) (2017-03-11)
+
+
+### :bug: Bug Fixes
+
+* **mixin:** fix cannot create VueI18n instance error for minify production ([7eeb29f](https://github.com/kazupon/vue-i18n/commit/7eeb29f))
+
+
+
+<a name="6.0.0-alpha.4"></a>
+# [6.0.0-alpha.4](https://github.com/kazupon/vue-i18n/compare/v6.0.0-alpha.3...v6.0.0-alpha.4) (2017-03-11)
+
+
+
+<a name="6.0.0-alpha.3"></a>
+# [6.0.0-alpha.3](https://github.com/kazupon/vue-i18n/compare/v6.0.0-alpha.2...v6.0.0-alpha.3) (2017-03-08)
+
+
+### :star: New Features
+
+* add `sync` option ([5c46c07](https://github.com/kazupon/vue-i18n/commit/5c46c07))
+
+
+### :zap: Improvements
+
+* **mixin:** add error throwings and a warning ([0e4ac39](https://github.com/kazupon/vue-i18n/commit/0e4ac39))
+
+
+
+<a name="6.0.0-alpha.2"></a>
+# [6.0.0-alpha.2](https://github.com/kazupon/vue-i18n/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2017-02-27)
+
+
+### :zap: Improvements
+
+* **mixin:** release i18n instance ([cc362a3](https://github.com/kazupon/vue-i18n/commit/cc362a3))
+* **vue:** support vue 2.2 ([5e7bf5e](https://github.com/kazupon/vue-i18n/commit/5e7bf5e))
+
+
+
+<a name="6.0.0-alpha.1"></a>
+# [6.0.0-alpha.1](https://github.com/kazupon/vue-i18n/compare/v5.0.2...v6.0.0-alpha.1) (2017-02-23)
+
+This is the first release of 6.0.
+In this version, we are some big breaking changes.
+
+- Recommended for: experiments, prototypes, upgrading small, non-critical apps
+- **NOT** recommended for: production use, upgrading production apps
+
+:warning: Documentation still needs to be worked on. And also, we might change some APIs and features.
+
+In the examples, please refer to this [examples](https://github.com/kazupon/vue-i18n/tree/dev/examples) directory.
+
+
+## Improvements
+- Server-Side Rendering: [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/formatting/custom)
+- Custom formatter: [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/ssr)
+
+## Features
+- Formatting <sup>support</sup>
+- Pluralization <sup>support</sup>
+- Locale and KeyPath Syntax <sup>support</sup>
+- Linked translation <sup>support</sup>
+- Fallback translation <sup>support</sup>
+- Component locale <sup>support</sup>
+- Dynamic locale <sup>DEPRECATED</sup>
+- Hot reload <sup>support</sup>
+
+## API
+
+### Global Config
+- Vue.config.lang <sup>DEPRECATED, use VueI18n constructor `locale` option, or VueI18n#locale</sup>
+- Vue.config.fallbackLang <sup>DEPRECATED, use VueI18n constructor `fallbackLocale` option, or VueI18n#fallbackLocale</sup>
+- Vue.config.missingHandler <sup>DEPRECATED, use VueI18n constructor `missing` option, or VueI18n#missing</sup>
+- Vue.config.i18nFormatter <sup>DEPRECATED, use VueI18n constructor `formatter` option, or VueI18n#formatter</sup>
+
+### Global Method
+- Vue.locale <sup>DEPRECATED, use VueI18n constructor `messages` option, or VueI18n#messages</sup>
+- Vue.t <sup>DEPRECATED, use VueI18n#t</sup>
+- Vue.tc <sup>DEPRECATED, use VueI18n#tc</sup>
+- Vue.te <sup>DEPRECATED, use VueI18n#te</sup>
+
+### Constructor Options
+- locales <sup>DEPRECATED, use `messages` of `i18n` option (e.g `{ i18n: { messaes: ... } }`)</sup>
+
+### Instance Properties
+- $lang <sup>DEPRECATED, use `locale` of Vue instance property `$i18n` (e.g `vm.$i18n.locale = 'en'`)
+
+### VueI18n class <sup>NEW</sup>
+- constructor options: See the [`I18nOptions` type](https://github.com/kazupon/vue-i18n/blob/dev/decls/i18n.js#L7-L15) of flowtype.
+- methods / properties: See the [`I18n` interface definition](https://github.com/kazupon/vue-i18n/blob/dev/decls/i18n.js#L17-L33) of flowtype.
+
+
+<a name="5.0.2"></a>
+## [5.0.2](https://github.com/kazupon/vue-i18n/compare/v5.0.1...v5.0.2) (2017-02-18)
+
+
+### :zap: Improvements
+
+* **npm:** revert node >= 6.0 engine restriction ([#110](https://github.com/kazupon/vue-i18n/issues/110)) by [@syxolk](https://github.com/syxolk) ([92b1bd1](https://github.com/kazupon/vue-i18n/commit/92b1bd1)), closes [#109](https://github.com/kazupon/vue-i18n/issues/109)
+
+
+
+<a name="5.0.1"></a>
+## [5.0.1](https://github.com/kazupon/vue-i18n/compare/v5.0.0...v5.0.1) (2017-02-16)
+
+
+### :zap: Improvements
+
+* **asset:** update locale reactivity setting ([b42fd9a](https://github.com/kazupon/vue-i18n/commit/b42fd9a))
+
+
+
+<a name="5.0.0"></a>
+# [5.0.0](https://github.com/kazupon/vue-i18n/compare/v4.10.0...v5.0.0) (2017-02-04)
+
+
+### :boom: Breaking changes
+
+* drop vue 1.0 supporting ([4da26cf](https://github.com/kazupon/vue-i18n/commit/4da26cf)), closes [#105](https://github.com/kazupon/vue-i18n/issues/105)
+
+
+
+<a name="4.10.0"></a>
+# [4.10.0](https://github.com/kazupon/vue-i18n/compare/v4.9.0...v4.10.0) (2017-01-01)
+
+
+### :star: New Features
+
+* `$lang` property for all component ([#99](https://github.com/kazupon/vue-i18n/issues/99)) by [@albert](https://github.com/albert)-zhang ([5ed69f8](https://github.com/kazupon/vue-i18n/commit/5ed69f8))
+
+
+### :up: Updates
+
+* **override:** change langVM keeping variable name ([3ec1bb2](https://github.com/kazupon/vue-i18n/commit/3ec1bb2))
+
+
+
+<a name="4.9.0"></a>
+# [4.9.0](https://github.com/kazupon/vue-i18n/compare/v4.8.0...v4.9.0) (2016-12-17)
+
+
+### :bug: Bug Fixes
+
+* **path:** fix nested key translation ([e15ead4](https://github.com/kazupon/vue-i18n/commit/e15ead4)), closes [#97](https://github.com/kazupon/vue-i18n/issues/97)
+
+
+### :star: New Features
+
+* add globally locale checking ([4cac8b9](https://github.com/kazupon/vue-i18n/commit/4cac8b9))
+* locale checking ([#98](https://github.com/kazupon/vue-i18n/issues/98)) by [@long](https://github.com/long)-long-float ([0bc0a6b](https://github.com/kazupon/vue-i18n/commit/0bc0a6b))
+
+
+<a name="4.8.0"></a>
+# [4.8.0](https://github.com/kazupon/vue-i18n/compare/v4.7.4...v4.8.0) (2016-12-08)
+
+
+### :zap: Improvements
+
+* **extend:** disable no translation warning when set missingHandler ([168a97c](https://github.com/kazupon/vue-i18n/commit/168a97c)), closes [#96](https://github.com/kazupon/vue-i18n/issues/96)
+
+
+
+<a name="4.7.4"></a>
+## [4.7.4](https://github.com/kazupon/vue-i18n/compare/v4.7.3...v4.7.4) (2016-11-29)
+
+
+### :bug: Bug Fixes
+
+* **extend:** fix interpolate error [@tariq86](https://github.com/tariq86) ([5f24e17](https://github.com/kazupon/vue-i18n/commit/5f24e17))
+
+
+
+<a name="4.7.3"></a>
+## [4.7.3](https://github.com/kazupon/vue-i18n/compare/v4.7.2...v4.7.3) (2016-11-24)
+
+
+### :bug: Bug Fixes
+
+* **extend:** fix array local ([35c268a](https://github.com/kazupon/vue-i18n/commit/35c268a)), closes [#91](https://github.com/kazupon/vue-i18n/issues/91) [#59](https://github.com/kazupon/vue-i18n/issues/59)
+
+
+
+<a name="4.7.2"></a>
+## [4.7.2](https://github.com/kazupon/vue-i18n/compare/v4.7.1...v4.7.2) (2016-11-19)
+
+
+### :bug: Bug Fixes
+
+* **observer:** fix dep undefined error ([#88](https://github.com/kazupon/vue-i18n/issues/88)) by [@fandaa](https://github.com/fandaa) ([724974e](https://github.com/kazupon/vue-i18n/commit/724974e)), closes [#88](https://github.com/kazupon/vue-i18n/issues/88)
+
+
+### :zap: Improvements
+
+* **extend:** support translate empty string ([#86](https://github.com/kazupon/vue-i18n/issues/86)) by [@QingWei](https://github.com/QingWei)-Li ([8e6d154](https://github.com/kazupon/vue-i18n/commit/8e6d154))
+
+
+
+<a name="4.7.1"></a>
+## [4.7.1](https://github.com/kazupon/vue-i18n/compare/v4.7.0...v4.7.1) (2016-10-29)
+
+
+### :bug: Bug Fixes
+
+* **interpolate:** named formatting: use name if value is missing ([#77](https://github.com/kazupon/vue-i18n/issues/77)) by [@SebastianS90](https://github.com/SebastianS90) ([a0cc343](https://github.com/kazupon/vue-i18n/commit/a0cc343))
+
+
+### :zap: Improvements
+
+* **named:** using default use nmae when value is missing ([c34e8f1](https://github.com/kazupon/vue-i18n/commit/c34e8f1))
+
+
+
+<a name="4.7.0"></a>
+# [4.7.0](https://github.com/kazupon/vue-i18n/compare/v4.6.0...v4.7.0) (2016-10-28)
+
+
+### :star: New Features
+
+* hot reloading ([#71](https://github.com/kazupon/vue-i18n/issues/71)) by [@gglnx](https://github.com/gglnx) ([7bb94ac](https://github.com/kazupon/vue-i18n/commit/7bb94ac))
+
+
+### :zap: Improvements
+
+* **pluralization:** zero choice ([#70](https://github.com/kazupon/vue-i18n/issues/70)) by [@sebwas](https://github.com/sebwas) ([5f0004f](https://github.com/kazupon/vue-i18n/commit/5f0004f))
+
+
+
+<a name="4.6.0"></a>
+# [4.6.0](https://github.com/kazupon/vue-i18n/compare/v4.5.0...v4.6.0) (2016-09-24)
+
+
+### :star: New Features
+
+* **config:** custom message formatter ([#57](https://github.com/kazupon/vue-i18n/issues/57)) by [@jvmccarthy](https://github.com/jvmccarthy) ([2748eb4](https://github.com/kazupon/vue-i18n/commit/2748eb4))
+
+
+
+<a name="4.5.0"></a>
+# [4.5.0](https://github.com/kazupon/vue-i18n/compare/v4.4.1...v4.5.0) (2016-09-15)
+
+
+### :star: New Features
+
+* **config:** translation miss capturing configration ([aca0ed6](https://github.com/kazupon/vue-i18n/commit/aca0ed6)), closes [#54](https://github.com/kazupon/vue-i18n/issues/54)
+
+
+
+<a name="4.4.1"></a>
+## [4.4.1](https://github.com/kazupon/vue-i18n/compare/v4.4.0...v4.4.1) (2016-09-10)
+
+
+### :zap: Improvements
+
+* **translate:** support hyphenated key ([#52](https://github.com/kazupon/vue-i18n/issues/52)) by [@tariq86](https://github.com/tariq86) ([a40acfd](https://github.com/kazupon/vue-i18n/commit/a40acfd))
+
+
+
+<a name="4.4.0"></a>
+# [4.4.0](https://github.com/kazupon/vue-i18n/compare/v4.3.1...v4.4.0) (2016-08-29)
+
+
+### :star: New Features
+
+* add linked translations ([#50](https://github.com/kazupon/vue-i18n/issues/50)) by [@mmochetti](https://github.com/mmochetti) ([f7ae073](https://github.com/kazupon/vue-i18n/commit/f7ae073))
+
+
+
+<a name="4.3.1"></a>
+## [4.3.1](https://github.com/kazupon/vue-i18n/compare/v4.3.0...v4.3.1) (2016-08-26)
+
+
+### :bug: Bug Fixes
+
+* **npm:** fix installing bug ([57e66aa](https://github.com/kazupon/vue-i18n/commit/57e66aa)), closes [#46](https://github.com/kazupon/vue-i18n/issues/46)
+
+
+
+<a name="4.3.0"></a>
+# [4.3.0](https://github.com/kazupon/vue-i18n/compare/v4.2.3...v4.3.0) (2016-08-26)
+
+
+### :star: New Features
+
+* add pluralization ([#44](https://github.com/kazupon/vue-i18n/issues/44)) by [@mmochetti](https://github.com/mmochetti) ([b5b84d8](https://github.com/kazupon/vue-i18n/commit/b5b84d8))
+
+
+
+<a name="4.2.3"></a>
+## [4.2.3](https://github.com/kazupon/vue-i18n/compare/v4.2.2...v4.2.3) (2016-08-23)
+
+
+### :chart_with_upwards_trend: Performance Fixes
+
+* improve re-rendering cost when change the lang ([0707338](https://github.com/kazupon/vue-i18n/commit/0707338))
+
+
+
+<a name="4.2.2"></a>
+## [4.2.2](https://github.com/kazupon/vue-i18n/compare/v4.2.1...v4.2.2) (2016-08-15)
+
+
+### :bug: Bug Fixes
+
+* **path:** fix array path syntax error ([bc9dbee](https://github.com/kazupon/vue-i18n/commit/bc9dbee)), closes [#42](https://github.com/kazupon/vue-i18n/issues/42) [#43](https://github.com/kazupon/vue-i18n/issues/43)
+
+
+
+<a name="4.2.1"></a>
+## [4.2.1](https://github.com/kazupon/vue-i18n/compare/v4.2.0...v4.2.1) (2016-08-13)
+
+
+### :zap: Improvements
+
+* **translate:** fallback translation warning ([5f6b271](https://github.com/kazupon/vue-i18n/commit/5f6b271))
+
+
+
+<a name="4.2.0"></a>
+# [4.2.0](https://github.com/kazupon/vue-i18n/compare/v4.1.0...v4.2.0) (2016-08-12)
+
+
+### :chart_with_upwards_trend: Performance Fixes
+
+* **format:** use hasOwn function of Vue.util ([a8a19a0](https://github.com/kazupon/vue-i18n/commit/a8a19a0))
+
+
+### :star: New Features
+
+* **fallback:** add fallback translation feature ([1d1f0f2](https://github.com/kazupon/vue-i18n/commit/1d1f0f2)), closes [#36](https://github.com/kazupon/vue-i18n/issues/36)
+
+
+
+<a name="4.1.0"></a>
+# [4.1.0](https://github.com/kazupon/vue-i18n/compare/v4.0.1...v4.1.0) (2016-07-25)
+
+
+### :bug: Bug Fixes
+
+* **util:** fixed isArray reference errors ([0c6f6a0](https://github.com/kazupon/vue-i18n/commit/0c6f6a0))
+
+
+### :star: New Features
+
+* support vue 2.0.0.beta later ([0e1d2f7](https://github.com/kazupon/vue-i18n/commit/0e1d2f7))
+
+
+
+<a name="4.0.1"></a>
+## [4.0.1](https://github.com/kazupon/vue-i18n/compare/v4.0.0...v4.0.1) (2016-06-06)
+
+
+### :bug: Bug Fixes
+
+* **translate:** fix underscore named argument translate issue ([eeaf936](https://github.com/kazupon/vue-i18n/commit/eeaf936))
+
+
+
+<a name="4.0.0"></a>
+# [4.0.0](https://github.com/kazupon/vue-i18n/compare/v3.1.1...v4.0.0) (2016-05-10)
+
+
+### :zap: Improvements
+
+* support vue 2.0-pre-alpha ([f6517bc](https://github.com/kazupon/vue-i18n/commit/f6517bc))
+
+
+
+<a name="3.1.1"></a>
+## [3.1.1](https://github.com/kazupon/vue-i18n/compare/v3.1.0...v3.1.1) (2016-05-09)
+
+
+### :star: New Features
+
+* auto installation for standalone ([2b0dc09](https://github.com/kazupon/vue-i18n/commit/2b0dc09))
+
+
+
+<a name="3.1.0"></a>
+# [3.1.0](https://github.com/kazupon/vue-i18n/compare/v3.0.0...v3.1.0) (2016-05-09)
+
+
+### :star: New Features
+
+* component locales ([12fe695](https://github.com/kazupon/vue-i18n/commit/12fe695)), closes [#29](https://github.com/kazupon/vue-i18n/issues/29)
+
+
+### :warning: Depcreted
+
+* **options:** remove Vue.use options ([d87b59b](https://github.com/kazupon/vue-i18n/commit/d87b59b))
+
+
+### :zap: Improvements
+
+* **keypath:** port the object path parser ([3ae04b7](https://github.com/kazupon/vue-i18n/commit/3ae04b7))
+* **translation:** fix hypenate included key translating ([d0a415f](https://github.com/kazupon/vue-i18n/commit/d0a415f)), closes [#24](https://github.com/kazupon/vue-i18n/issues/24)
+* **translation:** warning outputing when cannot translate with keypath ([b4c7c0e](https://github.com/kazupon/vue-i18n/commit/b4c7c0e)), closes [#22](https://github.com/kazupon/vue-i18n/issues/22)
+
+
+
+<a name="3.0.0"></a>
+# [3.0.0](https://github.com/kazupon/vue-i18n/compare/v2.4.1...v3.0.0) (2016-04-18)
+
+
+### Features
+
+* **lang:** support lang reactive changing ([203ee85](https://github.com/kazupon/vue-i18n/commit/203ee85)), closes [#2](https://github.com/kazupon/vue-i18n/issues/2) [#15](https://github.com/kazupon/vue-i18n/issues/15)
+* **locale:** support dynamic local ([4d61e8d](https://github.com/kazupon/vue-i18n/commit/4d61e8d)), closes [#6](https://github.com/kazupon/vue-i18n/issues/6) [#21](https://github.com/kazupon/vue-i18n/issues/21)
+
+### DEPRECATED
+
+* **index:** plugin install `Vue.use` options (`options.locales`, `options.lang`). See [README](https://github.com/kazupon/vue-i18n/blob/dev/README.md)
+
+
+<a name="2.4.1"></a>
+## [2.4.1](https://github.com/kazupon/vue-i18n/compare/v2.4.0...v2.4.1) (2016-02-29)
+
+### Features
+
+* **i18n:** support ruby on rails i18n interpolation format ([b6b2490](https://github.com/kazupon/vue-i18n/commit/b6b2490))
+
+
+
+<a name="2.4.0"></a>
+# [2.4.0](https://github.com/kazupon/vue-i18n/compare/v2.3.3...v2.4.0) (2016-02-06)
+
+
+### Features
+
+* **i18n:** add Vue.t function ([68935e3](https://github.com/kazupon/vue-i18n/commit/68935e3)), closes [#17](https://github.com/kazupon/vue-i18n/issues/17)
+
+
+
+<a name="2.3.3"></a>
+## [2.3.3](https://github.com/kazupon/vue-i18n/compare/v2.3.2...v2.3.3) (2015-12-09)
+
+
+### Bug Fixes
+
+* **npm:** npm install error ([e31e89e](https://github.com/kazupon/vue-i18n/commit/e31e89e))
+
+### Features
+
+* **bower:** good-bye bower :wink: ([d99eb15](https://github.com/kazupon/vue-i18n/commit/d99eb15))
+
+
+### BREAKING CHANGES
+
+* bower: not support `bower` package manager
+
+I think that bower is dead. :no_good:
+
+
+
+<a name="2.3.2"></a>
+## [2.3.2](https://github.com/kazupon/vue-i18n/compare/v2.3.1...v2.3.2) (2015-12-09)
+
+
+### Features
+
+* **bundle:** more compact the vue-i18n distribution file ([2f32ecc](https://github.com/kazupon/vue-i18n/commit/2f32ecc))
+
+
+
+<a name="2.3.1"></a>
+## [2.3.1](https://github.com/kazupon/vue-i18n/compare/v2.3.0...v2.3.1) (2015-12-01)
+
+### Reverts
+
+* **index:** automatically install for standalone ([25b8059](https://github.com/kazupon/vue-i18n/commit/25b8059))
+
+
+
+<a name="2.3.0"></a>
+# [2.3.0](https://github.com/kazupon/vue-i18n/compare/v2.2.0...v2.3.0) (2015-11-26)
+
+
+### Bug Fixes
+
+* **index:** cannot work at Vue 1.0.10 later ([6fd543e](https://github.com/kazupon/vue-i18n/commit/6fd543e)), closes [#9](https://github.com/kazupon/vue-i18n/issues/9)
+
+### Features
+
+* **index:** support automatically install for standalone ([ada2673](https://github.com/kazupon/vue-i18n/commit/ada2673))
+
+
+
+# v2.2.0 / 2015-09-16
+
+* Re-implemetation with ES6 (babel)
+
+# v2.1.0 / 2015-07-03
+
+* Add global local language setting with `Vue.config.lang`
+
+# v2.0.0 / 2015-06-29
+
+* Support Vue.js 0.12
+* Remove the followings (Breaking Changes)
+    * `Vue.t` function
+    * `v-t` directive
+
+# v1.1.1 / 2015-04-21
+
+* Fix unit test error
+
+# v1.1.0 / 2015-01-10
+
+* Support template string in `$t` method
+* Support language changing in `$t` method
+
+# v1.0.0 / 2015-01-10
+
+* Add `$t` method
+
+# v0.11.0 / 2014-11-07
+
+* Bump to 0.11.0
+
+# v0.2.0 / 2014-10-08
+
+* Support Vue.js 0.11.0-rc
+
+# v0.1.2 / 2014-10-07
+
+* Support bower
+
+# v0.1.1 / 2014-10-06
+
+* Add `Vue.t` function
+
+# v0.1.0 / 2014-05-06
+
+* Release first
+
+# v0.0.0 / 2014-05-03
+
+* Initial project

+ 20 - 0
plugin/vue-i18n/LICENSE

@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 kazuya kawaguchi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 73 - 0
plugin/vue-i18n/README.md

@@ -0,0 +1,73 @@
+<p align="center"><img width="128px" height="112px" src="./assets/vue-i18n-logo.png" alt="Vue I18n logo"></p>
+<h1 align="center">vue-i18n</h1>
+<p align="center">
+  <a href="https://circleci.com/gh/kazupon/vue-i18n/tree/dev"><img src="https://circleci.com/gh/kazupon/vue-i18n/tree/dev.svg?style=shield" alt="Build Status"></a>
+  <a href="https://codecov.io/gh/kazupon/vue-i18n"><img src="https://codecov.io/gh/kazupon/vue-i18n/branch/dev/graph/badge.svg" alt="Coverage Status"></a>
+  <a href="http://badge.fury.io/js/vue-i18n"><img src="https://badge.fury.io/js/vue-i18n.svg" alt="NPM version"></a>
+  <a href="https://discord.gg/4yCnk2m"><img src="https://img.shields.io/badge/Discord-join%20chat-738bd7.svg" alt="vue-i18n channel on Discord"></a>
+  <a href="https://devtoken.rocks/package/vue-i18n"><img src="https://badge.devtoken.rocks/vue-i18n" alt="vue-i18n Dev Token"></a>
+</p>
+
+<p align="center">Internationalization plugin for Vue.js</p>
+
+<br/>
+
+<h3 align="center">Silver Sponsors</h3>
+
+<p align="center">
+  <a href="https://www.codeandweb.com/babeledit?utm_campaign=vue-i18n-2019-01" target="_blank">
+    <img src="https://raw.githubusercontent.com/kazupon/vue-i18n/dev/vuepress/.vuepress/public/patrons/babeledit.png">
+  </a>
+</p>
+
+<h3 align="center">Bronze Sponsors</h3>
+
+<p align="center">
+  <a href="https://zenarchitects.co.jp/" target="_blank">
+    <img src="https://raw.githubusercontent.com/kazupon/vue-i18n/v8.x/vuepress/.vuepress/public/patrons/zenarchitects.png">
+  </a>
+</p>
+
+<br/>
+
+<p align="center">
+  <a href="https://www.patreon.com/kazupon" target="_blank">
+    <img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Become a Patreon">
+  </a>
+</p>
+
+<br/>
+
+## :loudspeaker: Notice
+
+vue-i18n will soon be transferred to [intlify organization](https://github.com/intlify). After that, it will be developed and maintained on intlify.
+
+The `vue-i18n` that has been released on npm will be released as `@intlify/vue-i18n` in near future.
+
+`@intlify/vue-i18n` repo is [here](https://github.com/intlify/vue-i18n-next)
+
+Intlify is a new i18n project kickoff by @kazupon. 😉
+
+## :book: Documentation
+
+See [here](http://kazupon.github.io/vue-i18n/)
+
+
+## :scroll: Changelog
+
+Detailed changes for each release are documented in the [CHANGELOG.md](https://github.com/kazupon/vue-i18n/blob/dev/CHANGELOG.md).
+
+
+## :exclamation: Issues
+
+Please make sure to read the [Issue Reporting Checklist](https://github.com/kazupon/vue-i18n/blob/dev/CONTRIBUTING.md#issue-reporting-guidelines) before opening an issue. Issues not conforming to the guidelines may be closed immediately.
+
+
+## :muscle: Contribution
+
+Please make sure to read the [Contributing Guide](https://github.com/kazupon/vue-i18n/blob/dev/CONTRIBUTING.md) before making a pull request.
+
+
+## :copyright: License
+
+[MIT](http://opensource.org/licenses/MIT)

+ 160 - 0
plugin/vue-i18n/decls/i18n.js

@@ -0,0 +1,160 @@
+declare var Intl: any;
+
+declare type Path = string;
+declare type Locale = string;
+declare type MessageContext = {
+  list: (index: number) => mixed,
+  named: (key: string) => mixed
+}
+declare type MessageFunction = (ctx: MessageContext) => string
+declare type FallbackLocale = string | string[] | false | { [locale: string]: string[] };
+declare type LocaleMessage = string | MessageFunction | LocaleMessageObject | LocaleMessageArray;
+declare type LocaleMessageObject = { [key: Path]: LocaleMessage };
+declare type LocaleMessageArray = Array<LocaleMessage>;
+declare type LocaleMessages = { [key: Locale]: LocaleMessageObject };
+
+// This options is the same as Intl.DateTimeFormat constructor options:
+// http://www.ecma-international.org/ecma-402/2.0/#sec-intl-datetimeformat-constructor
+declare type DateTimeFormatOptions = {
+  year?: 'numeric' | '2-digit',
+  month?: 'numeric' | '2-digit' | 'narrow' | 'short' | 'long',
+  day?: 'numeric' | '2-digit',
+  hour?: 'numeric' | '2-digit',
+  minute?: 'numeric' | '2-digit',
+  second?: 'numeric' | '2-digit',
+  weekday?: 'narrow' | 'short' | 'long',
+  hour12?: boolean,
+  era?: 'narrow' | 'short' | 'long',
+  timeZone?: string, // IANA time zone
+  timeZoneName?: 'short' | 'long',
+  localeMatcher?: 'lookup' | 'best fit',
+  formatMatcher?: 'basic' | 'best fit'
+};
+declare type DateTimeFormat = { [key: string]: DateTimeFormatOptions };
+declare type DateTimeFormats = { [key: Locale]: DateTimeFormat };
+
+// This options is the same as Intl.NumberFormat constructor options:
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat
+declare type NumberFormatOptions = {
+  style?: 'decimal' | 'currency' | 'percent',
+  currency?: string, // ISO 4217 currency codes
+  currencyDisplay?: 'symbol' | 'code' | 'name',
+  useGrouping?: boolean,
+  minimumIntegerDigits?: number,
+  minimumFractionDigits?: number,
+  maximumFractionDigits?: number,
+  minimumSignificantDigits?: number,
+  maximumSignificantDigits?: number,
+  localeMatcher?: 'lookup' | 'best fit',
+  formatMatcher?: 'basic' | 'best fit'
+};
+declare type NumberFormat = { [key: string]: NumberFormatOptions };
+declare type NumberFormats = { [key: Locale]: NumberFormat };
+declare type Modifiers = { [key: string]: (str: string) => string };
+
+declare type TranslateResult = string | LocaleMessages;
+declare type DateTimeFormatResult = string;
+declare type NumberFormatResult = string;
+declare type MissingHandler = (locale: Locale, key: Path, vm?: any) => string | void;
+declare type PostTranslationHandler = (str: string, key?: string) => string;
+declare type GetChoiceIndex = (choice: number, choicesLength: number) => number
+declare type ComponentInstanceCreatedListener = (newI18n: I18n, rootI18n: I18n) => void;
+
+declare type FormattedNumberPartType = 'currency' | 'decimal' | 'fraction' | 'group' | 'infinity' | 'integer' | 'literal' | 'minusSign' | 'nan' | 'plusSign' | 'percentSign';
+declare type FormattedNumberPart = {
+  type: FormattedNumberPartType,
+  value: string,
+};
+// This array is the same as Intl.NumberFormat.formatToParts() return value:
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat/formatToParts#Return_value
+declare type NumberFormatToPartsResult = Array<FormattedNumberPart>;
+
+declare type WarnHtmlInMessageLevel = 'off' | 'warn' | 'error';
+
+declare type I18nOptions = {
+  locale?: Locale,
+  fallbackLocale?: FallbackLocale,
+  messages?: LocaleMessages,
+  dateTimeFormats?: DateTimeFormats,
+  numberFormats?: NumberFormats,
+  formatter?: Formatter,
+  missing?: MissingHandler,
+  modifiers?: Modifiers,
+  root?: I18n, // for internal
+  fallbackRoot?: boolean,
+  formatFallbackMessages?: boolean,
+  sync?: boolean,
+  silentTranslationWarn?: boolean | RegExp,
+  silentFallbackWarn?: boolean | RegExp,
+  pluralizationRules?: PluralizationRules,
+  preserveDirectiveContent?: boolean,
+  warnHtmlInMessage?: WarnHtmlInMessageLevel,
+  sharedMessages?: LocaleMessage,
+  postTranslation?: PostTranslationHandler,
+  componentInstanceCreatedListener?: ComponentInstanceCreatedListener,
+};
+
+declare type IntlAvailability = {
+  dateTimeFormat: boolean,
+  numberFormat: boolean
+};
+
+declare type PluralizationRules = {
+  [lang: string]: GetChoiceIndex,
+}
+
+declare interface I18n {
+  static install: () => void, // for Vue plugin interface
+  static version: string,
+  static availabilities: IntlAvailability,
+  get vm (): any, // for internal
+  get locale (): Locale,
+  set locale (locale: Locale): void,
+  get fallbackLocale (): FallbackLocale,
+  set fallbackLocale (locale: FallbackLocale): void,
+  get messages (): LocaleMessages,
+  get dateTimeFormats (): DateTimeFormats,
+  get numberFormats (): NumberFormats,
+  get availableLocales (): Locale[],
+  get missing (): ?MissingHandler,
+  set missing (handler: MissingHandler): void,
+  get formatter (): Formatter,
+  set formatter (formatter: Formatter): void,
+  get formatFallbackMessages (): boolean,
+  set formatFallbackMessages (fallback: boolean): void,
+  get silentTranslationWarn (): boolean | RegExp,
+  set silentTranslationWarn (silent: boolean | RegExp): void,
+  get silentFallbackWarn (): boolean | RegExp,
+  set silentFallbackWarn (slient: boolean | RegExp): void,
+  get pluralizationRules (): PluralizationRules,
+  set pluralizationRules (rules: PluralizationRules): void,
+  get preserveDirectiveContent (): boolean,
+  set preserveDirectiveContent (preserve: boolean): void,
+  get warnHtmlInMessage (): WarnHtmlInMessageLevel,
+  set warnHtmlInMessage (level: WarnHtmlInMessageLevel): void,
+  get postTranslation (): ?PostTranslationHandler,
+  set postTranslation (handler: PostTranslationHandler): void,
+
+  getLocaleMessage (locale: Locale): LocaleMessageObject,
+  setLocaleMessage (locale: Locale, message: LocaleMessageObject): void,
+  mergeLocaleMessage (locale: Locale, message: LocaleMessageObject): void,
+  t (key: Path, ...values: any): TranslateResult,
+  i (key: Path, locale: Locale, values: Object): TranslateResult,
+  tc (key: Path, choice?: number, ...values: any): TranslateResult,
+  te (key: Path, locale?: Locale): boolean,
+  getDateTimeFormat (locale: Locale): DateTimeFormat,
+  setDateTimeFormat (locale: Locale, format: DateTimeFormat): void,
+  mergeDateTimeFormat (locale: Locale, format: DateTimeFormat): void,
+  d (value: number | Date, ...args: any): DateTimeFormatResult,
+  getNumberFormat (locale: Locale): NumberFormat,
+  setNumberFormat (locale: Locale, format: NumberFormat): void,
+  mergeNumberFormat (locale: Locale, format: NumberFormat): void,
+  n (value: number, ...args: any): NumberFormatResult,
+  getChoiceIndex: GetChoiceIndex,
+  pluralizationRules: PluralizationRules,
+  preserveDirectiveContent: boolean
+};
+
+declare interface Formatter {
+  interpolate (message: string, values: any, path: string): (Array<any> | null)
+};

+ 30 - 0
plugin/vue-i18n/decls/module.js

@@ -0,0 +1,30 @@
+declare type $npm$Vue$Dictionaly<T> = { [key: string]: T }
+
+declare type Util = {
+  extend: (to: Object, from: ?Object) => Object,
+  hasOwn: (obj: Object, key: string) => boolean,
+  isPlainObject: (obj: any) => boolean,
+  isObject: (obj: mixed) => boolean,
+}
+
+declare type Config = {
+  optionMergeStrategies: $npm$Vue$Dictionaly<Function>,
+  silent: boolean,
+  productionTip: boolean,
+  performance: boolean,
+  devtools: boolean,
+  errorHandler: ?(err: Error, vm: Vue, info: string) => void,
+  ignoredElements: Array<string>,
+  keyCodes: $npm$Vue$Dictionaly<number>,
+  isReservedTag: (x?: string) => boolean,
+  parsePlatformTagName: (x: string) => string,
+  isUnknownElement: (x?: string) => boolean,
+  getTagNamespace: (x?: string) => string | void,
+  mustUseProp: (tag: string, type: ?string, name: string) => boolean,
+}
+
+declare interface Vue {
+  static config: Config,
+  static util: Util,
+  static version: string,
+}

+ 2151 - 0
plugin/vue-i18n/dist/vue-i18n.common.js

@@ -0,0 +1,2151 @@
+/*!
+ * vue-i18n v8.21.0 
+ * (c) 2020 kazuya kawaguchi
+ * Released under the MIT License.
+ */
+'use strict';
+
+/*  */
+
+/**
+ * constants
+ */
+
+var numberFormatKeys = [
+  'style',
+  'currency',
+  'currencyDisplay',
+  'useGrouping',
+  'minimumIntegerDigits',
+  'minimumFractionDigits',
+  'maximumFractionDigits',
+  'minimumSignificantDigits',
+  'maximumSignificantDigits',
+  'localeMatcher',
+  'formatMatcher',
+  'unit'
+];
+
+/**
+ * utilities
+ */
+
+function warn (msg, err) {
+  if (typeof console !== 'undefined') {
+    console.warn('[vue-i18n] ' + msg);
+    /* istanbul ignore if */
+    if (err) {
+      console.warn(err.stack);
+    }
+  }
+}
+
+function error (msg, err) {
+  if (typeof console !== 'undefined') {
+    console.error('[vue-i18n] ' + msg);
+    /* istanbul ignore if */
+    if (err) {
+      console.error(err.stack);
+    }
+  }
+}
+
+var isArray = Array.isArray;
+
+function isObject (obj) {
+  return obj !== null && typeof obj === 'object'
+}
+
+function isBoolean (val) {
+  return typeof val === 'boolean'
+}
+
+function isString (val) {
+  return typeof val === 'string'
+}
+
+var toString = Object.prototype.toString;
+var OBJECT_STRING = '[object Object]';
+function isPlainObject (obj) {
+  return toString.call(obj) === OBJECT_STRING
+}
+
+function isNull (val) {
+  return val === null || val === undefined
+}
+
+function isFunction (val) {
+  return typeof val === 'function'
+}
+
+function parseArgs () {
+  var args = [], len = arguments.length;
+  while ( len-- ) args[ len ] = arguments[ len ];
+
+  var locale = null;
+  var params = null;
+  if (args.length === 1) {
+    if (isObject(args[0]) || isArray(args[0])) {
+      params = args[0];
+    } else if (typeof args[0] === 'string') {
+      locale = args[0];
+    }
+  } else if (args.length === 2) {
+    if (typeof args[0] === 'string') {
+      locale = args[0];
+    }
+    /* istanbul ignore if */
+    if (isObject(args[1]) || isArray(args[1])) {
+      params = args[1];
+    }
+  }
+
+  return { locale: locale, params: params }
+}
+
+function looseClone (obj) {
+  return JSON.parse(JSON.stringify(obj))
+}
+
+function remove (arr, item) {
+  if (arr.length) {
+    var index = arr.indexOf(item);
+    if (index > -1) {
+      return arr.splice(index, 1)
+    }
+  }
+}
+
+function includes (arr, item) {
+  return !!~arr.indexOf(item)
+}
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+function hasOwn (obj, key) {
+  return hasOwnProperty.call(obj, key)
+}
+
+function merge (target) {
+  var arguments$1 = arguments;
+
+  var output = Object(target);
+  for (var i = 1; i < arguments.length; i++) {
+    var source = arguments$1[i];
+    if (source !== undefined && source !== null) {
+      var key = (void 0);
+      for (key in source) {
+        if (hasOwn(source, key)) {
+          if (isObject(source[key])) {
+            output[key] = merge(output[key], source[key]);
+          } else {
+            output[key] = source[key];
+          }
+        }
+      }
+    }
+  }
+  return output
+}
+
+function looseEqual (a, b) {
+  if (a === b) { return true }
+  var isObjectA = isObject(a);
+  var isObjectB = isObject(b);
+  if (isObjectA && isObjectB) {
+    try {
+      var isArrayA = isArray(a);
+      var isArrayB = isArray(b);
+      if (isArrayA && isArrayB) {
+        return a.length === b.length && a.every(function (e, i) {
+          return looseEqual(e, b[i])
+        })
+      } else if (!isArrayA && !isArrayB) {
+        var keysA = Object.keys(a);
+        var keysB = Object.keys(b);
+        return keysA.length === keysB.length && keysA.every(function (key) {
+          return looseEqual(a[key], b[key])
+        })
+      } else {
+        /* istanbul ignore next */
+        return false
+      }
+    } catch (e) {
+      /* istanbul ignore next */
+      return false
+    }
+  } else if (!isObjectA && !isObjectB) {
+    return String(a) === String(b)
+  } else {
+    return false
+  }
+}
+
+/*  */
+
+function extend (Vue) {
+  if (!Vue.prototype.hasOwnProperty('$i18n')) {
+    // $FlowFixMe
+    Object.defineProperty(Vue.prototype, '$i18n', {
+      get: function get () { return this._i18n }
+    });
+  }
+
+  Vue.prototype.$t = function (key) {
+    var values = [], len = arguments.length - 1;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 1 ];
+
+    var i18n = this.$i18n;
+    return i18n._t.apply(i18n, [ key, i18n.locale, i18n._getMessages(), this ].concat( values ))
+  };
+
+  Vue.prototype.$tc = function (key, choice) {
+    var values = [], len = arguments.length - 2;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 2 ];
+
+    var i18n = this.$i18n;
+    return i18n._tc.apply(i18n, [ key, i18n.locale, i18n._getMessages(), this, choice ].concat( values ))
+  };
+
+  Vue.prototype.$te = function (key, locale) {
+    var i18n = this.$i18n;
+    return i18n._te(key, i18n.locale, i18n._getMessages(), locale)
+  };
+
+  Vue.prototype.$d = function (value) {
+    var ref;
+
+    var args = [], len = arguments.length - 1;
+    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+    return (ref = this.$i18n).d.apply(ref, [ value ].concat( args ))
+  };
+
+  Vue.prototype.$n = function (value) {
+    var ref;
+
+    var args = [], len = arguments.length - 1;
+    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+    return (ref = this.$i18n).n.apply(ref, [ value ].concat( args ))
+  };
+}
+
+/*  */
+
+var mixin = {
+  beforeCreate: function beforeCreate () {
+    var options = this.$options;
+    options.i18n = options.i18n || (options.__i18n ? {} : null);
+
+    if (options.i18n) {
+      if (options.i18n instanceof VueI18n) {
+        // init locale messages via custom blocks
+        if (options.__i18n) {
+          try {
+            var localeMessages = {};
+            options.__i18n.forEach(function (resource) {
+              localeMessages = merge(localeMessages, JSON.parse(resource));
+            });
+            Object.keys(localeMessages).forEach(function (locale) {
+              options.i18n.mergeLocaleMessage(locale, localeMessages[locale]);
+            });
+          } catch (e) {
+            if (process.env.NODE_ENV !== 'production') {
+              error("Cannot parse locale messages via custom blocks.", e);
+            }
+          }
+        }
+        this._i18n = options.i18n;
+        this._i18nWatcher = this._i18n.watchI18nData();
+      } else if (isPlainObject(options.i18n)) {
+        var rootI18n = this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n
+          ? this.$root.$i18n
+          : null;
+        // component local i18n
+        if (rootI18n) {
+          options.i18n.root = this.$root;
+          options.i18n.formatter = rootI18n.formatter;
+          options.i18n.fallbackLocale = rootI18n.fallbackLocale;
+          options.i18n.formatFallbackMessages = rootI18n.formatFallbackMessages;
+          options.i18n.silentTranslationWarn = rootI18n.silentTranslationWarn;
+          options.i18n.silentFallbackWarn = rootI18n.silentFallbackWarn;
+          options.i18n.pluralizationRules = rootI18n.pluralizationRules;
+          options.i18n.preserveDirectiveContent = rootI18n.preserveDirectiveContent;
+        }
+
+        // init locale messages via custom blocks
+        if (options.__i18n) {
+          try {
+            var localeMessages$1 = {};
+            options.__i18n.forEach(function (resource) {
+              localeMessages$1 = merge(localeMessages$1, JSON.parse(resource));
+            });
+            options.i18n.messages = localeMessages$1;
+          } catch (e) {
+            if (process.env.NODE_ENV !== 'production') {
+              warn("Cannot parse locale messages via custom blocks.", e);
+            }
+          }
+        }
+
+        var ref = options.i18n;
+        var sharedMessages = ref.sharedMessages;
+        if (sharedMessages && isPlainObject(sharedMessages)) {
+          options.i18n.messages = merge(options.i18n.messages, sharedMessages);
+        }
+
+        this._i18n = new VueI18n(options.i18n);
+        this._i18nWatcher = this._i18n.watchI18nData();
+
+        if (options.i18n.sync === undefined || !!options.i18n.sync) {
+          this._localeWatcher = this.$i18n.watchLocale();
+        }
+
+        if (rootI18n) {
+          rootI18n.onComponentInstanceCreated(this._i18n);
+        }
+      } else {
+        if (process.env.NODE_ENV !== 'production') {
+          warn("Cannot be interpreted 'i18n' option.");
+        }
+      }
+    } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
+      // root i18n
+      this._i18n = this.$root.$i18n;
+    } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
+      // parent i18n
+      this._i18n = options.parent.$i18n;
+    }
+  },
+
+  beforeMount: function beforeMount () {
+    var options = this.$options;
+    options.i18n = options.i18n || (options.__i18n ? {} : null);
+
+    if (options.i18n) {
+      if (options.i18n instanceof VueI18n) {
+        // init locale messages via custom blocks
+        this._i18n.subscribeDataChanging(this);
+        this._subscribing = true;
+      } else if (isPlainObject(options.i18n)) {
+        this._i18n.subscribeDataChanging(this);
+        this._subscribing = true;
+      } else {
+        if (process.env.NODE_ENV !== 'production') {
+          warn("Cannot be interpreted 'i18n' option.");
+        }
+      }
+    } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
+      this._i18n.subscribeDataChanging(this);
+      this._subscribing = true;
+    } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
+      this._i18n.subscribeDataChanging(this);
+      this._subscribing = true;
+    }
+  },
+
+  beforeDestroy: function beforeDestroy () {
+    if (!this._i18n) { return }
+
+    var self = this;
+    this.$nextTick(function () {
+      if (self._subscribing) {
+        self._i18n.unsubscribeDataChanging(self);
+        delete self._subscribing;
+      }
+
+      if (self._i18nWatcher) {
+        self._i18nWatcher();
+        self._i18n.destroyVM();
+        delete self._i18nWatcher;
+      }
+
+      if (self._localeWatcher) {
+        self._localeWatcher();
+        delete self._localeWatcher;
+      }
+    });
+  }
+};
+
+/*  */
+
+var interpolationComponent = {
+  name: 'i18n',
+  functional: true,
+  props: {
+    tag: {
+      type: [String, Boolean, Object],
+      default: 'span'
+    },
+    path: {
+      type: String,
+      required: true
+    },
+    locale: {
+      type: String
+    },
+    places: {
+      type: [Array, Object]
+    }
+  },
+  render: function render (h, ref) {
+    var data = ref.data;
+    var parent = ref.parent;
+    var props = ref.props;
+    var slots = ref.slots;
+
+    var $i18n = parent.$i18n;
+    if (!$i18n) {
+      if (process.env.NODE_ENV !== 'production') {
+        warn('Cannot find VueI18n instance!');
+      }
+      return
+    }
+
+    var path = props.path;
+    var locale = props.locale;
+    var places = props.places;
+    var params = slots();
+    var children = $i18n.i(
+      path,
+      locale,
+      onlyHasDefaultPlace(params) || places
+        ? useLegacyPlaces(params.default, places)
+        : params
+    );
+
+    var tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span';
+    return tag ? h(tag, data, children) : children
+  }
+};
+
+function onlyHasDefaultPlace (params) {
+  var prop;
+  for (prop in params) {
+    if (prop !== 'default') { return false }
+  }
+  return Boolean(prop)
+}
+
+function useLegacyPlaces (children, places) {
+  var params = places ? createParamsFromPlaces(places) : {};
+
+  if (!children) { return params }
+
+  // Filter empty text nodes
+  children = children.filter(function (child) {
+    return child.tag || child.text.trim() !== ''
+  });
+
+  var everyPlace = children.every(vnodeHasPlaceAttribute);
+  if (process.env.NODE_ENV !== 'production' && everyPlace) {
+    warn('`place` attribute is deprecated in next major version. Please switch to Vue slots.');
+  }
+
+  return children.reduce(
+    everyPlace ? assignChildPlace : assignChildIndex,
+    params
+  )
+}
+
+function createParamsFromPlaces (places) {
+  if (process.env.NODE_ENV !== 'production') {
+    warn('`places` prop is deprecated in next major version. Please switch to Vue slots.');
+  }
+
+  return Array.isArray(places)
+    ? places.reduce(assignChildIndex, {})
+    : Object.assign({}, places)
+}
+
+function assignChildPlace (params, child) {
+  if (child.data && child.data.attrs && child.data.attrs.place) {
+    params[child.data.attrs.place] = child;
+  }
+  return params
+}
+
+function assignChildIndex (params, child, index) {
+  params[index] = child;
+  return params
+}
+
+function vnodeHasPlaceAttribute (vnode) {
+  return Boolean(vnode.data && vnode.data.attrs && vnode.data.attrs.place)
+}
+
+/*  */
+
+var numberComponent = {
+  name: 'i18n-n',
+  functional: true,
+  props: {
+    tag: {
+      type: [String, Boolean, Object],
+      default: 'span'
+    },
+    value: {
+      type: Number,
+      required: true
+    },
+    format: {
+      type: [String, Object]
+    },
+    locale: {
+      type: String
+    }
+  },
+  render: function render (h, ref) {
+    var props = ref.props;
+    var parent = ref.parent;
+    var data = ref.data;
+
+    var i18n = parent.$i18n;
+
+    if (!i18n) {
+      if (process.env.NODE_ENV !== 'production') {
+        warn('Cannot find VueI18n instance!');
+      }
+      return null
+    }
+
+    var key = null;
+    var options = null;
+
+    if (isString(props.format)) {
+      key = props.format;
+    } else if (isObject(props.format)) {
+      if (props.format.key) {
+        key = props.format.key;
+      }
+
+      // Filter out number format options only
+      options = Object.keys(props.format).reduce(function (acc, prop) {
+        var obj;
+
+        if (includes(numberFormatKeys, prop)) {
+          return Object.assign({}, acc, ( obj = {}, obj[prop] = props.format[prop], obj ))
+        }
+        return acc
+      }, null);
+    }
+
+    var locale = props.locale || i18n.locale;
+    var parts = i18n._ntp(props.value, locale, key, options);
+
+    var values = parts.map(function (part, index) {
+      var obj;
+
+      var slot = data.scopedSlots && data.scopedSlots[part.type];
+      return slot ? slot(( obj = {}, obj[part.type] = part.value, obj.index = index, obj.parts = parts, obj )) : part.value
+    });
+
+    var tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span';
+    return tag
+      ? h(tag, {
+        attrs: data.attrs,
+        'class': data['class'],
+        staticClass: data.staticClass
+      }, values)
+      : values
+  }
+};
+
+/*  */
+
+function bind (el, binding, vnode) {
+  if (!assert(el, vnode)) { return }
+
+  t(el, binding, vnode);
+}
+
+function update (el, binding, vnode, oldVNode) {
+  if (!assert(el, vnode)) { return }
+
+  var i18n = vnode.context.$i18n;
+  if (localeEqual(el, vnode) &&
+    (looseEqual(binding.value, binding.oldValue) &&
+     looseEqual(el._localeMessage, i18n.getLocaleMessage(i18n.locale)))) { return }
+
+  t(el, binding, vnode);
+}
+
+function unbind (el, binding, vnode, oldVNode) {
+  var vm = vnode.context;
+  if (!vm) {
+    warn('Vue instance does not exists in VNode context');
+    return
+  }
+
+  var i18n = vnode.context.$i18n || {};
+  if (!binding.modifiers.preserve && !i18n.preserveDirectiveContent) {
+    el.textContent = '';
+  }
+  el._vt = undefined;
+  delete el['_vt'];
+  el._locale = undefined;
+  delete el['_locale'];
+  el._localeMessage = undefined;
+  delete el['_localeMessage'];
+}
+
+function assert (el, vnode) {
+  var vm = vnode.context;
+  if (!vm) {
+    warn('Vue instance does not exists in VNode context');
+    return false
+  }
+
+  if (!vm.$i18n) {
+    warn('VueI18n instance does not exists in Vue instance');
+    return false
+  }
+
+  return true
+}
+
+function localeEqual (el, vnode) {
+  var vm = vnode.context;
+  return el._locale === vm.$i18n.locale
+}
+
+function t (el, binding, vnode) {
+  var ref$1, ref$2;
+
+  var value = binding.value;
+
+  var ref = parseValue(value);
+  var path = ref.path;
+  var locale = ref.locale;
+  var args = ref.args;
+  var choice = ref.choice;
+  if (!path && !locale && !args) {
+    warn('value type not supported');
+    return
+  }
+
+  if (!path) {
+    warn('`path` is required in v-t directive');
+    return
+  }
+
+  var vm = vnode.context;
+  if (choice != null) {
+    el._vt = el.textContent = (ref$1 = vm.$i18n).tc.apply(ref$1, [ path, choice ].concat( makeParams(locale, args) ));
+  } else {
+    el._vt = el.textContent = (ref$2 = vm.$i18n).t.apply(ref$2, [ path ].concat( makeParams(locale, args) ));
+  }
+  el._locale = vm.$i18n.locale;
+  el._localeMessage = vm.$i18n.getLocaleMessage(vm.$i18n.locale);
+}
+
+function parseValue (value) {
+  var path;
+  var locale;
+  var args;
+  var choice;
+
+  if (isString(value)) {
+    path = value;
+  } else if (isPlainObject(value)) {
+    path = value.path;
+    locale = value.locale;
+    args = value.args;
+    choice = value.choice;
+  }
+
+  return { path: path, locale: locale, args: args, choice: choice }
+}
+
+function makeParams (locale, args) {
+  var params = [];
+
+  locale && params.push(locale);
+  if (args && (Array.isArray(args) || isPlainObject(args))) {
+    params.push(args);
+  }
+
+  return params
+}
+
+var Vue;
+
+function install (_Vue) {
+  /* istanbul ignore if */
+  if (process.env.NODE_ENV !== 'production' && install.installed && _Vue === Vue) {
+    warn('already installed.');
+    return
+  }
+  install.installed = true;
+
+  Vue = _Vue;
+
+  var version = (Vue.version && Number(Vue.version.split('.')[0])) || -1;
+  /* istanbul ignore if */
+  if (process.env.NODE_ENV !== 'production' && version < 2) {
+    warn(("vue-i18n (" + (install.version) + ") need to use Vue 2.0 or later (Vue: " + (Vue.version) + ")."));
+    return
+  }
+
+  extend(Vue);
+  Vue.mixin(mixin);
+  Vue.directive('t', { bind: bind, update: update, unbind: unbind });
+  Vue.component(interpolationComponent.name, interpolationComponent);
+  Vue.component(numberComponent.name, numberComponent);
+
+  // use simple mergeStrategies to prevent i18n instance lose '__proto__'
+  var strats = Vue.config.optionMergeStrategies;
+  strats.i18n = function (parentVal, childVal) {
+    return childVal === undefined
+      ? parentVal
+      : childVal
+  };
+}
+
+/*  */
+
+var BaseFormatter = function BaseFormatter () {
+  this._caches = Object.create(null);
+};
+
+BaseFormatter.prototype.interpolate = function interpolate (message, values) {
+  if (!values) {
+    return [message]
+  }
+  var tokens = this._caches[message];
+  if (!tokens) {
+    tokens = parse(message);
+    this._caches[message] = tokens;
+  }
+  return compile(tokens, values)
+};
+
+
+
+var RE_TOKEN_LIST_VALUE = /^(?:\d)+/;
+var RE_TOKEN_NAMED_VALUE = /^(?:\w)+/;
+
+function parse (format) {
+  var tokens = [];
+  var position = 0;
+
+  var text = '';
+  while (position < format.length) {
+    var char = format[position++];
+    if (char === '{') {
+      if (text) {
+        tokens.push({ type: 'text', value: text });
+      }
+
+      text = '';
+      var sub = '';
+      char = format[position++];
+      while (char !== undefined && char !== '}') {
+        sub += char;
+        char = format[position++];
+      }
+      var isClosed = char === '}';
+
+      var type = RE_TOKEN_LIST_VALUE.test(sub)
+        ? 'list'
+        : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
+          ? 'named'
+          : 'unknown';
+      tokens.push({ value: sub, type: type });
+    } else if (char === '%') {
+      // when found rails i18n syntax, skip text capture
+      if (format[(position)] !== '{') {
+        text += char;
+      }
+    } else {
+      text += char;
+    }
+  }
+
+  text && tokens.push({ type: 'text', value: text });
+
+  return tokens
+}
+
+function compile (tokens, values) {
+  var compiled = [];
+  var index = 0;
+
+  var mode = Array.isArray(values)
+    ? 'list'
+    : isObject(values)
+      ? 'named'
+      : 'unknown';
+  if (mode === 'unknown') { return compiled }
+
+  while (index < tokens.length) {
+    var token = tokens[index];
+    switch (token.type) {
+      case 'text':
+        compiled.push(token.value);
+        break
+      case 'list':
+        compiled.push(values[parseInt(token.value, 10)]);
+        break
+      case 'named':
+        if (mode === 'named') {
+          compiled.push((values)[token.value]);
+        } else {
+          if (process.env.NODE_ENV !== 'production') {
+            warn(("Type of token '" + (token.type) + "' and format of value '" + mode + "' don't match!"));
+          }
+        }
+        break
+      case 'unknown':
+        if (process.env.NODE_ENV !== 'production') {
+          warn("Detect 'unknown' type of token!");
+        }
+        break
+    }
+    index++;
+  }
+
+  return compiled
+}
+
+/*  */
+
+/**
+ *  Path parser
+ *  - Inspired:
+ *    Vue.js Path parser
+ */
+
+// actions
+var APPEND = 0;
+var PUSH = 1;
+var INC_SUB_PATH_DEPTH = 2;
+var PUSH_SUB_PATH = 3;
+
+// states
+var BEFORE_PATH = 0;
+var IN_PATH = 1;
+var BEFORE_IDENT = 2;
+var IN_IDENT = 3;
+var IN_SUB_PATH = 4;
+var IN_SINGLE_QUOTE = 5;
+var IN_DOUBLE_QUOTE = 6;
+var AFTER_PATH = 7;
+var ERROR = 8;
+
+var pathStateMachine = [];
+
+pathStateMachine[BEFORE_PATH] = {
+  'ws': [BEFORE_PATH],
+  'ident': [IN_IDENT, APPEND],
+  '[': [IN_SUB_PATH],
+  'eof': [AFTER_PATH]
+};
+
+pathStateMachine[IN_PATH] = {
+  'ws': [IN_PATH],
+  '.': [BEFORE_IDENT],
+  '[': [IN_SUB_PATH],
+  'eof': [AFTER_PATH]
+};
+
+pathStateMachine[BEFORE_IDENT] = {
+  'ws': [BEFORE_IDENT],
+  'ident': [IN_IDENT, APPEND],
+  '0': [IN_IDENT, APPEND],
+  'number': [IN_IDENT, APPEND]
+};
+
+pathStateMachine[IN_IDENT] = {
+  'ident': [IN_IDENT, APPEND],
+  '0': [IN_IDENT, APPEND],
+  'number': [IN_IDENT, APPEND],
+  'ws': [IN_PATH, PUSH],
+  '.': [BEFORE_IDENT, PUSH],
+  '[': [IN_SUB_PATH, PUSH],
+  'eof': [AFTER_PATH, PUSH]
+};
+
+pathStateMachine[IN_SUB_PATH] = {
+  "'": [IN_SINGLE_QUOTE, APPEND],
+  '"': [IN_DOUBLE_QUOTE, APPEND],
+  '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH],
+  ']': [IN_PATH, PUSH_SUB_PATH],
+  'eof': ERROR,
+  'else': [IN_SUB_PATH, APPEND]
+};
+
+pathStateMachine[IN_SINGLE_QUOTE] = {
+  "'": [IN_SUB_PATH, APPEND],
+  'eof': ERROR,
+  'else': [IN_SINGLE_QUOTE, APPEND]
+};
+
+pathStateMachine[IN_DOUBLE_QUOTE] = {
+  '"': [IN_SUB_PATH, APPEND],
+  'eof': ERROR,
+  'else': [IN_DOUBLE_QUOTE, APPEND]
+};
+
+/**
+ * Check if an expression is a literal value.
+ */
+
+var literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
+function isLiteral (exp) {
+  return literalValueRE.test(exp)
+}
+
+/**
+ * Strip quotes from a string
+ */
+
+function stripQuotes (str) {
+  var a = str.charCodeAt(0);
+  var b = str.charCodeAt(str.length - 1);
+  return a === b && (a === 0x22 || a === 0x27)
+    ? str.slice(1, -1)
+    : str
+}
+
+/**
+ * Determine the type of a character in a keypath.
+ */
+
+function getPathCharType (ch) {
+  if (ch === undefined || ch === null) { return 'eof' }
+
+  var code = ch.charCodeAt(0);
+
+  switch (code) {
+    case 0x5B: // [
+    case 0x5D: // ]
+    case 0x2E: // .
+    case 0x22: // "
+    case 0x27: // '
+      return ch
+
+    case 0x5F: // _
+    case 0x24: // $
+    case 0x2D: // -
+      return 'ident'
+
+    case 0x09: // Tab
+    case 0x0A: // Newline
+    case 0x0D: // Return
+    case 0xA0:  // No-break space
+    case 0xFEFF:  // Byte Order Mark
+    case 0x2028:  // Line Separator
+    case 0x2029:  // Paragraph Separator
+      return 'ws'
+  }
+
+  return 'ident'
+}
+
+/**
+ * Format a subPath, return its plain form if it is
+ * a literal string or number. Otherwise prepend the
+ * dynamic indicator (*).
+ */
+
+function formatSubPath (path) {
+  var trimmed = path.trim();
+  // invalid leading 0
+  if (path.charAt(0) === '0' && isNaN(path)) { return false }
+
+  return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed
+}
+
+/**
+ * Parse a string path into an array of segments
+ */
+
+function parse$1 (path) {
+  var keys = [];
+  var index = -1;
+  var mode = BEFORE_PATH;
+  var subPathDepth = 0;
+  var c;
+  var key;
+  var newChar;
+  var type;
+  var transition;
+  var action;
+  var typeMap;
+  var actions = [];
+
+  actions[PUSH] = function () {
+    if (key !== undefined) {
+      keys.push(key);
+      key = undefined;
+    }
+  };
+
+  actions[APPEND] = function () {
+    if (key === undefined) {
+      key = newChar;
+    } else {
+      key += newChar;
+    }
+  };
+
+  actions[INC_SUB_PATH_DEPTH] = function () {
+    actions[APPEND]();
+    subPathDepth++;
+  };
+
+  actions[PUSH_SUB_PATH] = function () {
+    if (subPathDepth > 0) {
+      subPathDepth--;
+      mode = IN_SUB_PATH;
+      actions[APPEND]();
+    } else {
+      subPathDepth = 0;
+      if (key === undefined) { return false }
+      key = formatSubPath(key);
+      if (key === false) {
+        return false
+      } else {
+        actions[PUSH]();
+      }
+    }
+  };
+
+  function maybeUnescapeQuote () {
+    var nextChar = path[index + 1];
+    if ((mode === IN_SINGLE_QUOTE && nextChar === "'") ||
+      (mode === IN_DOUBLE_QUOTE && nextChar === '"')) {
+      index++;
+      newChar = '\\' + nextChar;
+      actions[APPEND]();
+      return true
+    }
+  }
+
+  while (mode !== null) {
+    index++;
+    c = path[index];
+
+    if (c === '\\' && maybeUnescapeQuote()) {
+      continue
+    }
+
+    type = getPathCharType(c);
+    typeMap = pathStateMachine[mode];
+    transition = typeMap[type] || typeMap['else'] || ERROR;
+
+    if (transition === ERROR) {
+      return // parse error
+    }
+
+    mode = transition[0];
+    action = actions[transition[1]];
+    if (action) {
+      newChar = transition[2];
+      newChar = newChar === undefined
+        ? c
+        : newChar;
+      if (action() === false) {
+        return
+      }
+    }
+
+    if (mode === AFTER_PATH) {
+      return keys
+    }
+  }
+}
+
+
+
+
+
+var I18nPath = function I18nPath () {
+  this._cache = Object.create(null);
+};
+
+/**
+ * External parse that check for a cache hit first
+ */
+I18nPath.prototype.parsePath = function parsePath (path) {
+  var hit = this._cache[path];
+  if (!hit) {
+    hit = parse$1(path);
+    if (hit) {
+      this._cache[path] = hit;
+    }
+  }
+  return hit || []
+};
+
+/**
+ * Get path value from path string
+ */
+I18nPath.prototype.getPathValue = function getPathValue (obj, path) {
+  if (!isObject(obj)) { return null }
+
+  var paths = this.parsePath(path);
+  if (paths.length === 0) {
+    return null
+  } else {
+    var length = paths.length;
+    var last = obj;
+    var i = 0;
+    while (i < length) {
+      var value = last[paths[i]];
+      if (value === undefined) {
+        return null
+      }
+      last = value;
+      i++;
+    }
+
+    return last
+  }
+};
+
+/*  */
+
+
+
+var htmlTagMatcher = /<\/?[\w\s="/.':;#-\/]+>/;
+var linkKeyMatcher = /(?:@(?:\.[a-z]+)?:(?:[\w\-_|.]+|\([\w\-_|.]+\)))/g;
+var linkKeyPrefixMatcher = /^@(?:\.([a-z]+))?:/;
+var bracketsMatcher = /[()]/g;
+var defaultModifiers = {
+  'upper': function (str) { return str.toLocaleUpperCase(); },
+  'lower': function (str) { return str.toLocaleLowerCase(); },
+  'capitalize': function (str) { return ("" + (str.charAt(0).toLocaleUpperCase()) + (str.substr(1))); }
+};
+
+var defaultFormatter = new BaseFormatter();
+
+var VueI18n = function VueI18n (options) {
+  var this$1 = this;
+  if ( options === void 0 ) options = {};
+
+  // Auto install if it is not done yet and `window` has `Vue`.
+  // To allow users to avoid auto-installation in some cases,
+  // this code should be placed here. See #290
+  /* istanbul ignore if */
+  if (!Vue && typeof window !== 'undefined' && window.Vue) {
+    install(window.Vue);
+  }
+
+  var locale = options.locale || 'en-US';
+  var fallbackLocale = options.fallbackLocale === false
+    ? false
+    : options.fallbackLocale || 'en-US';
+  var messages = options.messages || {};
+  var dateTimeFormats = options.dateTimeFormats || {};
+  var numberFormats = options.numberFormats || {};
+
+  this._vm = null;
+  this._formatter = options.formatter || defaultFormatter;
+  this._modifiers = options.modifiers || {};
+  this._missing = options.missing || null;
+  this._root = options.root || null;
+  this._sync = options.sync === undefined ? true : !!options.sync;
+  this._fallbackRoot = options.fallbackRoot === undefined
+    ? true
+    : !!options.fallbackRoot;
+  this._formatFallbackMessages = options.formatFallbackMessages === undefined
+    ? false
+    : !!options.formatFallbackMessages;
+  this._silentTranslationWarn = options.silentTranslationWarn === undefined
+    ? false
+    : options.silentTranslationWarn;
+  this._silentFallbackWarn = options.silentFallbackWarn === undefined
+    ? false
+    : !!options.silentFallbackWarn;
+  this._dateTimeFormatters = {};
+  this._numberFormatters = {};
+  this._path = new I18nPath();
+  this._dataListeners = [];
+  this._componentInstanceCreatedListener = options.componentInstanceCreatedListener || null;
+  this._preserveDirectiveContent = options.preserveDirectiveContent === undefined
+    ? false
+    : !!options.preserveDirectiveContent;
+  this.pluralizationRules = options.pluralizationRules || {};
+  this._warnHtmlInMessage = options.warnHtmlInMessage || 'off';
+  this._postTranslation = options.postTranslation || null;
+
+  /**
+   * @param choice {number} a choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)`
+   * @param choicesLength {number} an overall amount of available choices
+   * @returns a final choice index
+  */
+  this.getChoiceIndex = function (choice, choicesLength) {
+    var thisPrototype = Object.getPrototypeOf(this$1);
+    if (thisPrototype && thisPrototype.getChoiceIndex) {
+      var prototypeGetChoiceIndex = (thisPrototype.getChoiceIndex);
+      return (prototypeGetChoiceIndex).call(this$1, choice, choicesLength)
+    }
+
+    // Default (old) getChoiceIndex implementation - english-compatible
+    var defaultImpl = function (_choice, _choicesLength) {
+      _choice = Math.abs(_choice);
+
+      if (_choicesLength === 2) {
+        return _choice
+          ? _choice > 1
+            ? 1
+            : 0
+          : 1
+      }
+
+      return _choice ? Math.min(_choice, 2) : 0
+    };
+
+    if (this$1.locale in this$1.pluralizationRules) {
+      return this$1.pluralizationRules[this$1.locale].apply(this$1, [choice, choicesLength])
+    } else {
+      return defaultImpl(choice, choicesLength)
+    }
+  };
+
+
+  this._exist = function (message, key) {
+    if (!message || !key) { return false }
+    if (!isNull(this$1._path.getPathValue(message, key))) { return true }
+    // fallback for flat key
+    if (message[key]) { return true }
+    return false
+  };
+
+  if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+    Object.keys(messages).forEach(function (locale) {
+      this$1._checkLocaleMessage(locale, this$1._warnHtmlInMessage, messages[locale]);
+    });
+  }
+
+  this._initVM({
+    locale: locale,
+    fallbackLocale: fallbackLocale,
+    messages: messages,
+    dateTimeFormats: dateTimeFormats,
+    numberFormats: numberFormats
+  });
+};
+
+var prototypeAccessors = { vm: { configurable: true },messages: { configurable: true },dateTimeFormats: { configurable: true },numberFormats: { configurable: true },availableLocales: { configurable: true },locale: { configurable: true },fallbackLocale: { configurable: true },formatFallbackMessages: { configurable: true },missing: { configurable: true },formatter: { configurable: true },silentTranslationWarn: { configurable: true },silentFallbackWarn: { configurable: true },preserveDirectiveContent: { configurable: true },warnHtmlInMessage: { configurable: true },postTranslation: { configurable: true } };
+
+VueI18n.prototype._checkLocaleMessage = function _checkLocaleMessage (locale, level, message) {
+  var paths = [];
+
+  var fn = function (level, locale, message, paths) {
+    if (isPlainObject(message)) {
+      Object.keys(message).forEach(function (key) {
+        var val = message[key];
+        if (isPlainObject(val)) {
+          paths.push(key);
+          paths.push('.');
+          fn(level, locale, val, paths);
+          paths.pop();
+          paths.pop();
+        } else {
+          paths.push(key);
+          fn(level, locale, val, paths);
+          paths.pop();
+        }
+      });
+    } else if (isArray(message)) {
+      message.forEach(function (item, index) {
+        if (isPlainObject(item)) {
+          paths.push(("[" + index + "]"));
+          paths.push('.');
+          fn(level, locale, item, paths);
+          paths.pop();
+          paths.pop();
+        } else {
+          paths.push(("[" + index + "]"));
+          fn(level, locale, item, paths);
+          paths.pop();
+        }
+      });
+    } else if (isString(message)) {
+      var ret = htmlTagMatcher.test(message);
+      if (ret) {
+        var msg = "Detected HTML in message '" + message + "' of keypath '" + (paths.join('')) + "' at '" + locale + "'. Consider component interpolation with '<i18n>' to avoid XSS. See https://bit.ly/2ZqJzkp";
+        if (level === 'warn') {
+          warn(msg);
+        } else if (level === 'error') {
+          error(msg);
+        }
+      }
+    }
+  };
+
+  fn(level, locale, message, paths);
+};
+
+VueI18n.prototype._initVM = function _initVM (data) {
+  var silent = Vue.config.silent;
+  Vue.config.silent = true;
+  this._vm = new Vue({ data: data });
+  Vue.config.silent = silent;
+};
+
+VueI18n.prototype.destroyVM = function destroyVM () {
+  this._vm.$destroy();
+};
+
+VueI18n.prototype.subscribeDataChanging = function subscribeDataChanging (vm) {
+  this._dataListeners.push(vm);
+};
+
+VueI18n.prototype.unsubscribeDataChanging = function unsubscribeDataChanging (vm) {
+  remove(this._dataListeners, vm);
+};
+
+VueI18n.prototype.watchI18nData = function watchI18nData () {
+  var self = this;
+  return this._vm.$watch('$data', function () {
+    var i = self._dataListeners.length;
+    while (i--) {
+      Vue.nextTick(function () {
+        self._dataListeners[i] && self._dataListeners[i].$forceUpdate();
+      });
+    }
+  }, { deep: true })
+};
+
+VueI18n.prototype.watchLocale = function watchLocale () {
+  /* istanbul ignore if */
+  if (!this._sync || !this._root) { return null }
+  var target = this._vm;
+  return this._root.$i18n.vm.$watch('locale', function (val) {
+    target.$set(target, 'locale', val);
+    target.$forceUpdate();
+  }, { immediate: true })
+};
+
+VueI18n.prototype.onComponentInstanceCreated = function onComponentInstanceCreated (newI18n) {
+  if (this._componentInstanceCreatedListener) {
+    this._componentInstanceCreatedListener(newI18n, this);
+  }
+};
+
+prototypeAccessors.vm.get = function () { return this._vm };
+
+prototypeAccessors.messages.get = function () { return looseClone(this._getMessages()) };
+prototypeAccessors.dateTimeFormats.get = function () { return looseClone(this._getDateTimeFormats()) };
+prototypeAccessors.numberFormats.get = function () { return looseClone(this._getNumberFormats()) };
+prototypeAccessors.availableLocales.get = function () { return Object.keys(this.messages).sort() };
+
+prototypeAccessors.locale.get = function () { return this._vm.locale };
+prototypeAccessors.locale.set = function (locale) {
+  this._vm.$set(this._vm, 'locale', locale);
+};
+
+prototypeAccessors.fallbackLocale.get = function () { return this._vm.fallbackLocale };
+prototypeAccessors.fallbackLocale.set = function (locale) {
+  this._localeChainCache = {};
+  this._vm.$set(this._vm, 'fallbackLocale', locale);
+};
+
+prototypeAccessors.formatFallbackMessages.get = function () { return this._formatFallbackMessages };
+prototypeAccessors.formatFallbackMessages.set = function (fallback) { this._formatFallbackMessages = fallback; };
+
+prototypeAccessors.missing.get = function () { return this._missing };
+prototypeAccessors.missing.set = function (handler) { this._missing = handler; };
+
+prototypeAccessors.formatter.get = function () { return this._formatter };
+prototypeAccessors.formatter.set = function (formatter) { this._formatter = formatter; };
+
+prototypeAccessors.silentTranslationWarn.get = function () { return this._silentTranslationWarn };
+prototypeAccessors.silentTranslationWarn.set = function (silent) { this._silentTranslationWarn = silent; };
+
+prototypeAccessors.silentFallbackWarn.get = function () { return this._silentFallbackWarn };
+prototypeAccessors.silentFallbackWarn.set = function (silent) { this._silentFallbackWarn = silent; };
+
+prototypeAccessors.preserveDirectiveContent.get = function () { return this._preserveDirectiveContent };
+prototypeAccessors.preserveDirectiveContent.set = function (preserve) { this._preserveDirectiveContent = preserve; };
+
+prototypeAccessors.warnHtmlInMessage.get = function () { return this._warnHtmlInMessage };
+prototypeAccessors.warnHtmlInMessage.set = function (level) {
+    var this$1 = this;
+
+  var orgLevel = this._warnHtmlInMessage;
+  this._warnHtmlInMessage = level;
+  if (orgLevel !== level && (level === 'warn' || level === 'error')) {
+    var messages = this._getMessages();
+    Object.keys(messages).forEach(function (locale) {
+      this$1._checkLocaleMessage(locale, this$1._warnHtmlInMessage, messages[locale]);
+    });
+  }
+};
+
+prototypeAccessors.postTranslation.get = function () { return this._postTranslation };
+prototypeAccessors.postTranslation.set = function (handler) { this._postTranslation = handler; };
+
+VueI18n.prototype._getMessages = function _getMessages () { return this._vm.messages };
+VueI18n.prototype._getDateTimeFormats = function _getDateTimeFormats () { return this._vm.dateTimeFormats };
+VueI18n.prototype._getNumberFormats = function _getNumberFormats () { return this._vm.numberFormats };
+
+VueI18n.prototype._warnDefault = function _warnDefault (locale, key, result, vm, values, interpolateMode) {
+  if (!isNull(result)) { return result }
+  if (this._missing) {
+    var missingRet = this._missing.apply(null, [locale, key, vm, values]);
+    if (isString(missingRet)) {
+      return missingRet
+    }
+  } else {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key)) {
+      warn(
+        "Cannot translate the value of keypath '" + key + "'. " +
+        'Use the value of keypath as default.'
+      );
+    }
+  }
+
+  if (this._formatFallbackMessages) {
+    var parsedArgs = parseArgs.apply(void 0, values);
+    return this._render(key, interpolateMode, parsedArgs.params, key)
+  } else {
+    return key
+  }
+};
+
+VueI18n.prototype._isFallbackRoot = function _isFallbackRoot (val) {
+  return !val && !isNull(this._root) && this._fallbackRoot
+};
+
+VueI18n.prototype._isSilentFallbackWarn = function _isSilentFallbackWarn (key) {
+  return this._silentFallbackWarn instanceof RegExp
+    ? this._silentFallbackWarn.test(key)
+    : this._silentFallbackWarn
+};
+
+VueI18n.prototype._isSilentFallback = function _isSilentFallback (locale, key) {
+  return this._isSilentFallbackWarn(key) && (this._isFallbackRoot() || locale !== this.fallbackLocale)
+};
+
+VueI18n.prototype._isSilentTranslationWarn = function _isSilentTranslationWarn (key) {
+  return this._silentTranslationWarn instanceof RegExp
+    ? this._silentTranslationWarn.test(key)
+    : this._silentTranslationWarn
+};
+
+VueI18n.prototype._interpolate = function _interpolate (
+  locale,
+  message,
+  key,
+  host,
+  interpolateMode,
+  values,
+  visitedLinkStack
+) {
+  if (!message) { return null }
+
+  var pathRet = this._path.getPathValue(message, key);
+  if (isArray(pathRet) || isPlainObject(pathRet)) { return pathRet }
+
+  var ret;
+  if (isNull(pathRet)) {
+    /* istanbul ignore else */
+    if (isPlainObject(message)) {
+      ret = message[key];
+      if (!(isString(ret) || isFunction(ret))) {
+        if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
+          warn(("Value of key '" + key + "' is not a string or function !"));
+        }
+        return null
+      }
+    } else {
+      return null
+    }
+  } else {
+    /* istanbul ignore else */
+    if (isString(pathRet) || isFunction(pathRet)) {
+      ret = pathRet;
+    } else {
+      if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
+        warn(("Value of key '" + key + "' is not a string or function!"));
+      }
+      return null
+    }
+  }
+
+  // Check for the existence of links within the translated string
+  if (isString(ret) && (ret.indexOf('@:') >= 0 || ret.indexOf('@.') >= 0)) {
+    ret = this._link(locale, message, ret, host, 'raw', values, visitedLinkStack);
+  }
+
+  return this._render(ret, interpolateMode, values, key)
+};
+
+VueI18n.prototype._link = function _link (
+  locale,
+  message,
+  str,
+  host,
+  interpolateMode,
+  values,
+  visitedLinkStack
+) {
+  var ret = str;
+
+  // Match all the links within the local
+  // We are going to replace each of
+  // them with its translation
+  var matches = ret.match(linkKeyMatcher);
+  for (var idx in matches) {
+    // ie compatible: filter custom array
+    // prototype method
+    if (!matches.hasOwnProperty(idx)) {
+      continue
+    }
+    var link = matches[idx];
+    var linkKeyPrefixMatches = link.match(linkKeyPrefixMatcher);
+    var linkPrefix = linkKeyPrefixMatches[0];
+      var formatterName = linkKeyPrefixMatches[1];
+
+    // Remove the leading @:, @.case: and the brackets
+    var linkPlaceholder = link.replace(linkPrefix, '').replace(bracketsMatcher, '');
+
+    if (includes(visitedLinkStack, linkPlaceholder)) {
+      if (process.env.NODE_ENV !== 'production') {
+        warn(("Circular reference found. \"" + link + "\" is already visited in the chain of " + (visitedLinkStack.reverse().join(' <- '))));
+      }
+      return ret
+    }
+    visitedLinkStack.push(linkPlaceholder);
+
+    // Translate the link
+    var translated = this._interpolate(
+      locale, message, linkPlaceholder, host,
+      interpolateMode === 'raw' ? 'string' : interpolateMode,
+      interpolateMode === 'raw' ? undefined : values,
+      visitedLinkStack
+    );
+
+    if (this._isFallbackRoot(translated)) {
+      if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(linkPlaceholder)) {
+        warn(("Fall back to translate the link placeholder '" + linkPlaceholder + "' with root locale."));
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      var root = this._root.$i18n;
+      translated = root._translate(
+        root._getMessages(), root.locale, root.fallbackLocale,
+        linkPlaceholder, host, interpolateMode, values
+      );
+    }
+    translated = this._warnDefault(
+      locale, linkPlaceholder, translated, host,
+      isArray(values) ? values : [values],
+      interpolateMode
+    );
+
+    if (this._modifiers.hasOwnProperty(formatterName)) {
+      translated = this._modifiers[formatterName](translated);
+    } else if (defaultModifiers.hasOwnProperty(formatterName)) {
+      translated = defaultModifiers[formatterName](translated);
+    }
+
+    visitedLinkStack.pop();
+
+    // Replace the link with the translated
+    ret = !translated ? ret : ret.replace(link, translated);
+  }
+
+  return ret
+};
+
+VueI18n.prototype._createMessageContext = function _createMessageContext (values) {
+  var _list = isArray(values) ? values : [];
+  var _named = isObject(values) ? values : {};
+  var list = function (index) { return _list[index]; };
+  var named = function (key) { return _named[key]; };
+  return {
+    list: list,
+    named: named
+  }
+};
+
+VueI18n.prototype._render = function _render (message, interpolateMode, values, path) {
+  if (isFunction(message)) {
+    return message(this._createMessageContext(values))
+  }
+
+  var ret = this._formatter.interpolate(message, values, path);
+
+  // If the custom formatter refuses to work - apply the default one
+  if (!ret) {
+    ret = defaultFormatter.interpolate(message, values, path);
+  }
+
+  // if interpolateMode is **not** 'string' ('row'),
+  // return the compiled data (e.g. ['foo', VNode, 'bar']) with formatter
+  return interpolateMode === 'string' && !isString(ret) ? ret.join('') : ret
+};
+
+VueI18n.prototype._appendItemToChain = function _appendItemToChain (chain, item, blocks) {
+  var follow = false;
+  if (!includes(chain, item)) {
+    follow = true;
+    if (item) {
+      follow = item[item.length - 1] !== '!';
+      item = item.replace(/!/g, '');
+      chain.push(item);
+      if (blocks && blocks[item]) {
+        follow = blocks[item];
+      }
+    }
+  }
+  return follow
+};
+
+VueI18n.prototype._appendLocaleToChain = function _appendLocaleToChain (chain, locale, blocks) {
+  var follow;
+  var tokens = locale.split('-');
+  do {
+    var item = tokens.join('-');
+    follow = this._appendItemToChain(chain, item, blocks);
+    tokens.splice(-1, 1);
+  } while (tokens.length && (follow === true))
+  return follow
+};
+
+VueI18n.prototype._appendBlockToChain = function _appendBlockToChain (chain, block, blocks) {
+  var follow = true;
+  for (var i = 0; (i < block.length) && (isBoolean(follow)); i++) {
+    var locale = block[i];
+    if (isString(locale)) {
+      follow = this._appendLocaleToChain(chain, locale, blocks);
+    }
+  }
+  return follow
+};
+
+VueI18n.prototype._getLocaleChain = function _getLocaleChain (start, fallbackLocale) {
+  if (start === '') { return [] }
+
+  if (!this._localeChainCache) {
+    this._localeChainCache = {};
+  }
+
+  var chain = this._localeChainCache[start];
+  if (!chain) {
+    if (!fallbackLocale) {
+      fallbackLocale = this.fallbackLocale;
+    }
+    chain = [];
+
+    // first block defined by start
+    var block = [start];
+
+    // while any intervening block found
+    while (isArray(block)) {
+      block = this._appendBlockToChain(
+        chain,
+        block,
+        fallbackLocale
+      );
+    }
+
+    // last block defined by default
+    var defaults;
+    if (isArray(fallbackLocale)) {
+      defaults = fallbackLocale;
+    } else if (isObject(fallbackLocale)) {
+      /* $FlowFixMe */
+      if (fallbackLocale['default']) {
+        defaults = fallbackLocale['default'];
+      } else {
+        defaults = null;
+      }
+    } else {
+      defaults = fallbackLocale;
+    }
+
+    // convert defaults to array
+    if (isString(defaults)) {
+      block = [defaults];
+    } else {
+      block = defaults;
+    }
+    if (block) {
+      this._appendBlockToChain(
+        chain,
+        block,
+        null
+      );
+    }
+    this._localeChainCache[start] = chain;
+  }
+  return chain
+};
+
+VueI18n.prototype._translate = function _translate (
+  messages,
+  locale,
+  fallback,
+  key,
+  host,
+  interpolateMode,
+  args
+) {
+  var chain = this._getLocaleChain(locale, fallback);
+  var res;
+  for (var i = 0; i < chain.length; i++) {
+    var step = chain[i];
+    res =
+      this._interpolate(step, messages[step], key, host, interpolateMode, args, [key]);
+    if (!isNull(res)) {
+      if (step !== locale && process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(("Fall back to translate the keypath '" + key + "' with '" + step + "' locale."));
+      }
+      return res
+    }
+  }
+  return null
+};
+
+VueI18n.prototype._t = function _t (key, _locale, messages, host) {
+    var ref;
+
+    var values = [], len = arguments.length - 4;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 4 ];
+  if (!key) { return '' }
+
+  var parsedArgs = parseArgs.apply(void 0, values);
+  var locale = parsedArgs.locale || _locale;
+
+  var ret = this._translate(
+    messages, locale, this.fallbackLocale, key,
+    host, 'string', parsedArgs.params
+  );
+  if (this._isFallbackRoot(ret)) {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+      warn(("Fall back to translate the keypath '" + key + "' with root locale."));
+    }
+    /* istanbul ignore if */
+    if (!this._root) { throw Error('unexpected error') }
+    return (ref = this._root).$t.apply(ref, [ key ].concat( values ))
+  } else {
+    ret = this._warnDefault(locale, key, ret, host, values, 'string');
+    if (this._postTranslation && ret !== null && ret !== undefined) {
+      ret = this._postTranslation(ret, key);
+    }
+    return ret
+  }
+};
+
+VueI18n.prototype.t = function t (key) {
+    var ref;
+
+    var values = [], len = arguments.length - 1;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 1 ];
+  return (ref = this)._t.apply(ref, [ key, this.locale, this._getMessages(), null ].concat( values ))
+};
+
+VueI18n.prototype._i = function _i (key, locale, messages, host, values) {
+  var ret =
+    this._translate(messages, locale, this.fallbackLocale, key, host, 'raw', values);
+  if (this._isFallbackRoot(ret)) {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key)) {
+      warn(("Fall back to interpolate the keypath '" + key + "' with root locale."));
+    }
+    if (!this._root) { throw Error('unexpected error') }
+    return this._root.$i18n.i(key, locale, values)
+  } else {
+    return this._warnDefault(locale, key, ret, host, [values], 'raw')
+  }
+};
+
+VueI18n.prototype.i = function i (key, locale, values) {
+  /* istanbul ignore if */
+  if (!key) { return '' }
+
+  if (!isString(locale)) {
+    locale = this.locale;
+  }
+
+  return this._i(key, locale, this._getMessages(), null, values)
+};
+
+VueI18n.prototype._tc = function _tc (
+  key,
+  _locale,
+  messages,
+  host,
+  choice
+) {
+    var ref;
+
+    var values = [], len = arguments.length - 5;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 5 ];
+  if (!key) { return '' }
+  if (choice === undefined) {
+    choice = 1;
+  }
+
+  var predefined = { 'count': choice, 'n': choice };
+  var parsedArgs = parseArgs.apply(void 0, values);
+  parsedArgs.params = Object.assign(predefined, parsedArgs.params);
+  values = parsedArgs.locale === null ? [parsedArgs.params] : [parsedArgs.locale, parsedArgs.params];
+  return this.fetchChoice((ref = this)._t.apply(ref, [ key, _locale, messages, host ].concat( values )), choice)
+};
+
+VueI18n.prototype.fetchChoice = function fetchChoice (message, choice) {
+  /* istanbul ignore if */
+  if (!message && !isString(message)) { return null }
+  var choices = message.split('|');
+
+  choice = this.getChoiceIndex(choice, choices.length);
+  if (!choices[choice]) { return message }
+  return choices[choice].trim()
+};
+
+VueI18n.prototype.tc = function tc (key, choice) {
+    var ref;
+
+    var values = [], len = arguments.length - 2;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 2 ];
+  return (ref = this)._tc.apply(ref, [ key, this.locale, this._getMessages(), null, choice ].concat( values ))
+};
+
+VueI18n.prototype._te = function _te (key, locale, messages) {
+    var args = [], len = arguments.length - 3;
+    while ( len-- > 0 ) args[ len ] = arguments[ len + 3 ];
+
+  var _locale = parseArgs.apply(void 0, args).locale || locale;
+  return this._exist(messages[_locale], key)
+};
+
+VueI18n.prototype.te = function te (key, locale) {
+  return this._te(key, this.locale, this._getMessages(), locale)
+};
+
+VueI18n.prototype.getLocaleMessage = function getLocaleMessage (locale) {
+  return looseClone(this._vm.messages[locale] || {})
+};
+
+VueI18n.prototype.setLocaleMessage = function setLocaleMessage (locale, message) {
+  if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+    this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
+  }
+  this._vm.$set(this._vm.messages, locale, message);
+};
+
+VueI18n.prototype.mergeLocaleMessage = function mergeLocaleMessage (locale, message) {
+  if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+    this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
+  }
+  this._vm.$set(this._vm.messages, locale, merge({}, this._vm.messages[locale] || {}, message));
+};
+
+VueI18n.prototype.getDateTimeFormat = function getDateTimeFormat (locale) {
+  return looseClone(this._vm.dateTimeFormats[locale] || {})
+};
+
+VueI18n.prototype.setDateTimeFormat = function setDateTimeFormat (locale, format) {
+  this._vm.$set(this._vm.dateTimeFormats, locale, format);
+  this._clearDateTimeFormat(locale, format);
+};
+
+VueI18n.prototype.mergeDateTimeFormat = function mergeDateTimeFormat (locale, format) {
+  this._vm.$set(this._vm.dateTimeFormats, locale, merge(this._vm.dateTimeFormats[locale] || {}, format));
+  this._clearDateTimeFormat(locale, format);
+};
+
+VueI18n.prototype._clearDateTimeFormat = function _clearDateTimeFormat (locale, format) {
+  for (var key in format) {
+    var id = locale + "__" + key;
+
+    if (!this._dateTimeFormatters.hasOwnProperty(id)) {
+      continue
+    }
+
+    delete this._dateTimeFormatters[id];
+  }
+};
+
+VueI18n.prototype._localizeDateTime = function _localizeDateTime (
+  value,
+  locale,
+  fallback,
+  dateTimeFormats,
+  key
+) {
+  var _locale = locale;
+  var formats = dateTimeFormats[_locale];
+
+  var chain = this._getLocaleChain(locale, fallback);
+  for (var i = 0; i < chain.length; i++) {
+    var current = _locale;
+    var step = chain[i];
+    formats = dateTimeFormats[step];
+    _locale = step;
+    // fallback locale
+    if (isNull(formats) || isNull(formats[key])) {
+      if (step !== locale && process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(("Fall back to '" + step + "' datetime formats from '" + current + "' datetime formats."));
+      }
+    } else {
+      break
+    }
+  }
+
+  if (isNull(formats) || isNull(formats[key])) {
+    return null
+  } else {
+    var format = formats[key];
+    var id = _locale + "__" + key;
+    var formatter = this._dateTimeFormatters[id];
+    if (!formatter) {
+      formatter = this._dateTimeFormatters[id] = new Intl.DateTimeFormat(_locale, format);
+    }
+    return formatter.format(value)
+  }
+};
+
+VueI18n.prototype._d = function _d (value, locale, key) {
+  /* istanbul ignore if */
+  if (process.env.NODE_ENV !== 'production' && !VueI18n.availabilities.dateTimeFormat) {
+    warn('Cannot format a Date value due to not supported Intl.DateTimeFormat.');
+    return ''
+  }
+
+  if (!key) {
+    return new Intl.DateTimeFormat(locale).format(value)
+  }
+
+  var ret =
+    this._localizeDateTime(value, locale, this.fallbackLocale, this._getDateTimeFormats(), key);
+  if (this._isFallbackRoot(ret)) {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+      warn(("Fall back to datetime localization of root: key '" + key + "'."));
+    }
+    /* istanbul ignore if */
+    if (!this._root) { throw Error('unexpected error') }
+    return this._root.$i18n.d(value, key, locale)
+  } else {
+    return ret || ''
+  }
+};
+
+VueI18n.prototype.d = function d (value) {
+    var args = [], len = arguments.length - 1;
+    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+
+  var locale = this.locale;
+  var key = null;
+
+  if (args.length === 1) {
+    if (isString(args[0])) {
+      key = args[0];
+    } else if (isObject(args[0])) {
+      if (args[0].locale) {
+        locale = args[0].locale;
+      }
+      if (args[0].key) {
+        key = args[0].key;
+      }
+    }
+  } else if (args.length === 2) {
+    if (isString(args[0])) {
+      key = args[0];
+    }
+    if (isString(args[1])) {
+      locale = args[1];
+    }
+  }
+
+  return this._d(value, locale, key)
+};
+
+VueI18n.prototype.getNumberFormat = function getNumberFormat (locale) {
+  return looseClone(this._vm.numberFormats[locale] || {})
+};
+
+VueI18n.prototype.setNumberFormat = function setNumberFormat (locale, format) {
+  this._vm.$set(this._vm.numberFormats, locale, format);
+  this._clearNumberFormat(locale, format);
+};
+
+VueI18n.prototype.mergeNumberFormat = function mergeNumberFormat (locale, format) {
+  this._vm.$set(this._vm.numberFormats, locale, merge(this._vm.numberFormats[locale] || {}, format));
+  this._clearNumberFormat(locale, format);
+};
+
+VueI18n.prototype._clearNumberFormat = function _clearNumberFormat (locale, format) {
+  for (var key in format) {
+    var id = locale + "__" + key;
+
+    if (!this._numberFormatters.hasOwnProperty(id)) {
+      continue
+    }
+
+    delete this._numberFormatters[id];
+  }
+};
+
+VueI18n.prototype._getNumberFormatter = function _getNumberFormatter (
+  value,
+  locale,
+  fallback,
+  numberFormats,
+  key,
+  options
+) {
+  var _locale = locale;
+  var formats = numberFormats[_locale];
+
+  var chain = this._getLocaleChain(locale, fallback);
+  for (var i = 0; i < chain.length; i++) {
+    var current = _locale;
+    var step = chain[i];
+    formats = numberFormats[step];
+    _locale = step;
+    // fallback locale
+    if (isNull(formats) || isNull(formats[key])) {
+      if (step !== locale && process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(("Fall back to '" + step + "' number formats from '" + current + "' number formats."));
+      }
+    } else {
+      break
+    }
+  }
+
+  if (isNull(formats) || isNull(formats[key])) {
+    return null
+  } else {
+    var format = formats[key];
+
+    var formatter;
+    if (options) {
+      // If options specified - create one time number formatter
+      formatter = new Intl.NumberFormat(_locale, Object.assign({}, format, options));
+    } else {
+      var id = _locale + "__" + key;
+      formatter = this._numberFormatters[id];
+      if (!formatter) {
+        formatter = this._numberFormatters[id] = new Intl.NumberFormat(_locale, format);
+      }
+    }
+    return formatter
+  }
+};
+
+VueI18n.prototype._n = function _n (value, locale, key, options) {
+  /* istanbul ignore if */
+  if (!VueI18n.availabilities.numberFormat) {
+    if (process.env.NODE_ENV !== 'production') {
+      warn('Cannot format a Number value due to not supported Intl.NumberFormat.');
+    }
+    return ''
+  }
+
+  if (!key) {
+    var nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
+    return nf.format(value)
+  }
+
+  var formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
+  var ret = formatter && formatter.format(value);
+  if (this._isFallbackRoot(ret)) {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+      warn(("Fall back to number localization of root: key '" + key + "'."));
+    }
+    /* istanbul ignore if */
+    if (!this._root) { throw Error('unexpected error') }
+    return this._root.$i18n.n(value, Object.assign({}, { key: key, locale: locale }, options))
+  } else {
+    return ret || ''
+  }
+};
+
+VueI18n.prototype.n = function n (value) {
+    var args = [], len = arguments.length - 1;
+    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+
+  var locale = this.locale;
+  var key = null;
+  var options = null;
+
+  if (args.length === 1) {
+    if (isString(args[0])) {
+      key = args[0];
+    } else if (isObject(args[0])) {
+      if (args[0].locale) {
+        locale = args[0].locale;
+      }
+      if (args[0].key) {
+        key = args[0].key;
+      }
+
+      // Filter out number format options only
+      options = Object.keys(args[0]).reduce(function (acc, key) {
+          var obj;
+
+        if (includes(numberFormatKeys, key)) {
+          return Object.assign({}, acc, ( obj = {}, obj[key] = args[0][key], obj ))
+        }
+        return acc
+      }, null);
+    }
+  } else if (args.length === 2) {
+    if (isString(args[0])) {
+      key = args[0];
+    }
+    if (isString(args[1])) {
+      locale = args[1];
+    }
+  }
+
+  return this._n(value, locale, key, options)
+};
+
+VueI18n.prototype._ntp = function _ntp (value, locale, key, options) {
+  /* istanbul ignore if */
+  if (!VueI18n.availabilities.numberFormat) {
+    if (process.env.NODE_ENV !== 'production') {
+      warn('Cannot format to parts a Number value due to not supported Intl.NumberFormat.');
+    }
+    return []
+  }
+
+  if (!key) {
+    var nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
+    return nf.formatToParts(value)
+  }
+
+  var formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
+  var ret = formatter && formatter.formatToParts(value);
+  if (this._isFallbackRoot(ret)) {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key)) {
+      warn(("Fall back to format number to parts of root: key '" + key + "' ."));
+    }
+    /* istanbul ignore if */
+    if (!this._root) { throw Error('unexpected error') }
+    return this._root.$i18n._ntp(value, locale, key, options)
+  } else {
+    return ret || []
+  }
+};
+
+Object.defineProperties( VueI18n.prototype, prototypeAccessors );
+
+var availabilities;
+// $FlowFixMe
+Object.defineProperty(VueI18n, 'availabilities', {
+  get: function get () {
+    if (!availabilities) {
+      var intlDefined = typeof Intl !== 'undefined';
+      availabilities = {
+        dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
+        numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
+      };
+    }
+
+    return availabilities
+  }
+});
+
+VueI18n.install = install;
+VueI18n.version = '8.21.0';
+
+module.exports = VueI18n;

+ 2104 - 0
plugin/vue-i18n/dist/vue-i18n.esm.browser.js

@@ -0,0 +1,2104 @@
+/*  */
+
+/**
+ * constants
+ */
+
+const numberFormatKeys = [
+  'style',
+  'currency',
+  'currencyDisplay',
+  'useGrouping',
+  'minimumIntegerDigits',
+  'minimumFractionDigits',
+  'maximumFractionDigits',
+  'minimumSignificantDigits',
+  'maximumSignificantDigits',
+  'localeMatcher',
+  'formatMatcher',
+  'unit'
+];
+
+/**
+ * utilities
+ */
+
+function warn (msg, err) {
+  if (typeof console !== 'undefined') {
+    console.warn('[vue-i18n] ' + msg);
+    /* istanbul ignore if */
+    if (err) {
+      console.warn(err.stack);
+    }
+  }
+}
+
+function error (msg, err) {
+  if (typeof console !== 'undefined') {
+    console.error('[vue-i18n] ' + msg);
+    /* istanbul ignore if */
+    if (err) {
+      console.error(err.stack);
+    }
+  }
+}
+
+const isArray = Array.isArray;
+
+function isObject (obj) {
+  return obj !== null && typeof obj === 'object'
+}
+
+function isBoolean (val) {
+  return typeof val === 'boolean'
+}
+
+function isString (val) {
+  return typeof val === 'string'
+}
+
+const toString = Object.prototype.toString;
+const OBJECT_STRING = '[object Object]';
+function isPlainObject (obj) {
+  return toString.call(obj) === OBJECT_STRING
+}
+
+function isNull (val) {
+  return val === null || val === undefined
+}
+
+function isFunction (val) {
+  return typeof val === 'function'
+}
+
+function parseArgs (...args) {
+  let locale = null;
+  let params = null;
+  if (args.length === 1) {
+    if (isObject(args[0]) || isArray(args[0])) {
+      params = args[0];
+    } else if (typeof args[0] === 'string') {
+      locale = args[0];
+    }
+  } else if (args.length === 2) {
+    if (typeof args[0] === 'string') {
+      locale = args[0];
+    }
+    /* istanbul ignore if */
+    if (isObject(args[1]) || isArray(args[1])) {
+      params = args[1];
+    }
+  }
+
+  return { locale, params }
+}
+
+function looseClone (obj) {
+  return JSON.parse(JSON.stringify(obj))
+}
+
+function remove (arr, item) {
+  if (arr.length) {
+    const index = arr.indexOf(item);
+    if (index > -1) {
+      return arr.splice(index, 1)
+    }
+  }
+}
+
+function includes (arr, item) {
+  return !!~arr.indexOf(item)
+}
+
+const hasOwnProperty = Object.prototype.hasOwnProperty;
+function hasOwn (obj, key) {
+  return hasOwnProperty.call(obj, key)
+}
+
+function merge (target) {
+  const output = Object(target);
+  for (let i = 1; i < arguments.length; i++) {
+    const source = arguments[i];
+    if (source !== undefined && source !== null) {
+      let key;
+      for (key in source) {
+        if (hasOwn(source, key)) {
+          if (isObject(source[key])) {
+            output[key] = merge(output[key], source[key]);
+          } else {
+            output[key] = source[key];
+          }
+        }
+      }
+    }
+  }
+  return output
+}
+
+function looseEqual (a, b) {
+  if (a === b) { return true }
+  const isObjectA = isObject(a);
+  const isObjectB = isObject(b);
+  if (isObjectA && isObjectB) {
+    try {
+      const isArrayA = isArray(a);
+      const isArrayB = isArray(b);
+      if (isArrayA && isArrayB) {
+        return a.length === b.length && a.every((e, i) => {
+          return looseEqual(e, b[i])
+        })
+      } else if (!isArrayA && !isArrayB) {
+        const keysA = Object.keys(a);
+        const keysB = Object.keys(b);
+        return keysA.length === keysB.length && keysA.every((key) => {
+          return looseEqual(a[key], b[key])
+        })
+      } else {
+        /* istanbul ignore next */
+        return false
+      }
+    } catch (e) {
+      /* istanbul ignore next */
+      return false
+    }
+  } else if (!isObjectA && !isObjectB) {
+    return String(a) === String(b)
+  } else {
+    return false
+  }
+}
+
+/*  */
+
+function extend (Vue) {
+  if (!Vue.prototype.hasOwnProperty('$i18n')) {
+    // $FlowFixMe
+    Object.defineProperty(Vue.prototype, '$i18n', {
+      get () { return this._i18n }
+    });
+  }
+
+  Vue.prototype.$t = function (key, ...values) {
+    const i18n = this.$i18n;
+    return i18n._t(key, i18n.locale, i18n._getMessages(), this, ...values)
+  };
+
+  Vue.prototype.$tc = function (key, choice, ...values) {
+    const i18n = this.$i18n;
+    return i18n._tc(key, i18n.locale, i18n._getMessages(), this, choice, ...values)
+  };
+
+  Vue.prototype.$te = function (key, locale) {
+    const i18n = this.$i18n;
+    return i18n._te(key, i18n.locale, i18n._getMessages(), locale)
+  };
+
+  Vue.prototype.$d = function (value, ...args) {
+    return this.$i18n.d(value, ...args)
+  };
+
+  Vue.prototype.$n = function (value, ...args) {
+    return this.$i18n.n(value, ...args)
+  };
+}
+
+/*  */
+
+var mixin = {
+  beforeCreate () {
+    const options = this.$options;
+    options.i18n = options.i18n || (options.__i18n ? {} : null);
+
+    if (options.i18n) {
+      if (options.i18n instanceof VueI18n) {
+        // init locale messages via custom blocks
+        if (options.__i18n) {
+          try {
+            let localeMessages = {};
+            options.__i18n.forEach(resource => {
+              localeMessages = merge(localeMessages, JSON.parse(resource));
+            });
+            Object.keys(localeMessages).forEach((locale) => {
+              options.i18n.mergeLocaleMessage(locale, localeMessages[locale]);
+            });
+          } catch (e) {
+            {
+              error(`Cannot parse locale messages via custom blocks.`, e);
+            }
+          }
+        }
+        this._i18n = options.i18n;
+        this._i18nWatcher = this._i18n.watchI18nData();
+      } else if (isPlainObject(options.i18n)) {
+        const rootI18n = this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n
+          ? this.$root.$i18n
+          : null;
+        // component local i18n
+        if (rootI18n) {
+          options.i18n.root = this.$root;
+          options.i18n.formatter = rootI18n.formatter;
+          options.i18n.fallbackLocale = rootI18n.fallbackLocale;
+          options.i18n.formatFallbackMessages = rootI18n.formatFallbackMessages;
+          options.i18n.silentTranslationWarn = rootI18n.silentTranslationWarn;
+          options.i18n.silentFallbackWarn = rootI18n.silentFallbackWarn;
+          options.i18n.pluralizationRules = rootI18n.pluralizationRules;
+          options.i18n.preserveDirectiveContent = rootI18n.preserveDirectiveContent;
+        }
+
+        // init locale messages via custom blocks
+        if (options.__i18n) {
+          try {
+            let localeMessages = {};
+            options.__i18n.forEach(resource => {
+              localeMessages = merge(localeMessages, JSON.parse(resource));
+            });
+            options.i18n.messages = localeMessages;
+          } catch (e) {
+            {
+              warn(`Cannot parse locale messages via custom blocks.`, e);
+            }
+          }
+        }
+
+        const { sharedMessages } = options.i18n;
+        if (sharedMessages && isPlainObject(sharedMessages)) {
+          options.i18n.messages = merge(options.i18n.messages, sharedMessages);
+        }
+
+        this._i18n = new VueI18n(options.i18n);
+        this._i18nWatcher = this._i18n.watchI18nData();
+
+        if (options.i18n.sync === undefined || !!options.i18n.sync) {
+          this._localeWatcher = this.$i18n.watchLocale();
+        }
+
+        if (rootI18n) {
+          rootI18n.onComponentInstanceCreated(this._i18n);
+        }
+      } else {
+        {
+          warn(`Cannot be interpreted 'i18n' option.`);
+        }
+      }
+    } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
+      // root i18n
+      this._i18n = this.$root.$i18n;
+    } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
+      // parent i18n
+      this._i18n = options.parent.$i18n;
+    }
+  },
+
+  beforeMount () {
+    const options = this.$options;
+    options.i18n = options.i18n || (options.__i18n ? {} : null);
+
+    if (options.i18n) {
+      if (options.i18n instanceof VueI18n) {
+        // init locale messages via custom blocks
+        this._i18n.subscribeDataChanging(this);
+        this._subscribing = true;
+      } else if (isPlainObject(options.i18n)) {
+        this._i18n.subscribeDataChanging(this);
+        this._subscribing = true;
+      } else {
+        {
+          warn(`Cannot be interpreted 'i18n' option.`);
+        }
+      }
+    } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
+      this._i18n.subscribeDataChanging(this);
+      this._subscribing = true;
+    } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
+      this._i18n.subscribeDataChanging(this);
+      this._subscribing = true;
+    }
+  },
+
+  beforeDestroy () {
+    if (!this._i18n) { return }
+
+    const self = this;
+    this.$nextTick(() => {
+      if (self._subscribing) {
+        self._i18n.unsubscribeDataChanging(self);
+        delete self._subscribing;
+      }
+
+      if (self._i18nWatcher) {
+        self._i18nWatcher();
+        self._i18n.destroyVM();
+        delete self._i18nWatcher;
+      }
+
+      if (self._localeWatcher) {
+        self._localeWatcher();
+        delete self._localeWatcher;
+      }
+    });
+  }
+};
+
+/*  */
+
+var interpolationComponent = {
+  name: 'i18n',
+  functional: true,
+  props: {
+    tag: {
+      type: [String, Boolean, Object],
+      default: 'span'
+    },
+    path: {
+      type: String,
+      required: true
+    },
+    locale: {
+      type: String
+    },
+    places: {
+      type: [Array, Object]
+    }
+  },
+  render (h, { data, parent, props, slots }) {
+    const { $i18n } = parent;
+    if (!$i18n) {
+      {
+        warn('Cannot find VueI18n instance!');
+      }
+      return
+    }
+
+    const { path, locale, places } = props;
+    const params = slots();
+    const children = $i18n.i(
+      path,
+      locale,
+      onlyHasDefaultPlace(params) || places
+        ? useLegacyPlaces(params.default, places)
+        : params
+    );
+
+    const tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span';
+    return tag ? h(tag, data, children) : children
+  }
+};
+
+function onlyHasDefaultPlace (params) {
+  let prop;
+  for (prop in params) {
+    if (prop !== 'default') { return false }
+  }
+  return Boolean(prop)
+}
+
+function useLegacyPlaces (children, places) {
+  const params = places ? createParamsFromPlaces(places) : {};
+
+  if (!children) { return params }
+
+  // Filter empty text nodes
+  children = children.filter(child => {
+    return child.tag || child.text.trim() !== ''
+  });
+
+  const everyPlace = children.every(vnodeHasPlaceAttribute);
+  if (everyPlace) {
+    warn('`place` attribute is deprecated in next major version. Please switch to Vue slots.');
+  }
+
+  return children.reduce(
+    everyPlace ? assignChildPlace : assignChildIndex,
+    params
+  )
+}
+
+function createParamsFromPlaces (places) {
+  {
+    warn('`places` prop is deprecated in next major version. Please switch to Vue slots.');
+  }
+
+  return Array.isArray(places)
+    ? places.reduce(assignChildIndex, {})
+    : Object.assign({}, places)
+}
+
+function assignChildPlace (params, child) {
+  if (child.data && child.data.attrs && child.data.attrs.place) {
+    params[child.data.attrs.place] = child;
+  }
+  return params
+}
+
+function assignChildIndex (params, child, index) {
+  params[index] = child;
+  return params
+}
+
+function vnodeHasPlaceAttribute (vnode) {
+  return Boolean(vnode.data && vnode.data.attrs && vnode.data.attrs.place)
+}
+
+/*  */
+
+var numberComponent = {
+  name: 'i18n-n',
+  functional: true,
+  props: {
+    tag: {
+      type: [String, Boolean, Object],
+      default: 'span'
+    },
+    value: {
+      type: Number,
+      required: true
+    },
+    format: {
+      type: [String, Object]
+    },
+    locale: {
+      type: String
+    }
+  },
+  render (h, { props, parent, data }) {
+    const i18n = parent.$i18n;
+
+    if (!i18n) {
+      {
+        warn('Cannot find VueI18n instance!');
+      }
+      return null
+    }
+
+    let key = null;
+    let options = null;
+
+    if (isString(props.format)) {
+      key = props.format;
+    } else if (isObject(props.format)) {
+      if (props.format.key) {
+        key = props.format.key;
+      }
+
+      // Filter out number format options only
+      options = Object.keys(props.format).reduce((acc, prop) => {
+        if (includes(numberFormatKeys, prop)) {
+          return Object.assign({}, acc, { [prop]: props.format[prop] })
+        }
+        return acc
+      }, null);
+    }
+
+    const locale = props.locale || i18n.locale;
+    const parts = i18n._ntp(props.value, locale, key, options);
+
+    const values = parts.map((part, index) => {
+      const slot = data.scopedSlots && data.scopedSlots[part.type];
+      return slot ? slot({ [part.type]: part.value, index, parts }) : part.value
+    });
+
+    const tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span';
+    return tag
+      ? h(tag, {
+        attrs: data.attrs,
+        'class': data['class'],
+        staticClass: data.staticClass
+      }, values)
+      : values
+  }
+};
+
+/*  */
+
+function bind (el, binding, vnode) {
+  if (!assert(el, vnode)) { return }
+
+  t(el, binding, vnode);
+}
+
+function update (el, binding, vnode, oldVNode) {
+  if (!assert(el, vnode)) { return }
+
+  const i18n = vnode.context.$i18n;
+  if (localeEqual(el, vnode) &&
+    (looseEqual(binding.value, binding.oldValue) &&
+     looseEqual(el._localeMessage, i18n.getLocaleMessage(i18n.locale)))) { return }
+
+  t(el, binding, vnode);
+}
+
+function unbind (el, binding, vnode, oldVNode) {
+  const vm = vnode.context;
+  if (!vm) {
+    warn('Vue instance does not exists in VNode context');
+    return
+  }
+
+  const i18n = vnode.context.$i18n || {};
+  if (!binding.modifiers.preserve && !i18n.preserveDirectiveContent) {
+    el.textContent = '';
+  }
+  el._vt = undefined;
+  delete el['_vt'];
+  el._locale = undefined;
+  delete el['_locale'];
+  el._localeMessage = undefined;
+  delete el['_localeMessage'];
+}
+
+function assert (el, vnode) {
+  const vm = vnode.context;
+  if (!vm) {
+    warn('Vue instance does not exists in VNode context');
+    return false
+  }
+
+  if (!vm.$i18n) {
+    warn('VueI18n instance does not exists in Vue instance');
+    return false
+  }
+
+  return true
+}
+
+function localeEqual (el, vnode) {
+  const vm = vnode.context;
+  return el._locale === vm.$i18n.locale
+}
+
+function t (el, binding, vnode) {
+  const value = binding.value;
+
+  const { path, locale, args, choice } = parseValue(value);
+  if (!path && !locale && !args) {
+    warn('value type not supported');
+    return
+  }
+
+  if (!path) {
+    warn('`path` is required in v-t directive');
+    return
+  }
+
+  const vm = vnode.context;
+  if (choice != null) {
+    el._vt = el.textContent = vm.$i18n.tc(path, choice, ...makeParams(locale, args));
+  } else {
+    el._vt = el.textContent = vm.$i18n.t(path, ...makeParams(locale, args));
+  }
+  el._locale = vm.$i18n.locale;
+  el._localeMessage = vm.$i18n.getLocaleMessage(vm.$i18n.locale);
+}
+
+function parseValue (value) {
+  let path;
+  let locale;
+  let args;
+  let choice;
+
+  if (isString(value)) {
+    path = value;
+  } else if (isPlainObject(value)) {
+    path = value.path;
+    locale = value.locale;
+    args = value.args;
+    choice = value.choice;
+  }
+
+  return { path, locale, args, choice }
+}
+
+function makeParams (locale, args) {
+  const params = [];
+
+  locale && params.push(locale);
+  if (args && (Array.isArray(args) || isPlainObject(args))) {
+    params.push(args);
+  }
+
+  return params
+}
+
+let Vue;
+
+function install (_Vue) {
+  /* istanbul ignore if */
+  if (install.installed && _Vue === Vue) {
+    warn('already installed.');
+    return
+  }
+  install.installed = true;
+
+  Vue = _Vue;
+
+  const version = (Vue.version && Number(Vue.version.split('.')[0])) || -1;
+  /* istanbul ignore if */
+  if (version < 2) {
+    warn(`vue-i18n (${install.version}) need to use Vue 2.0 or later (Vue: ${Vue.version}).`);
+    return
+  }
+
+  extend(Vue);
+  Vue.mixin(mixin);
+  Vue.directive('t', { bind, update, unbind });
+  Vue.component(interpolationComponent.name, interpolationComponent);
+  Vue.component(numberComponent.name, numberComponent);
+
+  // use simple mergeStrategies to prevent i18n instance lose '__proto__'
+  const strats = Vue.config.optionMergeStrategies;
+  strats.i18n = function (parentVal, childVal) {
+    return childVal === undefined
+      ? parentVal
+      : childVal
+  };
+}
+
+/*  */
+
+class BaseFormatter {
+  
+
+  constructor () {
+    this._caches = Object.create(null);
+  }
+
+  interpolate (message, values) {
+    if (!values) {
+      return [message]
+    }
+    let tokens = this._caches[message];
+    if (!tokens) {
+      tokens = parse(message);
+      this._caches[message] = tokens;
+    }
+    return compile(tokens, values)
+  }
+}
+
+
+
+const RE_TOKEN_LIST_VALUE = /^(?:\d)+/;
+const RE_TOKEN_NAMED_VALUE = /^(?:\w)+/;
+
+function parse (format) {
+  const tokens = [];
+  let position = 0;
+
+  let text = '';
+  while (position < format.length) {
+    let char = format[position++];
+    if (char === '{') {
+      if (text) {
+        tokens.push({ type: 'text', value: text });
+      }
+
+      text = '';
+      let sub = '';
+      char = format[position++];
+      while (char !== undefined && char !== '}') {
+        sub += char;
+        char = format[position++];
+      }
+      const isClosed = char === '}';
+
+      const type = RE_TOKEN_LIST_VALUE.test(sub)
+        ? 'list'
+        : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
+          ? 'named'
+          : 'unknown';
+      tokens.push({ value: sub, type });
+    } else if (char === '%') {
+      // when found rails i18n syntax, skip text capture
+      if (format[(position)] !== '{') {
+        text += char;
+      }
+    } else {
+      text += char;
+    }
+  }
+
+  text && tokens.push({ type: 'text', value: text });
+
+  return tokens
+}
+
+function compile (tokens, values) {
+  const compiled = [];
+  let index = 0;
+
+  const mode = Array.isArray(values)
+    ? 'list'
+    : isObject(values)
+      ? 'named'
+      : 'unknown';
+  if (mode === 'unknown') { return compiled }
+
+  while (index < tokens.length) {
+    const token = tokens[index];
+    switch (token.type) {
+      case 'text':
+        compiled.push(token.value);
+        break
+      case 'list':
+        compiled.push(values[parseInt(token.value, 10)]);
+        break
+      case 'named':
+        if (mode === 'named') {
+          compiled.push((values)[token.value]);
+        } else {
+          {
+            warn(`Type of token '${token.type}' and format of value '${mode}' don't match!`);
+          }
+        }
+        break
+      case 'unknown':
+        {
+          warn(`Detect 'unknown' type of token!`);
+        }
+        break
+    }
+    index++;
+  }
+
+  return compiled
+}
+
+/*  */
+
+/**
+ *  Path parser
+ *  - Inspired:
+ *    Vue.js Path parser
+ */
+
+// actions
+const APPEND = 0;
+const PUSH = 1;
+const INC_SUB_PATH_DEPTH = 2;
+const PUSH_SUB_PATH = 3;
+
+// states
+const BEFORE_PATH = 0;
+const IN_PATH = 1;
+const BEFORE_IDENT = 2;
+const IN_IDENT = 3;
+const IN_SUB_PATH = 4;
+const IN_SINGLE_QUOTE = 5;
+const IN_DOUBLE_QUOTE = 6;
+const AFTER_PATH = 7;
+const ERROR = 8;
+
+const pathStateMachine = [];
+
+pathStateMachine[BEFORE_PATH] = {
+  'ws': [BEFORE_PATH],
+  'ident': [IN_IDENT, APPEND],
+  '[': [IN_SUB_PATH],
+  'eof': [AFTER_PATH]
+};
+
+pathStateMachine[IN_PATH] = {
+  'ws': [IN_PATH],
+  '.': [BEFORE_IDENT],
+  '[': [IN_SUB_PATH],
+  'eof': [AFTER_PATH]
+};
+
+pathStateMachine[BEFORE_IDENT] = {
+  'ws': [BEFORE_IDENT],
+  'ident': [IN_IDENT, APPEND],
+  '0': [IN_IDENT, APPEND],
+  'number': [IN_IDENT, APPEND]
+};
+
+pathStateMachine[IN_IDENT] = {
+  'ident': [IN_IDENT, APPEND],
+  '0': [IN_IDENT, APPEND],
+  'number': [IN_IDENT, APPEND],
+  'ws': [IN_PATH, PUSH],
+  '.': [BEFORE_IDENT, PUSH],
+  '[': [IN_SUB_PATH, PUSH],
+  'eof': [AFTER_PATH, PUSH]
+};
+
+pathStateMachine[IN_SUB_PATH] = {
+  "'": [IN_SINGLE_QUOTE, APPEND],
+  '"': [IN_DOUBLE_QUOTE, APPEND],
+  '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH],
+  ']': [IN_PATH, PUSH_SUB_PATH],
+  'eof': ERROR,
+  'else': [IN_SUB_PATH, APPEND]
+};
+
+pathStateMachine[IN_SINGLE_QUOTE] = {
+  "'": [IN_SUB_PATH, APPEND],
+  'eof': ERROR,
+  'else': [IN_SINGLE_QUOTE, APPEND]
+};
+
+pathStateMachine[IN_DOUBLE_QUOTE] = {
+  '"': [IN_SUB_PATH, APPEND],
+  'eof': ERROR,
+  'else': [IN_DOUBLE_QUOTE, APPEND]
+};
+
+/**
+ * Check if an expression is a literal value.
+ */
+
+const literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
+function isLiteral (exp) {
+  return literalValueRE.test(exp)
+}
+
+/**
+ * Strip quotes from a string
+ */
+
+function stripQuotes (str) {
+  const a = str.charCodeAt(0);
+  const b = str.charCodeAt(str.length - 1);
+  return a === b && (a === 0x22 || a === 0x27)
+    ? str.slice(1, -1)
+    : str
+}
+
+/**
+ * Determine the type of a character in a keypath.
+ */
+
+function getPathCharType (ch) {
+  if (ch === undefined || ch === null) { return 'eof' }
+
+  const code = ch.charCodeAt(0);
+
+  switch (code) {
+    case 0x5B: // [
+    case 0x5D: // ]
+    case 0x2E: // .
+    case 0x22: // "
+    case 0x27: // '
+      return ch
+
+    case 0x5F: // _
+    case 0x24: // $
+    case 0x2D: // -
+      return 'ident'
+
+    case 0x09: // Tab
+    case 0x0A: // Newline
+    case 0x0D: // Return
+    case 0xA0:  // No-break space
+    case 0xFEFF:  // Byte Order Mark
+    case 0x2028:  // Line Separator
+    case 0x2029:  // Paragraph Separator
+      return 'ws'
+  }
+
+  return 'ident'
+}
+
+/**
+ * Format a subPath, return its plain form if it is
+ * a literal string or number. Otherwise prepend the
+ * dynamic indicator (*).
+ */
+
+function formatSubPath (path) {
+  const trimmed = path.trim();
+  // invalid leading 0
+  if (path.charAt(0) === '0' && isNaN(path)) { return false }
+
+  return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed
+}
+
+/**
+ * Parse a string path into an array of segments
+ */
+
+function parse$1 (path) {
+  const keys = [];
+  let index = -1;
+  let mode = BEFORE_PATH;
+  let subPathDepth = 0;
+  let c;
+  let key;
+  let newChar;
+  let type;
+  let transition;
+  let action;
+  let typeMap;
+  const actions = [];
+
+  actions[PUSH] = function () {
+    if (key !== undefined) {
+      keys.push(key);
+      key = undefined;
+    }
+  };
+
+  actions[APPEND] = function () {
+    if (key === undefined) {
+      key = newChar;
+    } else {
+      key += newChar;
+    }
+  };
+
+  actions[INC_SUB_PATH_DEPTH] = function () {
+    actions[APPEND]();
+    subPathDepth++;
+  };
+
+  actions[PUSH_SUB_PATH] = function () {
+    if (subPathDepth > 0) {
+      subPathDepth--;
+      mode = IN_SUB_PATH;
+      actions[APPEND]();
+    } else {
+      subPathDepth = 0;
+      if (key === undefined) { return false }
+      key = formatSubPath(key);
+      if (key === false) {
+        return false
+      } else {
+        actions[PUSH]();
+      }
+    }
+  };
+
+  function maybeUnescapeQuote () {
+    const nextChar = path[index + 1];
+    if ((mode === IN_SINGLE_QUOTE && nextChar === "'") ||
+      (mode === IN_DOUBLE_QUOTE && nextChar === '"')) {
+      index++;
+      newChar = '\\' + nextChar;
+      actions[APPEND]();
+      return true
+    }
+  }
+
+  while (mode !== null) {
+    index++;
+    c = path[index];
+
+    if (c === '\\' && maybeUnescapeQuote()) {
+      continue
+    }
+
+    type = getPathCharType(c);
+    typeMap = pathStateMachine[mode];
+    transition = typeMap[type] || typeMap['else'] || ERROR;
+
+    if (transition === ERROR) {
+      return // parse error
+    }
+
+    mode = transition[0];
+    action = actions[transition[1]];
+    if (action) {
+      newChar = transition[2];
+      newChar = newChar === undefined
+        ? c
+        : newChar;
+      if (action() === false) {
+        return
+      }
+    }
+
+    if (mode === AFTER_PATH) {
+      return keys
+    }
+  }
+}
+
+
+
+
+
+class I18nPath {
+  
+
+  constructor () {
+    this._cache = Object.create(null);
+  }
+
+  /**
+   * External parse that check for a cache hit first
+   */
+  parsePath (path) {
+    let hit = this._cache[path];
+    if (!hit) {
+      hit = parse$1(path);
+      if (hit) {
+        this._cache[path] = hit;
+      }
+    }
+    return hit || []
+  }
+
+  /**
+   * Get path value from path string
+   */
+  getPathValue (obj, path) {
+    if (!isObject(obj)) { return null }
+
+    const paths = this.parsePath(path);
+    if (paths.length === 0) {
+      return null
+    } else {
+      const length = paths.length;
+      let last = obj;
+      let i = 0;
+      while (i < length) {
+        const value = last[paths[i]];
+        if (value === undefined) {
+          return null
+        }
+        last = value;
+        i++;
+      }
+
+      return last
+    }
+  }
+}
+
+/*  */
+
+
+
+const htmlTagMatcher = /<\/?[\w\s="/.':;#-\/]+>/;
+const linkKeyMatcher = /(?:@(?:\.[a-z]+)?:(?:[\w\-_|.]+|\([\w\-_|.]+\)))/g;
+const linkKeyPrefixMatcher = /^@(?:\.([a-z]+))?:/;
+const bracketsMatcher = /[()]/g;
+const defaultModifiers = {
+  'upper': str => str.toLocaleUpperCase(),
+  'lower': str => str.toLocaleLowerCase(),
+  'capitalize': str => `${str.charAt(0).toLocaleUpperCase()}${str.substr(1)}`
+};
+
+const defaultFormatter = new BaseFormatter();
+
+class VueI18n {
+  
+  
+  
+
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
+  constructor (options = {}) {
+    // Auto install if it is not done yet and `window` has `Vue`.
+    // To allow users to avoid auto-installation in some cases,
+    // this code should be placed here. See #290
+    /* istanbul ignore if */
+    if (!Vue && typeof window !== 'undefined' && window.Vue) {
+      install(window.Vue);
+    }
+
+    const locale = options.locale || 'en-US';
+    const fallbackLocale = options.fallbackLocale === false
+      ? false
+      : options.fallbackLocale || 'en-US';
+    const messages = options.messages || {};
+    const dateTimeFormats = options.dateTimeFormats || {};
+    const numberFormats = options.numberFormats || {};
+
+    this._vm = null;
+    this._formatter = options.formatter || defaultFormatter;
+    this._modifiers = options.modifiers || {};
+    this._missing = options.missing || null;
+    this._root = options.root || null;
+    this._sync = options.sync === undefined ? true : !!options.sync;
+    this._fallbackRoot = options.fallbackRoot === undefined
+      ? true
+      : !!options.fallbackRoot;
+    this._formatFallbackMessages = options.formatFallbackMessages === undefined
+      ? false
+      : !!options.formatFallbackMessages;
+    this._silentTranslationWarn = options.silentTranslationWarn === undefined
+      ? false
+      : options.silentTranslationWarn;
+    this._silentFallbackWarn = options.silentFallbackWarn === undefined
+      ? false
+      : !!options.silentFallbackWarn;
+    this._dateTimeFormatters = {};
+    this._numberFormatters = {};
+    this._path = new I18nPath();
+    this._dataListeners = [];
+    this._componentInstanceCreatedListener = options.componentInstanceCreatedListener || null;
+    this._preserveDirectiveContent = options.preserveDirectiveContent === undefined
+      ? false
+      : !!options.preserveDirectiveContent;
+    this.pluralizationRules = options.pluralizationRules || {};
+    this._warnHtmlInMessage = options.warnHtmlInMessage || 'off';
+    this._postTranslation = options.postTranslation || null;
+
+    /**
+     * @param choice {number} a choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)`
+     * @param choicesLength {number} an overall amount of available choices
+     * @returns a final choice index
+    */
+    this.getChoiceIndex = (choice, choicesLength) => {
+      const thisPrototype = Object.getPrototypeOf(this);
+      if (thisPrototype && thisPrototype.getChoiceIndex) {
+        const prototypeGetChoiceIndex = (thisPrototype.getChoiceIndex);
+        return (prototypeGetChoiceIndex).call(this, choice, choicesLength)
+      }
+
+      // Default (old) getChoiceIndex implementation - english-compatible
+      const defaultImpl = (_choice, _choicesLength) => {
+        _choice = Math.abs(_choice);
+
+        if (_choicesLength === 2) {
+          return _choice
+            ? _choice > 1
+              ? 1
+              : 0
+            : 1
+        }
+
+        return _choice ? Math.min(_choice, 2) : 0
+      };
+
+      if (this.locale in this.pluralizationRules) {
+        return this.pluralizationRules[this.locale].apply(this, [choice, choicesLength])
+      } else {
+        return defaultImpl(choice, choicesLength)
+      }
+    };
+
+
+    this._exist = (message, key) => {
+      if (!message || !key) { return false }
+      if (!isNull(this._path.getPathValue(message, key))) { return true }
+      // fallback for flat key
+      if (message[key]) { return true }
+      return false
+    };
+
+    if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+      Object.keys(messages).forEach(locale => {
+        this._checkLocaleMessage(locale, this._warnHtmlInMessage, messages[locale]);
+      });
+    }
+
+    this._initVM({
+      locale,
+      fallbackLocale,
+      messages,
+      dateTimeFormats,
+      numberFormats
+    });
+  }
+
+  _checkLocaleMessage (locale, level, message) {
+    const paths = [];
+
+    const fn = (level, locale, message, paths) => {
+      if (isPlainObject(message)) {
+        Object.keys(message).forEach(key => {
+          const val = message[key];
+          if (isPlainObject(val)) {
+            paths.push(key);
+            paths.push('.');
+            fn(level, locale, val, paths);
+            paths.pop();
+            paths.pop();
+          } else {
+            paths.push(key);
+            fn(level, locale, val, paths);
+            paths.pop();
+          }
+        });
+      } else if (isArray(message)) {
+        message.forEach((item, index) => {
+          if (isPlainObject(item)) {
+            paths.push(`[${index}]`);
+            paths.push('.');
+            fn(level, locale, item, paths);
+            paths.pop();
+            paths.pop();
+          } else {
+            paths.push(`[${index}]`);
+            fn(level, locale, item, paths);
+            paths.pop();
+          }
+        });
+      } else if (isString(message)) {
+        const ret = htmlTagMatcher.test(message);
+        if (ret) {
+          const msg = `Detected HTML in message '${message}' of keypath '${paths.join('')}' at '${locale}'. Consider component interpolation with '<i18n>' to avoid XSS. See https://bit.ly/2ZqJzkp`;
+          if (level === 'warn') {
+            warn(msg);
+          } else if (level === 'error') {
+            error(msg);
+          }
+        }
+      }
+    };
+
+    fn(level, locale, message, paths);
+  }
+
+  _initVM (data) {
+    const silent = Vue.config.silent;
+    Vue.config.silent = true;
+    this._vm = new Vue({ data });
+    Vue.config.silent = silent;
+  }
+
+  destroyVM () {
+    this._vm.$destroy();
+  }
+
+  subscribeDataChanging (vm) {
+    this._dataListeners.push(vm);
+  }
+
+  unsubscribeDataChanging (vm) {
+    remove(this._dataListeners, vm);
+  }
+
+  watchI18nData () {
+    const self = this;
+    return this._vm.$watch('$data', () => {
+      let i = self._dataListeners.length;
+      while (i--) {
+        Vue.nextTick(() => {
+          self._dataListeners[i] && self._dataListeners[i].$forceUpdate();
+        });
+      }
+    }, { deep: true })
+  }
+
+  watchLocale () {
+    /* istanbul ignore if */
+    if (!this._sync || !this._root) { return null }
+    const target = this._vm;
+    return this._root.$i18n.vm.$watch('locale', (val) => {
+      target.$set(target, 'locale', val);
+      target.$forceUpdate();
+    }, { immediate: true })
+  }
+
+  onComponentInstanceCreated (newI18n) {
+    if (this._componentInstanceCreatedListener) {
+      this._componentInstanceCreatedListener(newI18n, this);
+    }
+  }
+
+  get vm () { return this._vm }
+
+  get messages () { return looseClone(this._getMessages()) }
+  get dateTimeFormats () { return looseClone(this._getDateTimeFormats()) }
+  get numberFormats () { return looseClone(this._getNumberFormats()) }
+  get availableLocales () { return Object.keys(this.messages).sort() }
+
+  get locale () { return this._vm.locale }
+  set locale (locale) {
+    this._vm.$set(this._vm, 'locale', locale);
+  }
+
+  get fallbackLocale () { return this._vm.fallbackLocale }
+  set fallbackLocale (locale) {
+    this._localeChainCache = {};
+    this._vm.$set(this._vm, 'fallbackLocale', locale);
+  }
+
+  get formatFallbackMessages () { return this._formatFallbackMessages }
+  set formatFallbackMessages (fallback) { this._formatFallbackMessages = fallback; }
+
+  get missing () { return this._missing }
+  set missing (handler) { this._missing = handler; }
+
+  get formatter () { return this._formatter }
+  set formatter (formatter) { this._formatter = formatter; }
+
+  get silentTranslationWarn () { return this._silentTranslationWarn }
+  set silentTranslationWarn (silent) { this._silentTranslationWarn = silent; }
+
+  get silentFallbackWarn () { return this._silentFallbackWarn }
+  set silentFallbackWarn (silent) { this._silentFallbackWarn = silent; }
+
+  get preserveDirectiveContent () { return this._preserveDirectiveContent }
+  set preserveDirectiveContent (preserve) { this._preserveDirectiveContent = preserve; }
+
+  get warnHtmlInMessage () { return this._warnHtmlInMessage }
+  set warnHtmlInMessage (level) {
+    const orgLevel = this._warnHtmlInMessage;
+    this._warnHtmlInMessage = level;
+    if (orgLevel !== level && (level === 'warn' || level === 'error')) {
+      const messages = this._getMessages();
+      Object.keys(messages).forEach(locale => {
+        this._checkLocaleMessage(locale, this._warnHtmlInMessage, messages[locale]);
+      });
+    }
+  }
+
+  get postTranslation () { return this._postTranslation }
+  set postTranslation (handler) { this._postTranslation = handler; }
+
+  _getMessages () { return this._vm.messages }
+  _getDateTimeFormats () { return this._vm.dateTimeFormats }
+  _getNumberFormats () { return this._vm.numberFormats }
+
+  _warnDefault (locale, key, result, vm, values, interpolateMode) {
+    if (!isNull(result)) { return result }
+    if (this._missing) {
+      const missingRet = this._missing.apply(null, [locale, key, vm, values]);
+      if (isString(missingRet)) {
+        return missingRet
+      }
+    } else {
+      if (!this._isSilentTranslationWarn(key)) {
+        warn(
+          `Cannot translate the value of keypath '${key}'. ` +
+          'Use the value of keypath as default.'
+        );
+      }
+    }
+
+    if (this._formatFallbackMessages) {
+      const parsedArgs = parseArgs(...values);
+      return this._render(key, interpolateMode, parsedArgs.params, key)
+    } else {
+      return key
+    }
+  }
+
+  _isFallbackRoot (val) {
+    return !val && !isNull(this._root) && this._fallbackRoot
+  }
+
+  _isSilentFallbackWarn (key) {
+    return this._silentFallbackWarn instanceof RegExp
+      ? this._silentFallbackWarn.test(key)
+      : this._silentFallbackWarn
+  }
+
+  _isSilentFallback (locale, key) {
+    return this._isSilentFallbackWarn(key) && (this._isFallbackRoot() || locale !== this.fallbackLocale)
+  }
+
+  _isSilentTranslationWarn (key) {
+    return this._silentTranslationWarn instanceof RegExp
+      ? this._silentTranslationWarn.test(key)
+      : this._silentTranslationWarn
+  }
+
+  _interpolate (
+    locale,
+    message,
+    key,
+    host,
+    interpolateMode,
+    values,
+    visitedLinkStack
+  ) {
+    if (!message) { return null }
+
+    const pathRet = this._path.getPathValue(message, key);
+    if (isArray(pathRet) || isPlainObject(pathRet)) { return pathRet }
+
+    let ret;
+    if (isNull(pathRet)) {
+      /* istanbul ignore else */
+      if (isPlainObject(message)) {
+        ret = message[key];
+        if (!(isString(ret) || isFunction(ret))) {
+          if (!this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
+            warn(`Value of key '${key}' is not a string or function !`);
+          }
+          return null
+        }
+      } else {
+        return null
+      }
+    } else {
+      /* istanbul ignore else */
+      if (isString(pathRet) || isFunction(pathRet)) {
+        ret = pathRet;
+      } else {
+        if (!this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
+          warn(`Value of key '${key}' is not a string or function!`);
+        }
+        return null
+      }
+    }
+
+    // Check for the existence of links within the translated string
+    if (isString(ret) && (ret.indexOf('@:') >= 0 || ret.indexOf('@.') >= 0)) {
+      ret = this._link(locale, message, ret, host, 'raw', values, visitedLinkStack);
+    }
+
+    return this._render(ret, interpolateMode, values, key)
+  }
+
+  _link (
+    locale,
+    message,
+    str,
+    host,
+    interpolateMode,
+    values,
+    visitedLinkStack
+  ) {
+    let ret = str;
+
+    // Match all the links within the local
+    // We are going to replace each of
+    // them with its translation
+    const matches = ret.match(linkKeyMatcher);
+    for (let idx in matches) {
+      // ie compatible: filter custom array
+      // prototype method
+      if (!matches.hasOwnProperty(idx)) {
+        continue
+      }
+      const link = matches[idx];
+      const linkKeyPrefixMatches = link.match(linkKeyPrefixMatcher);
+      const [linkPrefix, formatterName] = linkKeyPrefixMatches;
+
+      // Remove the leading @:, @.case: and the brackets
+      const linkPlaceholder = link.replace(linkPrefix, '').replace(bracketsMatcher, '');
+
+      if (includes(visitedLinkStack, linkPlaceholder)) {
+        {
+          warn(`Circular reference found. "${link}" is already visited in the chain of ${visitedLinkStack.reverse().join(' <- ')}`);
+        }
+        return ret
+      }
+      visitedLinkStack.push(linkPlaceholder);
+
+      // Translate the link
+      let translated = this._interpolate(
+        locale, message, linkPlaceholder, host,
+        interpolateMode === 'raw' ? 'string' : interpolateMode,
+        interpolateMode === 'raw' ? undefined : values,
+        visitedLinkStack
+      );
+
+      if (this._isFallbackRoot(translated)) {
+        if (!this._isSilentTranslationWarn(linkPlaceholder)) {
+          warn(`Fall back to translate the link placeholder '${linkPlaceholder}' with root locale.`);
+        }
+        /* istanbul ignore if */
+        if (!this._root) { throw Error('unexpected error') }
+        const root = this._root.$i18n;
+        translated = root._translate(
+          root._getMessages(), root.locale, root.fallbackLocale,
+          linkPlaceholder, host, interpolateMode, values
+        );
+      }
+      translated = this._warnDefault(
+        locale, linkPlaceholder, translated, host,
+        isArray(values) ? values : [values],
+        interpolateMode
+      );
+
+      if (this._modifiers.hasOwnProperty(formatterName)) {
+        translated = this._modifiers[formatterName](translated);
+      } else if (defaultModifiers.hasOwnProperty(formatterName)) {
+        translated = defaultModifiers[formatterName](translated);
+      }
+
+      visitedLinkStack.pop();
+
+      // Replace the link with the translated
+      ret = !translated ? ret : ret.replace(link, translated);
+    }
+
+    return ret
+  }
+
+  _createMessageContext (values) {
+    const _list = isArray(values) ? values : [];
+    const _named = isObject(values) ? values : {};
+    const list = (index) => _list[index];
+    const named = (key) => _named[key];
+    return {
+      list,
+      named
+    }
+  }
+
+  _render (message, interpolateMode, values, path) {
+    if (isFunction(message)) {
+      return message(this._createMessageContext(values))
+    }
+
+    let ret = this._formatter.interpolate(message, values, path);
+
+    // If the custom formatter refuses to work - apply the default one
+    if (!ret) {
+      ret = defaultFormatter.interpolate(message, values, path);
+    }
+
+    // if interpolateMode is **not** 'string' ('row'),
+    // return the compiled data (e.g. ['foo', VNode, 'bar']) with formatter
+    return interpolateMode === 'string' && !isString(ret) ? ret.join('') : ret
+  }
+
+  _appendItemToChain (chain, item, blocks) {
+    let follow = false;
+    if (!includes(chain, item)) {
+      follow = true;
+      if (item) {
+        follow = item[item.length - 1] !== '!';
+        item = item.replace(/!/g, '');
+        chain.push(item);
+        if (blocks && blocks[item]) {
+          follow = blocks[item];
+        }
+      }
+    }
+    return follow
+  }
+
+  _appendLocaleToChain (chain, locale, blocks) {
+    let follow;
+    const tokens = locale.split('-');
+    do {
+      const item = tokens.join('-');
+      follow = this._appendItemToChain(chain, item, blocks);
+      tokens.splice(-1, 1);
+    } while (tokens.length && (follow === true))
+    return follow
+  }
+
+  _appendBlockToChain (chain, block, blocks) {
+    let follow = true;
+    for (let i = 0; (i < block.length) && (isBoolean(follow)); i++) {
+      const locale = block[i];
+      if (isString(locale)) {
+        follow = this._appendLocaleToChain(chain, locale, blocks);
+      }
+    }
+    return follow
+  }
+
+  _getLocaleChain (start, fallbackLocale) {
+    if (start === '') { return [] }
+
+    if (!this._localeChainCache) {
+      this._localeChainCache = {};
+    }
+
+    let chain = this._localeChainCache[start];
+    if (!chain) {
+      if (!fallbackLocale) {
+        fallbackLocale = this.fallbackLocale;
+      }
+      chain = [];
+
+      // first block defined by start
+      let block = [start];
+
+      // while any intervening block found
+      while (isArray(block)) {
+        block = this._appendBlockToChain(
+          chain,
+          block,
+          fallbackLocale
+        );
+      }
+
+      // last block defined by default
+      let defaults;
+      if (isArray(fallbackLocale)) {
+        defaults = fallbackLocale;
+      } else if (isObject(fallbackLocale)) {
+        /* $FlowFixMe */
+        if (fallbackLocale['default']) {
+          defaults = fallbackLocale['default'];
+        } else {
+          defaults = null;
+        }
+      } else {
+        defaults = fallbackLocale;
+      }
+
+      // convert defaults to array
+      if (isString(defaults)) {
+        block = [defaults];
+      } else {
+        block = defaults;
+      }
+      if (block) {
+        this._appendBlockToChain(
+          chain,
+          block,
+          null
+        );
+      }
+      this._localeChainCache[start] = chain;
+    }
+    return chain
+  }
+
+  _translate (
+    messages,
+    locale,
+    fallback,
+    key,
+    host,
+    interpolateMode,
+    args
+  ) {
+    const chain = this._getLocaleChain(locale, fallback);
+    let res;
+    for (let i = 0; i < chain.length; i++) {
+      const step = chain[i];
+      res =
+        this._interpolate(step, messages[step], key, host, interpolateMode, args, [key]);
+      if (!isNull(res)) {
+        if (step !== locale && "development" !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+          warn(("Fall back to translate the keypath '" + key + "' with '" + step + "' locale."));
+        }
+        return res
+      }
+    }
+    return null
+  }
+
+  _t (key, _locale, messages, host, ...values) {
+    if (!key) { return '' }
+
+    const parsedArgs = parseArgs(...values);
+    const locale = parsedArgs.locale || _locale;
+
+    let ret = this._translate(
+      messages, locale, this.fallbackLocale, key,
+      host, 'string', parsedArgs.params
+    );
+    if (this._isFallbackRoot(ret)) {
+      if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(`Fall back to translate the keypath '${key}' with root locale.`);
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$t(key, ...values)
+    } else {
+      ret = this._warnDefault(locale, key, ret, host, values, 'string');
+      if (this._postTranslation && ret !== null && ret !== undefined) {
+        ret = this._postTranslation(ret, key);
+      }
+      return ret
+    }
+  }
+
+  t (key, ...values) {
+    return this._t(key, this.locale, this._getMessages(), null, ...values)
+  }
+
+  _i (key, locale, messages, host, values) {
+    const ret =
+      this._translate(messages, locale, this.fallbackLocale, key, host, 'raw', values);
+    if (this._isFallbackRoot(ret)) {
+      if (!this._isSilentTranslationWarn(key)) {
+        warn(`Fall back to interpolate the keypath '${key}' with root locale.`);
+      }
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n.i(key, locale, values)
+    } else {
+      return this._warnDefault(locale, key, ret, host, [values], 'raw')
+    }
+  }
+
+  i (key, locale, values) {
+    /* istanbul ignore if */
+    if (!key) { return '' }
+
+    if (!isString(locale)) {
+      locale = this.locale;
+    }
+
+    return this._i(key, locale, this._getMessages(), null, values)
+  }
+
+  _tc (
+    key,
+    _locale,
+    messages,
+    host,
+    choice,
+    ...values
+  ) {
+    if (!key) { return '' }
+    if (choice === undefined) {
+      choice = 1;
+    }
+
+    const predefined = { 'count': choice, 'n': choice };
+    const parsedArgs = parseArgs(...values);
+    parsedArgs.params = Object.assign(predefined, parsedArgs.params);
+    values = parsedArgs.locale === null ? [parsedArgs.params] : [parsedArgs.locale, parsedArgs.params];
+    return this.fetchChoice(this._t(key, _locale, messages, host, ...values), choice)
+  }
+
+  fetchChoice (message, choice) {
+    /* istanbul ignore if */
+    if (!message && !isString(message)) { return null }
+    const choices = message.split('|');
+
+    choice = this.getChoiceIndex(choice, choices.length);
+    if (!choices[choice]) { return message }
+    return choices[choice].trim()
+  }
+
+  tc (key, choice, ...values) {
+    return this._tc(key, this.locale, this._getMessages(), null, choice, ...values)
+  }
+
+  _te (key, locale, messages, ...args) {
+    const _locale = parseArgs(...args).locale || locale;
+    return this._exist(messages[_locale], key)
+  }
+
+  te (key, locale) {
+    return this._te(key, this.locale, this._getMessages(), locale)
+  }
+
+  getLocaleMessage (locale) {
+    return looseClone(this._vm.messages[locale] || {})
+  }
+
+  setLocaleMessage (locale, message) {
+    if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+      this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
+    }
+    this._vm.$set(this._vm.messages, locale, message);
+  }
+
+  mergeLocaleMessage (locale, message) {
+    if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+      this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
+    }
+    this._vm.$set(this._vm.messages, locale, merge({}, this._vm.messages[locale] || {}, message));
+  }
+
+  getDateTimeFormat (locale) {
+    return looseClone(this._vm.dateTimeFormats[locale] || {})
+  }
+
+  setDateTimeFormat (locale, format) {
+    this._vm.$set(this._vm.dateTimeFormats, locale, format);
+    this._clearDateTimeFormat(locale, format);
+  }
+
+  mergeDateTimeFormat (locale, format) {
+    this._vm.$set(this._vm.dateTimeFormats, locale, merge(this._vm.dateTimeFormats[locale] || {}, format));
+    this._clearDateTimeFormat(locale, format);
+  }
+
+  _clearDateTimeFormat (locale, format) {
+    for (let key in format) {
+      const id = `${locale}__${key}`;
+
+      if (!this._dateTimeFormatters.hasOwnProperty(id)) {
+        continue
+      }
+
+      delete this._dateTimeFormatters[id];
+    }
+  }
+
+  _localizeDateTime (
+    value,
+    locale,
+    fallback,
+    dateTimeFormats,
+    key
+  ) {
+    let _locale = locale;
+    let formats = dateTimeFormats[_locale];
+
+    const chain = this._getLocaleChain(locale, fallback);
+    for (let i = 0; i < chain.length; i++) {
+      const current = _locale;
+      const step = chain[i];
+      formats = dateTimeFormats[step];
+      _locale = step;
+      // fallback locale
+      if (isNull(formats) || isNull(formats[key])) {
+        if (step !== locale && "development" !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+          warn(`Fall back to '${step}' datetime formats from '${current}' datetime formats.`);
+        }
+      } else {
+        break
+      }
+    }
+
+    if (isNull(formats) || isNull(formats[key])) {
+      return null
+    } else {
+      const format = formats[key];
+      const id = `${_locale}__${key}`;
+      let formatter = this._dateTimeFormatters[id];
+      if (!formatter) {
+        formatter = this._dateTimeFormatters[id] = new Intl.DateTimeFormat(_locale, format);
+      }
+      return formatter.format(value)
+    }
+  }
+
+  _d (value, locale, key) {
+    /* istanbul ignore if */
+    if (!VueI18n.availabilities.dateTimeFormat) {
+      warn('Cannot format a Date value due to not supported Intl.DateTimeFormat.');
+      return ''
+    }
+
+    if (!key) {
+      return new Intl.DateTimeFormat(locale).format(value)
+    }
+
+    const ret =
+      this._localizeDateTime(value, locale, this.fallbackLocale, this._getDateTimeFormats(), key);
+    if (this._isFallbackRoot(ret)) {
+      if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(`Fall back to datetime localization of root: key '${key}'.`);
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n.d(value, key, locale)
+    } else {
+      return ret || ''
+    }
+  }
+
+  d (value, ...args) {
+    let locale = this.locale;
+    let key = null;
+
+    if (args.length === 1) {
+      if (isString(args[0])) {
+        key = args[0];
+      } else if (isObject(args[0])) {
+        if (args[0].locale) {
+          locale = args[0].locale;
+        }
+        if (args[0].key) {
+          key = args[0].key;
+        }
+      }
+    } else if (args.length === 2) {
+      if (isString(args[0])) {
+        key = args[0];
+      }
+      if (isString(args[1])) {
+        locale = args[1];
+      }
+    }
+
+    return this._d(value, locale, key)
+  }
+
+  getNumberFormat (locale) {
+    return looseClone(this._vm.numberFormats[locale] || {})
+  }
+
+  setNumberFormat (locale, format) {
+    this._vm.$set(this._vm.numberFormats, locale, format);
+    this._clearNumberFormat(locale, format);
+  }
+
+  mergeNumberFormat (locale, format) {
+    this._vm.$set(this._vm.numberFormats, locale, merge(this._vm.numberFormats[locale] || {}, format));
+    this._clearNumberFormat(locale, format);
+  }
+
+  _clearNumberFormat (locale, format) {
+    for (let key in format) {
+      const id = `${locale}__${key}`;
+
+      if (!this._numberFormatters.hasOwnProperty(id)) {
+        continue
+      }
+
+      delete this._numberFormatters[id];
+    }
+  }
+
+  _getNumberFormatter (
+    value,
+    locale,
+    fallback,
+    numberFormats,
+    key,
+    options
+  ) {
+    let _locale = locale;
+    let formats = numberFormats[_locale];
+
+    const chain = this._getLocaleChain(locale, fallback);
+    for (let i = 0; i < chain.length; i++) {
+      const current = _locale;
+      const step = chain[i];
+      formats = numberFormats[step];
+      _locale = step;
+      // fallback locale
+      if (isNull(formats) || isNull(formats[key])) {
+        if (step !== locale && "development" !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+          warn(`Fall back to '${step}' number formats from '${current}' number formats.`);
+        }
+      } else {
+        break
+      }
+    }
+
+    if (isNull(formats) || isNull(formats[key])) {
+      return null
+    } else {
+      const format = formats[key];
+
+      let formatter;
+      if (options) {
+        // If options specified - create one time number formatter
+        formatter = new Intl.NumberFormat(_locale, Object.assign({}, format, options));
+      } else {
+        const id = `${_locale}__${key}`;
+        formatter = this._numberFormatters[id];
+        if (!formatter) {
+          formatter = this._numberFormatters[id] = new Intl.NumberFormat(_locale, format);
+        }
+      }
+      return formatter
+    }
+  }
+
+  _n (value, locale, key, options) {
+    /* istanbul ignore if */
+    if (!VueI18n.availabilities.numberFormat) {
+      {
+        warn('Cannot format a Number value due to not supported Intl.NumberFormat.');
+      }
+      return ''
+    }
+
+    if (!key) {
+      const nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
+      return nf.format(value)
+    }
+
+    const formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
+    const ret = formatter && formatter.format(value);
+    if (this._isFallbackRoot(ret)) {
+      if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(`Fall back to number localization of root: key '${key}'.`);
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n.n(value, Object.assign({}, { key, locale }, options))
+    } else {
+      return ret || ''
+    }
+  }
+
+  n (value, ...args) {
+    let locale = this.locale;
+    let key = null;
+    let options = null;
+
+    if (args.length === 1) {
+      if (isString(args[0])) {
+        key = args[0];
+      } else if (isObject(args[0])) {
+        if (args[0].locale) {
+          locale = args[0].locale;
+        }
+        if (args[0].key) {
+          key = args[0].key;
+        }
+
+        // Filter out number format options only
+        options = Object.keys(args[0]).reduce((acc, key) => {
+          if (includes(numberFormatKeys, key)) {
+            return Object.assign({}, acc, { [key]: args[0][key] })
+          }
+          return acc
+        }, null);
+      }
+    } else if (args.length === 2) {
+      if (isString(args[0])) {
+        key = args[0];
+      }
+      if (isString(args[1])) {
+        locale = args[1];
+      }
+    }
+
+    return this._n(value, locale, key, options)
+  }
+
+  _ntp (value, locale, key, options) {
+    /* istanbul ignore if */
+    if (!VueI18n.availabilities.numberFormat) {
+      {
+        warn('Cannot format to parts a Number value due to not supported Intl.NumberFormat.');
+      }
+      return []
+    }
+
+    if (!key) {
+      const nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
+      return nf.formatToParts(value)
+    }
+
+    const formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
+    const ret = formatter && formatter.formatToParts(value);
+    if (this._isFallbackRoot(ret)) {
+      if (!this._isSilentTranslationWarn(key)) {
+        warn(`Fall back to format number to parts of root: key '${key}' .`);
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n._ntp(value, locale, key, options)
+    } else {
+      return ret || []
+    }
+  }
+}
+
+let availabilities;
+// $FlowFixMe
+Object.defineProperty(VueI18n, 'availabilities', {
+  get () {
+    if (!availabilities) {
+      const intlDefined = typeof Intl !== 'undefined';
+      availabilities = {
+        dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
+        numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
+      };
+    }
+
+    return availabilities
+  }
+});
+
+VueI18n.install = install;
+VueI18n.version = '8.21.0';
+
+export default VueI18n;

File diff suppressed because it is too large
+ 0 - 0
plugin/vue-i18n/dist/vue-i18n.esm.browser.min.js


+ 2149 - 0
plugin/vue-i18n/dist/vue-i18n.esm.js

@@ -0,0 +1,2149 @@
+/*!
+ * vue-i18n v8.21.0 
+ * (c) 2020 kazuya kawaguchi
+ * Released under the MIT License.
+ */
+/*  */
+
+/**
+ * constants
+ */
+
+var numberFormatKeys = [
+  'style',
+  'currency',
+  'currencyDisplay',
+  'useGrouping',
+  'minimumIntegerDigits',
+  'minimumFractionDigits',
+  'maximumFractionDigits',
+  'minimumSignificantDigits',
+  'maximumSignificantDigits',
+  'localeMatcher',
+  'formatMatcher',
+  'unit'
+];
+
+/**
+ * utilities
+ */
+
+function warn (msg, err) {
+  if (typeof console !== 'undefined') {
+    console.warn('[vue-i18n] ' + msg);
+    /* istanbul ignore if */
+    if (err) {
+      console.warn(err.stack);
+    }
+  }
+}
+
+function error (msg, err) {
+  if (typeof console !== 'undefined') {
+    console.error('[vue-i18n] ' + msg);
+    /* istanbul ignore if */
+    if (err) {
+      console.error(err.stack);
+    }
+  }
+}
+
+var isArray = Array.isArray;
+
+function isObject (obj) {
+  return obj !== null && typeof obj === 'object'
+}
+
+function isBoolean (val) {
+  return typeof val === 'boolean'
+}
+
+function isString (val) {
+  return typeof val === 'string'
+}
+
+var toString = Object.prototype.toString;
+var OBJECT_STRING = '[object Object]';
+function isPlainObject (obj) {
+  return toString.call(obj) === OBJECT_STRING
+}
+
+function isNull (val) {
+  return val === null || val === undefined
+}
+
+function isFunction (val) {
+  return typeof val === 'function'
+}
+
+function parseArgs () {
+  var args = [], len = arguments.length;
+  while ( len-- ) args[ len ] = arguments[ len ];
+
+  var locale = null;
+  var params = null;
+  if (args.length === 1) {
+    if (isObject(args[0]) || isArray(args[0])) {
+      params = args[0];
+    } else if (typeof args[0] === 'string') {
+      locale = args[0];
+    }
+  } else if (args.length === 2) {
+    if (typeof args[0] === 'string') {
+      locale = args[0];
+    }
+    /* istanbul ignore if */
+    if (isObject(args[1]) || isArray(args[1])) {
+      params = args[1];
+    }
+  }
+
+  return { locale: locale, params: params }
+}
+
+function looseClone (obj) {
+  return JSON.parse(JSON.stringify(obj))
+}
+
+function remove (arr, item) {
+  if (arr.length) {
+    var index = arr.indexOf(item);
+    if (index > -1) {
+      return arr.splice(index, 1)
+    }
+  }
+}
+
+function includes (arr, item) {
+  return !!~arr.indexOf(item)
+}
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+function hasOwn (obj, key) {
+  return hasOwnProperty.call(obj, key)
+}
+
+function merge (target) {
+  var arguments$1 = arguments;
+
+  var output = Object(target);
+  for (var i = 1; i < arguments.length; i++) {
+    var source = arguments$1[i];
+    if (source !== undefined && source !== null) {
+      var key = (void 0);
+      for (key in source) {
+        if (hasOwn(source, key)) {
+          if (isObject(source[key])) {
+            output[key] = merge(output[key], source[key]);
+          } else {
+            output[key] = source[key];
+          }
+        }
+      }
+    }
+  }
+  return output
+}
+
+function looseEqual (a, b) {
+  if (a === b) { return true }
+  var isObjectA = isObject(a);
+  var isObjectB = isObject(b);
+  if (isObjectA && isObjectB) {
+    try {
+      var isArrayA = isArray(a);
+      var isArrayB = isArray(b);
+      if (isArrayA && isArrayB) {
+        return a.length === b.length && a.every(function (e, i) {
+          return looseEqual(e, b[i])
+        })
+      } else if (!isArrayA && !isArrayB) {
+        var keysA = Object.keys(a);
+        var keysB = Object.keys(b);
+        return keysA.length === keysB.length && keysA.every(function (key) {
+          return looseEqual(a[key], b[key])
+        })
+      } else {
+        /* istanbul ignore next */
+        return false
+      }
+    } catch (e) {
+      /* istanbul ignore next */
+      return false
+    }
+  } else if (!isObjectA && !isObjectB) {
+    return String(a) === String(b)
+  } else {
+    return false
+  }
+}
+
+/*  */
+
+function extend (Vue) {
+  if (!Vue.prototype.hasOwnProperty('$i18n')) {
+    // $FlowFixMe
+    Object.defineProperty(Vue.prototype, '$i18n', {
+      get: function get () { return this._i18n }
+    });
+  }
+
+  Vue.prototype.$t = function (key) {
+    var values = [], len = arguments.length - 1;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 1 ];
+
+    var i18n = this.$i18n;
+    return i18n._t.apply(i18n, [ key, i18n.locale, i18n._getMessages(), this ].concat( values ))
+  };
+
+  Vue.prototype.$tc = function (key, choice) {
+    var values = [], len = arguments.length - 2;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 2 ];
+
+    var i18n = this.$i18n;
+    return i18n._tc.apply(i18n, [ key, i18n.locale, i18n._getMessages(), this, choice ].concat( values ))
+  };
+
+  Vue.prototype.$te = function (key, locale) {
+    var i18n = this.$i18n;
+    return i18n._te(key, i18n.locale, i18n._getMessages(), locale)
+  };
+
+  Vue.prototype.$d = function (value) {
+    var ref;
+
+    var args = [], len = arguments.length - 1;
+    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+    return (ref = this.$i18n).d.apply(ref, [ value ].concat( args ))
+  };
+
+  Vue.prototype.$n = function (value) {
+    var ref;
+
+    var args = [], len = arguments.length - 1;
+    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+    return (ref = this.$i18n).n.apply(ref, [ value ].concat( args ))
+  };
+}
+
+/*  */
+
+var mixin = {
+  beforeCreate: function beforeCreate () {
+    var options = this.$options;
+    options.i18n = options.i18n || (options.__i18n ? {} : null);
+
+    if (options.i18n) {
+      if (options.i18n instanceof VueI18n) {
+        // init locale messages via custom blocks
+        if (options.__i18n) {
+          try {
+            var localeMessages = {};
+            options.__i18n.forEach(function (resource) {
+              localeMessages = merge(localeMessages, JSON.parse(resource));
+            });
+            Object.keys(localeMessages).forEach(function (locale) {
+              options.i18n.mergeLocaleMessage(locale, localeMessages[locale]);
+            });
+          } catch (e) {
+            if (process.env.NODE_ENV !== 'production') {
+              error("Cannot parse locale messages via custom blocks.", e);
+            }
+          }
+        }
+        this._i18n = options.i18n;
+        this._i18nWatcher = this._i18n.watchI18nData();
+      } else if (isPlainObject(options.i18n)) {
+        var rootI18n = this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n
+          ? this.$root.$i18n
+          : null;
+        // component local i18n
+        if (rootI18n) {
+          options.i18n.root = this.$root;
+          options.i18n.formatter = rootI18n.formatter;
+          options.i18n.fallbackLocale = rootI18n.fallbackLocale;
+          options.i18n.formatFallbackMessages = rootI18n.formatFallbackMessages;
+          options.i18n.silentTranslationWarn = rootI18n.silentTranslationWarn;
+          options.i18n.silentFallbackWarn = rootI18n.silentFallbackWarn;
+          options.i18n.pluralizationRules = rootI18n.pluralizationRules;
+          options.i18n.preserveDirectiveContent = rootI18n.preserveDirectiveContent;
+        }
+
+        // init locale messages via custom blocks
+        if (options.__i18n) {
+          try {
+            var localeMessages$1 = {};
+            options.__i18n.forEach(function (resource) {
+              localeMessages$1 = merge(localeMessages$1, JSON.parse(resource));
+            });
+            options.i18n.messages = localeMessages$1;
+          } catch (e) {
+            if (process.env.NODE_ENV !== 'production') {
+              warn("Cannot parse locale messages via custom blocks.", e);
+            }
+          }
+        }
+
+        var ref = options.i18n;
+        var sharedMessages = ref.sharedMessages;
+        if (sharedMessages && isPlainObject(sharedMessages)) {
+          options.i18n.messages = merge(options.i18n.messages, sharedMessages);
+        }
+
+        this._i18n = new VueI18n(options.i18n);
+        this._i18nWatcher = this._i18n.watchI18nData();
+
+        if (options.i18n.sync === undefined || !!options.i18n.sync) {
+          this._localeWatcher = this.$i18n.watchLocale();
+        }
+
+        if (rootI18n) {
+          rootI18n.onComponentInstanceCreated(this._i18n);
+        }
+      } else {
+        if (process.env.NODE_ENV !== 'production') {
+          warn("Cannot be interpreted 'i18n' option.");
+        }
+      }
+    } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
+      // root i18n
+      this._i18n = this.$root.$i18n;
+    } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
+      // parent i18n
+      this._i18n = options.parent.$i18n;
+    }
+  },
+
+  beforeMount: function beforeMount () {
+    var options = this.$options;
+    options.i18n = options.i18n || (options.__i18n ? {} : null);
+
+    if (options.i18n) {
+      if (options.i18n instanceof VueI18n) {
+        // init locale messages via custom blocks
+        this._i18n.subscribeDataChanging(this);
+        this._subscribing = true;
+      } else if (isPlainObject(options.i18n)) {
+        this._i18n.subscribeDataChanging(this);
+        this._subscribing = true;
+      } else {
+        if (process.env.NODE_ENV !== 'production') {
+          warn("Cannot be interpreted 'i18n' option.");
+        }
+      }
+    } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
+      this._i18n.subscribeDataChanging(this);
+      this._subscribing = true;
+    } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
+      this._i18n.subscribeDataChanging(this);
+      this._subscribing = true;
+    }
+  },
+
+  beforeDestroy: function beforeDestroy () {
+    if (!this._i18n) { return }
+
+    var self = this;
+    this.$nextTick(function () {
+      if (self._subscribing) {
+        self._i18n.unsubscribeDataChanging(self);
+        delete self._subscribing;
+      }
+
+      if (self._i18nWatcher) {
+        self._i18nWatcher();
+        self._i18n.destroyVM();
+        delete self._i18nWatcher;
+      }
+
+      if (self._localeWatcher) {
+        self._localeWatcher();
+        delete self._localeWatcher;
+      }
+    });
+  }
+};
+
+/*  */
+
+var interpolationComponent = {
+  name: 'i18n',
+  functional: true,
+  props: {
+    tag: {
+      type: [String, Boolean, Object],
+      default: 'span'
+    },
+    path: {
+      type: String,
+      required: true
+    },
+    locale: {
+      type: String
+    },
+    places: {
+      type: [Array, Object]
+    }
+  },
+  render: function render (h, ref) {
+    var data = ref.data;
+    var parent = ref.parent;
+    var props = ref.props;
+    var slots = ref.slots;
+
+    var $i18n = parent.$i18n;
+    if (!$i18n) {
+      if (process.env.NODE_ENV !== 'production') {
+        warn('Cannot find VueI18n instance!');
+      }
+      return
+    }
+
+    var path = props.path;
+    var locale = props.locale;
+    var places = props.places;
+    var params = slots();
+    var children = $i18n.i(
+      path,
+      locale,
+      onlyHasDefaultPlace(params) || places
+        ? useLegacyPlaces(params.default, places)
+        : params
+    );
+
+    var tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span';
+    return tag ? h(tag, data, children) : children
+  }
+};
+
+function onlyHasDefaultPlace (params) {
+  var prop;
+  for (prop in params) {
+    if (prop !== 'default') { return false }
+  }
+  return Boolean(prop)
+}
+
+function useLegacyPlaces (children, places) {
+  var params = places ? createParamsFromPlaces(places) : {};
+
+  if (!children) { return params }
+
+  // Filter empty text nodes
+  children = children.filter(function (child) {
+    return child.tag || child.text.trim() !== ''
+  });
+
+  var everyPlace = children.every(vnodeHasPlaceAttribute);
+  if (process.env.NODE_ENV !== 'production' && everyPlace) {
+    warn('`place` attribute is deprecated in next major version. Please switch to Vue slots.');
+  }
+
+  return children.reduce(
+    everyPlace ? assignChildPlace : assignChildIndex,
+    params
+  )
+}
+
+function createParamsFromPlaces (places) {
+  if (process.env.NODE_ENV !== 'production') {
+    warn('`places` prop is deprecated in next major version. Please switch to Vue slots.');
+  }
+
+  return Array.isArray(places)
+    ? places.reduce(assignChildIndex, {})
+    : Object.assign({}, places)
+}
+
+function assignChildPlace (params, child) {
+  if (child.data && child.data.attrs && child.data.attrs.place) {
+    params[child.data.attrs.place] = child;
+  }
+  return params
+}
+
+function assignChildIndex (params, child, index) {
+  params[index] = child;
+  return params
+}
+
+function vnodeHasPlaceAttribute (vnode) {
+  return Boolean(vnode.data && vnode.data.attrs && vnode.data.attrs.place)
+}
+
+/*  */
+
+var numberComponent = {
+  name: 'i18n-n',
+  functional: true,
+  props: {
+    tag: {
+      type: [String, Boolean, Object],
+      default: 'span'
+    },
+    value: {
+      type: Number,
+      required: true
+    },
+    format: {
+      type: [String, Object]
+    },
+    locale: {
+      type: String
+    }
+  },
+  render: function render (h, ref) {
+    var props = ref.props;
+    var parent = ref.parent;
+    var data = ref.data;
+
+    var i18n = parent.$i18n;
+
+    if (!i18n) {
+      if (process.env.NODE_ENV !== 'production') {
+        warn('Cannot find VueI18n instance!');
+      }
+      return null
+    }
+
+    var key = null;
+    var options = null;
+
+    if (isString(props.format)) {
+      key = props.format;
+    } else if (isObject(props.format)) {
+      if (props.format.key) {
+        key = props.format.key;
+      }
+
+      // Filter out number format options only
+      options = Object.keys(props.format).reduce(function (acc, prop) {
+        var obj;
+
+        if (includes(numberFormatKeys, prop)) {
+          return Object.assign({}, acc, ( obj = {}, obj[prop] = props.format[prop], obj ))
+        }
+        return acc
+      }, null);
+    }
+
+    var locale = props.locale || i18n.locale;
+    var parts = i18n._ntp(props.value, locale, key, options);
+
+    var values = parts.map(function (part, index) {
+      var obj;
+
+      var slot = data.scopedSlots && data.scopedSlots[part.type];
+      return slot ? slot(( obj = {}, obj[part.type] = part.value, obj.index = index, obj.parts = parts, obj )) : part.value
+    });
+
+    var tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span';
+    return tag
+      ? h(tag, {
+        attrs: data.attrs,
+        'class': data['class'],
+        staticClass: data.staticClass
+      }, values)
+      : values
+  }
+};
+
+/*  */
+
+function bind (el, binding, vnode) {
+  if (!assert(el, vnode)) { return }
+
+  t(el, binding, vnode);
+}
+
+function update (el, binding, vnode, oldVNode) {
+  if (!assert(el, vnode)) { return }
+
+  var i18n = vnode.context.$i18n;
+  if (localeEqual(el, vnode) &&
+    (looseEqual(binding.value, binding.oldValue) &&
+     looseEqual(el._localeMessage, i18n.getLocaleMessage(i18n.locale)))) { return }
+
+  t(el, binding, vnode);
+}
+
+function unbind (el, binding, vnode, oldVNode) {
+  var vm = vnode.context;
+  if (!vm) {
+    warn('Vue instance does not exists in VNode context');
+    return
+  }
+
+  var i18n = vnode.context.$i18n || {};
+  if (!binding.modifiers.preserve && !i18n.preserveDirectiveContent) {
+    el.textContent = '';
+  }
+  el._vt = undefined;
+  delete el['_vt'];
+  el._locale = undefined;
+  delete el['_locale'];
+  el._localeMessage = undefined;
+  delete el['_localeMessage'];
+}
+
+function assert (el, vnode) {
+  var vm = vnode.context;
+  if (!vm) {
+    warn('Vue instance does not exists in VNode context');
+    return false
+  }
+
+  if (!vm.$i18n) {
+    warn('VueI18n instance does not exists in Vue instance');
+    return false
+  }
+
+  return true
+}
+
+function localeEqual (el, vnode) {
+  var vm = vnode.context;
+  return el._locale === vm.$i18n.locale
+}
+
+function t (el, binding, vnode) {
+  var ref$1, ref$2;
+
+  var value = binding.value;
+
+  var ref = parseValue(value);
+  var path = ref.path;
+  var locale = ref.locale;
+  var args = ref.args;
+  var choice = ref.choice;
+  if (!path && !locale && !args) {
+    warn('value type not supported');
+    return
+  }
+
+  if (!path) {
+    warn('`path` is required in v-t directive');
+    return
+  }
+
+  var vm = vnode.context;
+  if (choice != null) {
+    el._vt = el.textContent = (ref$1 = vm.$i18n).tc.apply(ref$1, [ path, choice ].concat( makeParams(locale, args) ));
+  } else {
+    el._vt = el.textContent = (ref$2 = vm.$i18n).t.apply(ref$2, [ path ].concat( makeParams(locale, args) ));
+  }
+  el._locale = vm.$i18n.locale;
+  el._localeMessage = vm.$i18n.getLocaleMessage(vm.$i18n.locale);
+}
+
+function parseValue (value) {
+  var path;
+  var locale;
+  var args;
+  var choice;
+
+  if (isString(value)) {
+    path = value;
+  } else if (isPlainObject(value)) {
+    path = value.path;
+    locale = value.locale;
+    args = value.args;
+    choice = value.choice;
+  }
+
+  return { path: path, locale: locale, args: args, choice: choice }
+}
+
+function makeParams (locale, args) {
+  var params = [];
+
+  locale && params.push(locale);
+  if (args && (Array.isArray(args) || isPlainObject(args))) {
+    params.push(args);
+  }
+
+  return params
+}
+
+var Vue;
+
+function install (_Vue) {
+  /* istanbul ignore if */
+  if (process.env.NODE_ENV !== 'production' && install.installed && _Vue === Vue) {
+    warn('already installed.');
+    return
+  }
+  install.installed = true;
+
+  Vue = _Vue;
+
+  var version = (Vue.version && Number(Vue.version.split('.')[0])) || -1;
+  /* istanbul ignore if */
+  if (process.env.NODE_ENV !== 'production' && version < 2) {
+    warn(("vue-i18n (" + (install.version) + ") need to use Vue 2.0 or later (Vue: " + (Vue.version) + ")."));
+    return
+  }
+
+  extend(Vue);
+  Vue.mixin(mixin);
+  Vue.directive('t', { bind: bind, update: update, unbind: unbind });
+  Vue.component(interpolationComponent.name, interpolationComponent);
+  Vue.component(numberComponent.name, numberComponent);
+
+  // use simple mergeStrategies to prevent i18n instance lose '__proto__'
+  var strats = Vue.config.optionMergeStrategies;
+  strats.i18n = function (parentVal, childVal) {
+    return childVal === undefined
+      ? parentVal
+      : childVal
+  };
+}
+
+/*  */
+
+var BaseFormatter = function BaseFormatter () {
+  this._caches = Object.create(null);
+};
+
+BaseFormatter.prototype.interpolate = function interpolate (message, values) {
+  if (!values) {
+    return [message]
+  }
+  var tokens = this._caches[message];
+  if (!tokens) {
+    tokens = parse(message);
+    this._caches[message] = tokens;
+  }
+  return compile(tokens, values)
+};
+
+
+
+var RE_TOKEN_LIST_VALUE = /^(?:\d)+/;
+var RE_TOKEN_NAMED_VALUE = /^(?:\w)+/;
+
+function parse (format) {
+  var tokens = [];
+  var position = 0;
+
+  var text = '';
+  while (position < format.length) {
+    var char = format[position++];
+    if (char === '{') {
+      if (text) {
+        tokens.push({ type: 'text', value: text });
+      }
+
+      text = '';
+      var sub = '';
+      char = format[position++];
+      while (char !== undefined && char !== '}') {
+        sub += char;
+        char = format[position++];
+      }
+      var isClosed = char === '}';
+
+      var type = RE_TOKEN_LIST_VALUE.test(sub)
+        ? 'list'
+        : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
+          ? 'named'
+          : 'unknown';
+      tokens.push({ value: sub, type: type });
+    } else if (char === '%') {
+      // when found rails i18n syntax, skip text capture
+      if (format[(position)] !== '{') {
+        text += char;
+      }
+    } else {
+      text += char;
+    }
+  }
+
+  text && tokens.push({ type: 'text', value: text });
+
+  return tokens
+}
+
+function compile (tokens, values) {
+  var compiled = [];
+  var index = 0;
+
+  var mode = Array.isArray(values)
+    ? 'list'
+    : isObject(values)
+      ? 'named'
+      : 'unknown';
+  if (mode === 'unknown') { return compiled }
+
+  while (index < tokens.length) {
+    var token = tokens[index];
+    switch (token.type) {
+      case 'text':
+        compiled.push(token.value);
+        break
+      case 'list':
+        compiled.push(values[parseInt(token.value, 10)]);
+        break
+      case 'named':
+        if (mode === 'named') {
+          compiled.push((values)[token.value]);
+        } else {
+          if (process.env.NODE_ENV !== 'production') {
+            warn(("Type of token '" + (token.type) + "' and format of value '" + mode + "' don't match!"));
+          }
+        }
+        break
+      case 'unknown':
+        if (process.env.NODE_ENV !== 'production') {
+          warn("Detect 'unknown' type of token!");
+        }
+        break
+    }
+    index++;
+  }
+
+  return compiled
+}
+
+/*  */
+
+/**
+ *  Path parser
+ *  - Inspired:
+ *    Vue.js Path parser
+ */
+
+// actions
+var APPEND = 0;
+var PUSH = 1;
+var INC_SUB_PATH_DEPTH = 2;
+var PUSH_SUB_PATH = 3;
+
+// states
+var BEFORE_PATH = 0;
+var IN_PATH = 1;
+var BEFORE_IDENT = 2;
+var IN_IDENT = 3;
+var IN_SUB_PATH = 4;
+var IN_SINGLE_QUOTE = 5;
+var IN_DOUBLE_QUOTE = 6;
+var AFTER_PATH = 7;
+var ERROR = 8;
+
+var pathStateMachine = [];
+
+pathStateMachine[BEFORE_PATH] = {
+  'ws': [BEFORE_PATH],
+  'ident': [IN_IDENT, APPEND],
+  '[': [IN_SUB_PATH],
+  'eof': [AFTER_PATH]
+};
+
+pathStateMachine[IN_PATH] = {
+  'ws': [IN_PATH],
+  '.': [BEFORE_IDENT],
+  '[': [IN_SUB_PATH],
+  'eof': [AFTER_PATH]
+};
+
+pathStateMachine[BEFORE_IDENT] = {
+  'ws': [BEFORE_IDENT],
+  'ident': [IN_IDENT, APPEND],
+  '0': [IN_IDENT, APPEND],
+  'number': [IN_IDENT, APPEND]
+};
+
+pathStateMachine[IN_IDENT] = {
+  'ident': [IN_IDENT, APPEND],
+  '0': [IN_IDENT, APPEND],
+  'number': [IN_IDENT, APPEND],
+  'ws': [IN_PATH, PUSH],
+  '.': [BEFORE_IDENT, PUSH],
+  '[': [IN_SUB_PATH, PUSH],
+  'eof': [AFTER_PATH, PUSH]
+};
+
+pathStateMachine[IN_SUB_PATH] = {
+  "'": [IN_SINGLE_QUOTE, APPEND],
+  '"': [IN_DOUBLE_QUOTE, APPEND],
+  '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH],
+  ']': [IN_PATH, PUSH_SUB_PATH],
+  'eof': ERROR,
+  'else': [IN_SUB_PATH, APPEND]
+};
+
+pathStateMachine[IN_SINGLE_QUOTE] = {
+  "'": [IN_SUB_PATH, APPEND],
+  'eof': ERROR,
+  'else': [IN_SINGLE_QUOTE, APPEND]
+};
+
+pathStateMachine[IN_DOUBLE_QUOTE] = {
+  '"': [IN_SUB_PATH, APPEND],
+  'eof': ERROR,
+  'else': [IN_DOUBLE_QUOTE, APPEND]
+};
+
+/**
+ * Check if an expression is a literal value.
+ */
+
+var literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
+function isLiteral (exp) {
+  return literalValueRE.test(exp)
+}
+
+/**
+ * Strip quotes from a string
+ */
+
+function stripQuotes (str) {
+  var a = str.charCodeAt(0);
+  var b = str.charCodeAt(str.length - 1);
+  return a === b && (a === 0x22 || a === 0x27)
+    ? str.slice(1, -1)
+    : str
+}
+
+/**
+ * Determine the type of a character in a keypath.
+ */
+
+function getPathCharType (ch) {
+  if (ch === undefined || ch === null) { return 'eof' }
+
+  var code = ch.charCodeAt(0);
+
+  switch (code) {
+    case 0x5B: // [
+    case 0x5D: // ]
+    case 0x2E: // .
+    case 0x22: // "
+    case 0x27: // '
+      return ch
+
+    case 0x5F: // _
+    case 0x24: // $
+    case 0x2D: // -
+      return 'ident'
+
+    case 0x09: // Tab
+    case 0x0A: // Newline
+    case 0x0D: // Return
+    case 0xA0:  // No-break space
+    case 0xFEFF:  // Byte Order Mark
+    case 0x2028:  // Line Separator
+    case 0x2029:  // Paragraph Separator
+      return 'ws'
+  }
+
+  return 'ident'
+}
+
+/**
+ * Format a subPath, return its plain form if it is
+ * a literal string or number. Otherwise prepend the
+ * dynamic indicator (*).
+ */
+
+function formatSubPath (path) {
+  var trimmed = path.trim();
+  // invalid leading 0
+  if (path.charAt(0) === '0' && isNaN(path)) { return false }
+
+  return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed
+}
+
+/**
+ * Parse a string path into an array of segments
+ */
+
+function parse$1 (path) {
+  var keys = [];
+  var index = -1;
+  var mode = BEFORE_PATH;
+  var subPathDepth = 0;
+  var c;
+  var key;
+  var newChar;
+  var type;
+  var transition;
+  var action;
+  var typeMap;
+  var actions = [];
+
+  actions[PUSH] = function () {
+    if (key !== undefined) {
+      keys.push(key);
+      key = undefined;
+    }
+  };
+
+  actions[APPEND] = function () {
+    if (key === undefined) {
+      key = newChar;
+    } else {
+      key += newChar;
+    }
+  };
+
+  actions[INC_SUB_PATH_DEPTH] = function () {
+    actions[APPEND]();
+    subPathDepth++;
+  };
+
+  actions[PUSH_SUB_PATH] = function () {
+    if (subPathDepth > 0) {
+      subPathDepth--;
+      mode = IN_SUB_PATH;
+      actions[APPEND]();
+    } else {
+      subPathDepth = 0;
+      if (key === undefined) { return false }
+      key = formatSubPath(key);
+      if (key === false) {
+        return false
+      } else {
+        actions[PUSH]();
+      }
+    }
+  };
+
+  function maybeUnescapeQuote () {
+    var nextChar = path[index + 1];
+    if ((mode === IN_SINGLE_QUOTE && nextChar === "'") ||
+      (mode === IN_DOUBLE_QUOTE && nextChar === '"')) {
+      index++;
+      newChar = '\\' + nextChar;
+      actions[APPEND]();
+      return true
+    }
+  }
+
+  while (mode !== null) {
+    index++;
+    c = path[index];
+
+    if (c === '\\' && maybeUnescapeQuote()) {
+      continue
+    }
+
+    type = getPathCharType(c);
+    typeMap = pathStateMachine[mode];
+    transition = typeMap[type] || typeMap['else'] || ERROR;
+
+    if (transition === ERROR) {
+      return // parse error
+    }
+
+    mode = transition[0];
+    action = actions[transition[1]];
+    if (action) {
+      newChar = transition[2];
+      newChar = newChar === undefined
+        ? c
+        : newChar;
+      if (action() === false) {
+        return
+      }
+    }
+
+    if (mode === AFTER_PATH) {
+      return keys
+    }
+  }
+}
+
+
+
+
+
+var I18nPath = function I18nPath () {
+  this._cache = Object.create(null);
+};
+
+/**
+ * External parse that check for a cache hit first
+ */
+I18nPath.prototype.parsePath = function parsePath (path) {
+  var hit = this._cache[path];
+  if (!hit) {
+    hit = parse$1(path);
+    if (hit) {
+      this._cache[path] = hit;
+    }
+  }
+  return hit || []
+};
+
+/**
+ * Get path value from path string
+ */
+I18nPath.prototype.getPathValue = function getPathValue (obj, path) {
+  if (!isObject(obj)) { return null }
+
+  var paths = this.parsePath(path);
+  if (paths.length === 0) {
+    return null
+  } else {
+    var length = paths.length;
+    var last = obj;
+    var i = 0;
+    while (i < length) {
+      var value = last[paths[i]];
+      if (value === undefined) {
+        return null
+      }
+      last = value;
+      i++;
+    }
+
+    return last
+  }
+};
+
+/*  */
+
+
+
+var htmlTagMatcher = /<\/?[\w\s="/.':;#-\/]+>/;
+var linkKeyMatcher = /(?:@(?:\.[a-z]+)?:(?:[\w\-_|.]+|\([\w\-_|.]+\)))/g;
+var linkKeyPrefixMatcher = /^@(?:\.([a-z]+))?:/;
+var bracketsMatcher = /[()]/g;
+var defaultModifiers = {
+  'upper': function (str) { return str.toLocaleUpperCase(); },
+  'lower': function (str) { return str.toLocaleLowerCase(); },
+  'capitalize': function (str) { return ("" + (str.charAt(0).toLocaleUpperCase()) + (str.substr(1))); }
+};
+
+var defaultFormatter = new BaseFormatter();
+
+var VueI18n = function VueI18n (options) {
+  var this$1 = this;
+  if ( options === void 0 ) options = {};
+
+  // Auto install if it is not done yet and `window` has `Vue`.
+  // To allow users to avoid auto-installation in some cases,
+  // this code should be placed here. See #290
+  /* istanbul ignore if */
+  if (!Vue && typeof window !== 'undefined' && window.Vue) {
+    install(window.Vue);
+  }
+
+  var locale = options.locale || 'en-US';
+  var fallbackLocale = options.fallbackLocale === false
+    ? false
+    : options.fallbackLocale || 'en-US';
+  var messages = options.messages || {};
+  var dateTimeFormats = options.dateTimeFormats || {};
+  var numberFormats = options.numberFormats || {};
+
+  this._vm = null;
+  this._formatter = options.formatter || defaultFormatter;
+  this._modifiers = options.modifiers || {};
+  this._missing = options.missing || null;
+  this._root = options.root || null;
+  this._sync = options.sync === undefined ? true : !!options.sync;
+  this._fallbackRoot = options.fallbackRoot === undefined
+    ? true
+    : !!options.fallbackRoot;
+  this._formatFallbackMessages = options.formatFallbackMessages === undefined
+    ? false
+    : !!options.formatFallbackMessages;
+  this._silentTranslationWarn = options.silentTranslationWarn === undefined
+    ? false
+    : options.silentTranslationWarn;
+  this._silentFallbackWarn = options.silentFallbackWarn === undefined
+    ? false
+    : !!options.silentFallbackWarn;
+  this._dateTimeFormatters = {};
+  this._numberFormatters = {};
+  this._path = new I18nPath();
+  this._dataListeners = [];
+  this._componentInstanceCreatedListener = options.componentInstanceCreatedListener || null;
+  this._preserveDirectiveContent = options.preserveDirectiveContent === undefined
+    ? false
+    : !!options.preserveDirectiveContent;
+  this.pluralizationRules = options.pluralizationRules || {};
+  this._warnHtmlInMessage = options.warnHtmlInMessage || 'off';
+  this._postTranslation = options.postTranslation || null;
+
+  /**
+   * @param choice {number} a choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)`
+   * @param choicesLength {number} an overall amount of available choices
+   * @returns a final choice index
+  */
+  this.getChoiceIndex = function (choice, choicesLength) {
+    var thisPrototype = Object.getPrototypeOf(this$1);
+    if (thisPrototype && thisPrototype.getChoiceIndex) {
+      var prototypeGetChoiceIndex = (thisPrototype.getChoiceIndex);
+      return (prototypeGetChoiceIndex).call(this$1, choice, choicesLength)
+    }
+
+    // Default (old) getChoiceIndex implementation - english-compatible
+    var defaultImpl = function (_choice, _choicesLength) {
+      _choice = Math.abs(_choice);
+
+      if (_choicesLength === 2) {
+        return _choice
+          ? _choice > 1
+            ? 1
+            : 0
+          : 1
+      }
+
+      return _choice ? Math.min(_choice, 2) : 0
+    };
+
+    if (this$1.locale in this$1.pluralizationRules) {
+      return this$1.pluralizationRules[this$1.locale].apply(this$1, [choice, choicesLength])
+    } else {
+      return defaultImpl(choice, choicesLength)
+    }
+  };
+
+
+  this._exist = function (message, key) {
+    if (!message || !key) { return false }
+    if (!isNull(this$1._path.getPathValue(message, key))) { return true }
+    // fallback for flat key
+    if (message[key]) { return true }
+    return false
+  };
+
+  if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+    Object.keys(messages).forEach(function (locale) {
+      this$1._checkLocaleMessage(locale, this$1._warnHtmlInMessage, messages[locale]);
+    });
+  }
+
+  this._initVM({
+    locale: locale,
+    fallbackLocale: fallbackLocale,
+    messages: messages,
+    dateTimeFormats: dateTimeFormats,
+    numberFormats: numberFormats
+  });
+};
+
+var prototypeAccessors = { vm: { configurable: true },messages: { configurable: true },dateTimeFormats: { configurable: true },numberFormats: { configurable: true },availableLocales: { configurable: true },locale: { configurable: true },fallbackLocale: { configurable: true },formatFallbackMessages: { configurable: true },missing: { configurable: true },formatter: { configurable: true },silentTranslationWarn: { configurable: true },silentFallbackWarn: { configurable: true },preserveDirectiveContent: { configurable: true },warnHtmlInMessage: { configurable: true },postTranslation: { configurable: true } };
+
+VueI18n.prototype._checkLocaleMessage = function _checkLocaleMessage (locale, level, message) {
+  var paths = [];
+
+  var fn = function (level, locale, message, paths) {
+    if (isPlainObject(message)) {
+      Object.keys(message).forEach(function (key) {
+        var val = message[key];
+        if (isPlainObject(val)) {
+          paths.push(key);
+          paths.push('.');
+          fn(level, locale, val, paths);
+          paths.pop();
+          paths.pop();
+        } else {
+          paths.push(key);
+          fn(level, locale, val, paths);
+          paths.pop();
+        }
+      });
+    } else if (isArray(message)) {
+      message.forEach(function (item, index) {
+        if (isPlainObject(item)) {
+          paths.push(("[" + index + "]"));
+          paths.push('.');
+          fn(level, locale, item, paths);
+          paths.pop();
+          paths.pop();
+        } else {
+          paths.push(("[" + index + "]"));
+          fn(level, locale, item, paths);
+          paths.pop();
+        }
+      });
+    } else if (isString(message)) {
+      var ret = htmlTagMatcher.test(message);
+      if (ret) {
+        var msg = "Detected HTML in message '" + message + "' of keypath '" + (paths.join('')) + "' at '" + locale + "'. Consider component interpolation with '<i18n>' to avoid XSS. See https://bit.ly/2ZqJzkp";
+        if (level === 'warn') {
+          warn(msg);
+        } else if (level === 'error') {
+          error(msg);
+        }
+      }
+    }
+  };
+
+  fn(level, locale, message, paths);
+};
+
+VueI18n.prototype._initVM = function _initVM (data) {
+  var silent = Vue.config.silent;
+  Vue.config.silent = true;
+  this._vm = new Vue({ data: data });
+  Vue.config.silent = silent;
+};
+
+VueI18n.prototype.destroyVM = function destroyVM () {
+  this._vm.$destroy();
+};
+
+VueI18n.prototype.subscribeDataChanging = function subscribeDataChanging (vm) {
+  this._dataListeners.push(vm);
+};
+
+VueI18n.prototype.unsubscribeDataChanging = function unsubscribeDataChanging (vm) {
+  remove(this._dataListeners, vm);
+};
+
+VueI18n.prototype.watchI18nData = function watchI18nData () {
+  var self = this;
+  return this._vm.$watch('$data', function () {
+    var i = self._dataListeners.length;
+    while (i--) {
+      Vue.nextTick(function () {
+        self._dataListeners[i] && self._dataListeners[i].$forceUpdate();
+      });
+    }
+  }, { deep: true })
+};
+
+VueI18n.prototype.watchLocale = function watchLocale () {
+  /* istanbul ignore if */
+  if (!this._sync || !this._root) { return null }
+  var target = this._vm;
+  return this._root.$i18n.vm.$watch('locale', function (val) {
+    target.$set(target, 'locale', val);
+    target.$forceUpdate();
+  }, { immediate: true })
+};
+
+VueI18n.prototype.onComponentInstanceCreated = function onComponentInstanceCreated (newI18n) {
+  if (this._componentInstanceCreatedListener) {
+    this._componentInstanceCreatedListener(newI18n, this);
+  }
+};
+
+prototypeAccessors.vm.get = function () { return this._vm };
+
+prototypeAccessors.messages.get = function () { return looseClone(this._getMessages()) };
+prototypeAccessors.dateTimeFormats.get = function () { return looseClone(this._getDateTimeFormats()) };
+prototypeAccessors.numberFormats.get = function () { return looseClone(this._getNumberFormats()) };
+prototypeAccessors.availableLocales.get = function () { return Object.keys(this.messages).sort() };
+
+prototypeAccessors.locale.get = function () { return this._vm.locale };
+prototypeAccessors.locale.set = function (locale) {
+  this._vm.$set(this._vm, 'locale', locale);
+};
+
+prototypeAccessors.fallbackLocale.get = function () { return this._vm.fallbackLocale };
+prototypeAccessors.fallbackLocale.set = function (locale) {
+  this._localeChainCache = {};
+  this._vm.$set(this._vm, 'fallbackLocale', locale);
+};
+
+prototypeAccessors.formatFallbackMessages.get = function () { return this._formatFallbackMessages };
+prototypeAccessors.formatFallbackMessages.set = function (fallback) { this._formatFallbackMessages = fallback; };
+
+prototypeAccessors.missing.get = function () { return this._missing };
+prototypeAccessors.missing.set = function (handler) { this._missing = handler; };
+
+prototypeAccessors.formatter.get = function () { return this._formatter };
+prototypeAccessors.formatter.set = function (formatter) { this._formatter = formatter; };
+
+prototypeAccessors.silentTranslationWarn.get = function () { return this._silentTranslationWarn };
+prototypeAccessors.silentTranslationWarn.set = function (silent) { this._silentTranslationWarn = silent; };
+
+prototypeAccessors.silentFallbackWarn.get = function () { return this._silentFallbackWarn };
+prototypeAccessors.silentFallbackWarn.set = function (silent) { this._silentFallbackWarn = silent; };
+
+prototypeAccessors.preserveDirectiveContent.get = function () { return this._preserveDirectiveContent };
+prototypeAccessors.preserveDirectiveContent.set = function (preserve) { this._preserveDirectiveContent = preserve; };
+
+prototypeAccessors.warnHtmlInMessage.get = function () { return this._warnHtmlInMessage };
+prototypeAccessors.warnHtmlInMessage.set = function (level) {
+    var this$1 = this;
+
+  var orgLevel = this._warnHtmlInMessage;
+  this._warnHtmlInMessage = level;
+  if (orgLevel !== level && (level === 'warn' || level === 'error')) {
+    var messages = this._getMessages();
+    Object.keys(messages).forEach(function (locale) {
+      this$1._checkLocaleMessage(locale, this$1._warnHtmlInMessage, messages[locale]);
+    });
+  }
+};
+
+prototypeAccessors.postTranslation.get = function () { return this._postTranslation };
+prototypeAccessors.postTranslation.set = function (handler) { this._postTranslation = handler; };
+
+VueI18n.prototype._getMessages = function _getMessages () { return this._vm.messages };
+VueI18n.prototype._getDateTimeFormats = function _getDateTimeFormats () { return this._vm.dateTimeFormats };
+VueI18n.prototype._getNumberFormats = function _getNumberFormats () { return this._vm.numberFormats };
+
+VueI18n.prototype._warnDefault = function _warnDefault (locale, key, result, vm, values, interpolateMode) {
+  if (!isNull(result)) { return result }
+  if (this._missing) {
+    var missingRet = this._missing.apply(null, [locale, key, vm, values]);
+    if (isString(missingRet)) {
+      return missingRet
+    }
+  } else {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key)) {
+      warn(
+        "Cannot translate the value of keypath '" + key + "'. " +
+        'Use the value of keypath as default.'
+      );
+    }
+  }
+
+  if (this._formatFallbackMessages) {
+    var parsedArgs = parseArgs.apply(void 0, values);
+    return this._render(key, interpolateMode, parsedArgs.params, key)
+  } else {
+    return key
+  }
+};
+
+VueI18n.prototype._isFallbackRoot = function _isFallbackRoot (val) {
+  return !val && !isNull(this._root) && this._fallbackRoot
+};
+
+VueI18n.prototype._isSilentFallbackWarn = function _isSilentFallbackWarn (key) {
+  return this._silentFallbackWarn instanceof RegExp
+    ? this._silentFallbackWarn.test(key)
+    : this._silentFallbackWarn
+};
+
+VueI18n.prototype._isSilentFallback = function _isSilentFallback (locale, key) {
+  return this._isSilentFallbackWarn(key) && (this._isFallbackRoot() || locale !== this.fallbackLocale)
+};
+
+VueI18n.prototype._isSilentTranslationWarn = function _isSilentTranslationWarn (key) {
+  return this._silentTranslationWarn instanceof RegExp
+    ? this._silentTranslationWarn.test(key)
+    : this._silentTranslationWarn
+};
+
+VueI18n.prototype._interpolate = function _interpolate (
+  locale,
+  message,
+  key,
+  host,
+  interpolateMode,
+  values,
+  visitedLinkStack
+) {
+  if (!message) { return null }
+
+  var pathRet = this._path.getPathValue(message, key);
+  if (isArray(pathRet) || isPlainObject(pathRet)) { return pathRet }
+
+  var ret;
+  if (isNull(pathRet)) {
+    /* istanbul ignore else */
+    if (isPlainObject(message)) {
+      ret = message[key];
+      if (!(isString(ret) || isFunction(ret))) {
+        if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
+          warn(("Value of key '" + key + "' is not a string or function !"));
+        }
+        return null
+      }
+    } else {
+      return null
+    }
+  } else {
+    /* istanbul ignore else */
+    if (isString(pathRet) || isFunction(pathRet)) {
+      ret = pathRet;
+    } else {
+      if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
+        warn(("Value of key '" + key + "' is not a string or function!"));
+      }
+      return null
+    }
+  }
+
+  // Check for the existence of links within the translated string
+  if (isString(ret) && (ret.indexOf('@:') >= 0 || ret.indexOf('@.') >= 0)) {
+    ret = this._link(locale, message, ret, host, 'raw', values, visitedLinkStack);
+  }
+
+  return this._render(ret, interpolateMode, values, key)
+};
+
+VueI18n.prototype._link = function _link (
+  locale,
+  message,
+  str,
+  host,
+  interpolateMode,
+  values,
+  visitedLinkStack
+) {
+  var ret = str;
+
+  // Match all the links within the local
+  // We are going to replace each of
+  // them with its translation
+  var matches = ret.match(linkKeyMatcher);
+  for (var idx in matches) {
+    // ie compatible: filter custom array
+    // prototype method
+    if (!matches.hasOwnProperty(idx)) {
+      continue
+    }
+    var link = matches[idx];
+    var linkKeyPrefixMatches = link.match(linkKeyPrefixMatcher);
+    var linkPrefix = linkKeyPrefixMatches[0];
+      var formatterName = linkKeyPrefixMatches[1];
+
+    // Remove the leading @:, @.case: and the brackets
+    var linkPlaceholder = link.replace(linkPrefix, '').replace(bracketsMatcher, '');
+
+    if (includes(visitedLinkStack, linkPlaceholder)) {
+      if (process.env.NODE_ENV !== 'production') {
+        warn(("Circular reference found. \"" + link + "\" is already visited in the chain of " + (visitedLinkStack.reverse().join(' <- '))));
+      }
+      return ret
+    }
+    visitedLinkStack.push(linkPlaceholder);
+
+    // Translate the link
+    var translated = this._interpolate(
+      locale, message, linkPlaceholder, host,
+      interpolateMode === 'raw' ? 'string' : interpolateMode,
+      interpolateMode === 'raw' ? undefined : values,
+      visitedLinkStack
+    );
+
+    if (this._isFallbackRoot(translated)) {
+      if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(linkPlaceholder)) {
+        warn(("Fall back to translate the link placeholder '" + linkPlaceholder + "' with root locale."));
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      var root = this._root.$i18n;
+      translated = root._translate(
+        root._getMessages(), root.locale, root.fallbackLocale,
+        linkPlaceholder, host, interpolateMode, values
+      );
+    }
+    translated = this._warnDefault(
+      locale, linkPlaceholder, translated, host,
+      isArray(values) ? values : [values],
+      interpolateMode
+    );
+
+    if (this._modifiers.hasOwnProperty(formatterName)) {
+      translated = this._modifiers[formatterName](translated);
+    } else if (defaultModifiers.hasOwnProperty(formatterName)) {
+      translated = defaultModifiers[formatterName](translated);
+    }
+
+    visitedLinkStack.pop();
+
+    // Replace the link with the translated
+    ret = !translated ? ret : ret.replace(link, translated);
+  }
+
+  return ret
+};
+
+VueI18n.prototype._createMessageContext = function _createMessageContext (values) {
+  var _list = isArray(values) ? values : [];
+  var _named = isObject(values) ? values : {};
+  var list = function (index) { return _list[index]; };
+  var named = function (key) { return _named[key]; };
+  return {
+    list: list,
+    named: named
+  }
+};
+
+VueI18n.prototype._render = function _render (message, interpolateMode, values, path) {
+  if (isFunction(message)) {
+    return message(this._createMessageContext(values))
+  }
+
+  var ret = this._formatter.interpolate(message, values, path);
+
+  // If the custom formatter refuses to work - apply the default one
+  if (!ret) {
+    ret = defaultFormatter.interpolate(message, values, path);
+  }
+
+  // if interpolateMode is **not** 'string' ('row'),
+  // return the compiled data (e.g. ['foo', VNode, 'bar']) with formatter
+  return interpolateMode === 'string' && !isString(ret) ? ret.join('') : ret
+};
+
+VueI18n.prototype._appendItemToChain = function _appendItemToChain (chain, item, blocks) {
+  var follow = false;
+  if (!includes(chain, item)) {
+    follow = true;
+    if (item) {
+      follow = item[item.length - 1] !== '!';
+      item = item.replace(/!/g, '');
+      chain.push(item);
+      if (blocks && blocks[item]) {
+        follow = blocks[item];
+      }
+    }
+  }
+  return follow
+};
+
+VueI18n.prototype._appendLocaleToChain = function _appendLocaleToChain (chain, locale, blocks) {
+  var follow;
+  var tokens = locale.split('-');
+  do {
+    var item = tokens.join('-');
+    follow = this._appendItemToChain(chain, item, blocks);
+    tokens.splice(-1, 1);
+  } while (tokens.length && (follow === true))
+  return follow
+};
+
+VueI18n.prototype._appendBlockToChain = function _appendBlockToChain (chain, block, blocks) {
+  var follow = true;
+  for (var i = 0; (i < block.length) && (isBoolean(follow)); i++) {
+    var locale = block[i];
+    if (isString(locale)) {
+      follow = this._appendLocaleToChain(chain, locale, blocks);
+    }
+  }
+  return follow
+};
+
+VueI18n.prototype._getLocaleChain = function _getLocaleChain (start, fallbackLocale) {
+  if (start === '') { return [] }
+
+  if (!this._localeChainCache) {
+    this._localeChainCache = {};
+  }
+
+  var chain = this._localeChainCache[start];
+  if (!chain) {
+    if (!fallbackLocale) {
+      fallbackLocale = this.fallbackLocale;
+    }
+    chain = [];
+
+    // first block defined by start
+    var block = [start];
+
+    // while any intervening block found
+    while (isArray(block)) {
+      block = this._appendBlockToChain(
+        chain,
+        block,
+        fallbackLocale
+      );
+    }
+
+    // last block defined by default
+    var defaults;
+    if (isArray(fallbackLocale)) {
+      defaults = fallbackLocale;
+    } else if (isObject(fallbackLocale)) {
+      /* $FlowFixMe */
+      if (fallbackLocale['default']) {
+        defaults = fallbackLocale['default'];
+      } else {
+        defaults = null;
+      }
+    } else {
+      defaults = fallbackLocale;
+    }
+
+    // convert defaults to array
+    if (isString(defaults)) {
+      block = [defaults];
+    } else {
+      block = defaults;
+    }
+    if (block) {
+      this._appendBlockToChain(
+        chain,
+        block,
+        null
+      );
+    }
+    this._localeChainCache[start] = chain;
+  }
+  return chain
+};
+
+VueI18n.prototype._translate = function _translate (
+  messages,
+  locale,
+  fallback,
+  key,
+  host,
+  interpolateMode,
+  args
+) {
+  var chain = this._getLocaleChain(locale, fallback);
+  var res;
+  for (var i = 0; i < chain.length; i++) {
+    var step = chain[i];
+    res =
+      this._interpolate(step, messages[step], key, host, interpolateMode, args, [key]);
+    if (!isNull(res)) {
+      if (step !== locale && process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(("Fall back to translate the keypath '" + key + "' with '" + step + "' locale."));
+      }
+      return res
+    }
+  }
+  return null
+};
+
+VueI18n.prototype._t = function _t (key, _locale, messages, host) {
+    var ref;
+
+    var values = [], len = arguments.length - 4;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 4 ];
+  if (!key) { return '' }
+
+  var parsedArgs = parseArgs.apply(void 0, values);
+  var locale = parsedArgs.locale || _locale;
+
+  var ret = this._translate(
+    messages, locale, this.fallbackLocale, key,
+    host, 'string', parsedArgs.params
+  );
+  if (this._isFallbackRoot(ret)) {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+      warn(("Fall back to translate the keypath '" + key + "' with root locale."));
+    }
+    /* istanbul ignore if */
+    if (!this._root) { throw Error('unexpected error') }
+    return (ref = this._root).$t.apply(ref, [ key ].concat( values ))
+  } else {
+    ret = this._warnDefault(locale, key, ret, host, values, 'string');
+    if (this._postTranslation && ret !== null && ret !== undefined) {
+      ret = this._postTranslation(ret, key);
+    }
+    return ret
+  }
+};
+
+VueI18n.prototype.t = function t (key) {
+    var ref;
+
+    var values = [], len = arguments.length - 1;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 1 ];
+  return (ref = this)._t.apply(ref, [ key, this.locale, this._getMessages(), null ].concat( values ))
+};
+
+VueI18n.prototype._i = function _i (key, locale, messages, host, values) {
+  var ret =
+    this._translate(messages, locale, this.fallbackLocale, key, host, 'raw', values);
+  if (this._isFallbackRoot(ret)) {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key)) {
+      warn(("Fall back to interpolate the keypath '" + key + "' with root locale."));
+    }
+    if (!this._root) { throw Error('unexpected error') }
+    return this._root.$i18n.i(key, locale, values)
+  } else {
+    return this._warnDefault(locale, key, ret, host, [values], 'raw')
+  }
+};
+
+VueI18n.prototype.i = function i (key, locale, values) {
+  /* istanbul ignore if */
+  if (!key) { return '' }
+
+  if (!isString(locale)) {
+    locale = this.locale;
+  }
+
+  return this._i(key, locale, this._getMessages(), null, values)
+};
+
+VueI18n.prototype._tc = function _tc (
+  key,
+  _locale,
+  messages,
+  host,
+  choice
+) {
+    var ref;
+
+    var values = [], len = arguments.length - 5;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 5 ];
+  if (!key) { return '' }
+  if (choice === undefined) {
+    choice = 1;
+  }
+
+  var predefined = { 'count': choice, 'n': choice };
+  var parsedArgs = parseArgs.apply(void 0, values);
+  parsedArgs.params = Object.assign(predefined, parsedArgs.params);
+  values = parsedArgs.locale === null ? [parsedArgs.params] : [parsedArgs.locale, parsedArgs.params];
+  return this.fetchChoice((ref = this)._t.apply(ref, [ key, _locale, messages, host ].concat( values )), choice)
+};
+
+VueI18n.prototype.fetchChoice = function fetchChoice (message, choice) {
+  /* istanbul ignore if */
+  if (!message && !isString(message)) { return null }
+  var choices = message.split('|');
+
+  choice = this.getChoiceIndex(choice, choices.length);
+  if (!choices[choice]) { return message }
+  return choices[choice].trim()
+};
+
+VueI18n.prototype.tc = function tc (key, choice) {
+    var ref;
+
+    var values = [], len = arguments.length - 2;
+    while ( len-- > 0 ) values[ len ] = arguments[ len + 2 ];
+  return (ref = this)._tc.apply(ref, [ key, this.locale, this._getMessages(), null, choice ].concat( values ))
+};
+
+VueI18n.prototype._te = function _te (key, locale, messages) {
+    var args = [], len = arguments.length - 3;
+    while ( len-- > 0 ) args[ len ] = arguments[ len + 3 ];
+
+  var _locale = parseArgs.apply(void 0, args).locale || locale;
+  return this._exist(messages[_locale], key)
+};
+
+VueI18n.prototype.te = function te (key, locale) {
+  return this._te(key, this.locale, this._getMessages(), locale)
+};
+
+VueI18n.prototype.getLocaleMessage = function getLocaleMessage (locale) {
+  return looseClone(this._vm.messages[locale] || {})
+};
+
+VueI18n.prototype.setLocaleMessage = function setLocaleMessage (locale, message) {
+  if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+    this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
+  }
+  this._vm.$set(this._vm.messages, locale, message);
+};
+
+VueI18n.prototype.mergeLocaleMessage = function mergeLocaleMessage (locale, message) {
+  if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+    this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
+  }
+  this._vm.$set(this._vm.messages, locale, merge({}, this._vm.messages[locale] || {}, message));
+};
+
+VueI18n.prototype.getDateTimeFormat = function getDateTimeFormat (locale) {
+  return looseClone(this._vm.dateTimeFormats[locale] || {})
+};
+
+VueI18n.prototype.setDateTimeFormat = function setDateTimeFormat (locale, format) {
+  this._vm.$set(this._vm.dateTimeFormats, locale, format);
+  this._clearDateTimeFormat(locale, format);
+};
+
+VueI18n.prototype.mergeDateTimeFormat = function mergeDateTimeFormat (locale, format) {
+  this._vm.$set(this._vm.dateTimeFormats, locale, merge(this._vm.dateTimeFormats[locale] || {}, format));
+  this._clearDateTimeFormat(locale, format);
+};
+
+VueI18n.prototype._clearDateTimeFormat = function _clearDateTimeFormat (locale, format) {
+  for (var key in format) {
+    var id = locale + "__" + key;
+
+    if (!this._dateTimeFormatters.hasOwnProperty(id)) {
+      continue
+    }
+
+    delete this._dateTimeFormatters[id];
+  }
+};
+
+VueI18n.prototype._localizeDateTime = function _localizeDateTime (
+  value,
+  locale,
+  fallback,
+  dateTimeFormats,
+  key
+) {
+  var _locale = locale;
+  var formats = dateTimeFormats[_locale];
+
+  var chain = this._getLocaleChain(locale, fallback);
+  for (var i = 0; i < chain.length; i++) {
+    var current = _locale;
+    var step = chain[i];
+    formats = dateTimeFormats[step];
+    _locale = step;
+    // fallback locale
+    if (isNull(formats) || isNull(formats[key])) {
+      if (step !== locale && process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(("Fall back to '" + step + "' datetime formats from '" + current + "' datetime formats."));
+      }
+    } else {
+      break
+    }
+  }
+
+  if (isNull(formats) || isNull(formats[key])) {
+    return null
+  } else {
+    var format = formats[key];
+    var id = _locale + "__" + key;
+    var formatter = this._dateTimeFormatters[id];
+    if (!formatter) {
+      formatter = this._dateTimeFormatters[id] = new Intl.DateTimeFormat(_locale, format);
+    }
+    return formatter.format(value)
+  }
+};
+
+VueI18n.prototype._d = function _d (value, locale, key) {
+  /* istanbul ignore if */
+  if (process.env.NODE_ENV !== 'production' && !VueI18n.availabilities.dateTimeFormat) {
+    warn('Cannot format a Date value due to not supported Intl.DateTimeFormat.');
+    return ''
+  }
+
+  if (!key) {
+    return new Intl.DateTimeFormat(locale).format(value)
+  }
+
+  var ret =
+    this._localizeDateTime(value, locale, this.fallbackLocale, this._getDateTimeFormats(), key);
+  if (this._isFallbackRoot(ret)) {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+      warn(("Fall back to datetime localization of root: key '" + key + "'."));
+    }
+    /* istanbul ignore if */
+    if (!this._root) { throw Error('unexpected error') }
+    return this._root.$i18n.d(value, key, locale)
+  } else {
+    return ret || ''
+  }
+};
+
+VueI18n.prototype.d = function d (value) {
+    var args = [], len = arguments.length - 1;
+    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+
+  var locale = this.locale;
+  var key = null;
+
+  if (args.length === 1) {
+    if (isString(args[0])) {
+      key = args[0];
+    } else if (isObject(args[0])) {
+      if (args[0].locale) {
+        locale = args[0].locale;
+      }
+      if (args[0].key) {
+        key = args[0].key;
+      }
+    }
+  } else if (args.length === 2) {
+    if (isString(args[0])) {
+      key = args[0];
+    }
+    if (isString(args[1])) {
+      locale = args[1];
+    }
+  }
+
+  return this._d(value, locale, key)
+};
+
+VueI18n.prototype.getNumberFormat = function getNumberFormat (locale) {
+  return looseClone(this._vm.numberFormats[locale] || {})
+};
+
+VueI18n.prototype.setNumberFormat = function setNumberFormat (locale, format) {
+  this._vm.$set(this._vm.numberFormats, locale, format);
+  this._clearNumberFormat(locale, format);
+};
+
+VueI18n.prototype.mergeNumberFormat = function mergeNumberFormat (locale, format) {
+  this._vm.$set(this._vm.numberFormats, locale, merge(this._vm.numberFormats[locale] || {}, format));
+  this._clearNumberFormat(locale, format);
+};
+
+VueI18n.prototype._clearNumberFormat = function _clearNumberFormat (locale, format) {
+  for (var key in format) {
+    var id = locale + "__" + key;
+
+    if (!this._numberFormatters.hasOwnProperty(id)) {
+      continue
+    }
+
+    delete this._numberFormatters[id];
+  }
+};
+
+VueI18n.prototype._getNumberFormatter = function _getNumberFormatter (
+  value,
+  locale,
+  fallback,
+  numberFormats,
+  key,
+  options
+) {
+  var _locale = locale;
+  var formats = numberFormats[_locale];
+
+  var chain = this._getLocaleChain(locale, fallback);
+  for (var i = 0; i < chain.length; i++) {
+    var current = _locale;
+    var step = chain[i];
+    formats = numberFormats[step];
+    _locale = step;
+    // fallback locale
+    if (isNull(formats) || isNull(formats[key])) {
+      if (step !== locale && process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(("Fall back to '" + step + "' number formats from '" + current + "' number formats."));
+      }
+    } else {
+      break
+    }
+  }
+
+  if (isNull(formats) || isNull(formats[key])) {
+    return null
+  } else {
+    var format = formats[key];
+
+    var formatter;
+    if (options) {
+      // If options specified - create one time number formatter
+      formatter = new Intl.NumberFormat(_locale, Object.assign({}, format, options));
+    } else {
+      var id = _locale + "__" + key;
+      formatter = this._numberFormatters[id];
+      if (!formatter) {
+        formatter = this._numberFormatters[id] = new Intl.NumberFormat(_locale, format);
+      }
+    }
+    return formatter
+  }
+};
+
+VueI18n.prototype._n = function _n (value, locale, key, options) {
+  /* istanbul ignore if */
+  if (!VueI18n.availabilities.numberFormat) {
+    if (process.env.NODE_ENV !== 'production') {
+      warn('Cannot format a Number value due to not supported Intl.NumberFormat.');
+    }
+    return ''
+  }
+
+  if (!key) {
+    var nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
+    return nf.format(value)
+  }
+
+  var formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
+  var ret = formatter && formatter.format(value);
+  if (this._isFallbackRoot(ret)) {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+      warn(("Fall back to number localization of root: key '" + key + "'."));
+    }
+    /* istanbul ignore if */
+    if (!this._root) { throw Error('unexpected error') }
+    return this._root.$i18n.n(value, Object.assign({}, { key: key, locale: locale }, options))
+  } else {
+    return ret || ''
+  }
+};
+
+VueI18n.prototype.n = function n (value) {
+    var args = [], len = arguments.length - 1;
+    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+
+  var locale = this.locale;
+  var key = null;
+  var options = null;
+
+  if (args.length === 1) {
+    if (isString(args[0])) {
+      key = args[0];
+    } else if (isObject(args[0])) {
+      if (args[0].locale) {
+        locale = args[0].locale;
+      }
+      if (args[0].key) {
+        key = args[0].key;
+      }
+
+      // Filter out number format options only
+      options = Object.keys(args[0]).reduce(function (acc, key) {
+          var obj;
+
+        if (includes(numberFormatKeys, key)) {
+          return Object.assign({}, acc, ( obj = {}, obj[key] = args[0][key], obj ))
+        }
+        return acc
+      }, null);
+    }
+  } else if (args.length === 2) {
+    if (isString(args[0])) {
+      key = args[0];
+    }
+    if (isString(args[1])) {
+      locale = args[1];
+    }
+  }
+
+  return this._n(value, locale, key, options)
+};
+
+VueI18n.prototype._ntp = function _ntp (value, locale, key, options) {
+  /* istanbul ignore if */
+  if (!VueI18n.availabilities.numberFormat) {
+    if (process.env.NODE_ENV !== 'production') {
+      warn('Cannot format to parts a Number value due to not supported Intl.NumberFormat.');
+    }
+    return []
+  }
+
+  if (!key) {
+    var nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
+    return nf.formatToParts(value)
+  }
+
+  var formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
+  var ret = formatter && formatter.formatToParts(value);
+  if (this._isFallbackRoot(ret)) {
+    if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key)) {
+      warn(("Fall back to format number to parts of root: key '" + key + "' ."));
+    }
+    /* istanbul ignore if */
+    if (!this._root) { throw Error('unexpected error') }
+    return this._root.$i18n._ntp(value, locale, key, options)
+  } else {
+    return ret || []
+  }
+};
+
+Object.defineProperties( VueI18n.prototype, prototypeAccessors );
+
+var availabilities;
+// $FlowFixMe
+Object.defineProperty(VueI18n, 'availabilities', {
+  get: function get () {
+    if (!availabilities) {
+      var intlDefined = typeof Intl !== 'undefined';
+      availabilities = {
+        dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
+        numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
+      };
+    }
+
+    return availabilities
+  }
+});
+
+VueI18n.install = install;
+VueI18n.version = '8.21.0';
+
+export default VueI18n;

+ 2157 - 0
plugin/vue-i18n/dist/vue-i18n.js

@@ -0,0 +1,2157 @@
+/*!
+ * vue-i18n v8.21.0 
+ * (c) 2020 kazuya kawaguchi
+ * Released under the MIT License.
+ */
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+  typeof define === 'function' && define.amd ? define(factory) :
+  (global.VueI18n = factory());
+}(this, (function () { 'use strict';
+
+  /*  */
+
+  /**
+   * constants
+   */
+
+  var numberFormatKeys = [
+    'style',
+    'currency',
+    'currencyDisplay',
+    'useGrouping',
+    'minimumIntegerDigits',
+    'minimumFractionDigits',
+    'maximumFractionDigits',
+    'minimumSignificantDigits',
+    'maximumSignificantDigits',
+    'localeMatcher',
+    'formatMatcher',
+    'unit'
+  ];
+
+  /**
+   * utilities
+   */
+
+  function warn (msg, err) {
+    if (typeof console !== 'undefined') {
+      console.warn('[vue-i18n] ' + msg);
+      /* istanbul ignore if */
+      if (err) {
+        console.warn(err.stack);
+      }
+    }
+  }
+
+  function error (msg, err) {
+    if (typeof console !== 'undefined') {
+      console.error('[vue-i18n] ' + msg);
+      /* istanbul ignore if */
+      if (err) {
+        console.error(err.stack);
+      }
+    }
+  }
+
+  var isArray = Array.isArray;
+
+  function isObject (obj) {
+    return obj !== null && typeof obj === 'object'
+  }
+
+  function isBoolean (val) {
+    return typeof val === 'boolean'
+  }
+
+  function isString (val) {
+    return typeof val === 'string'
+  }
+
+  var toString = Object.prototype.toString;
+  var OBJECT_STRING = '[object Object]';
+  function isPlainObject (obj) {
+    return toString.call(obj) === OBJECT_STRING
+  }
+
+  function isNull (val) {
+    return val === null || val === undefined
+  }
+
+  function isFunction (val) {
+    return typeof val === 'function'
+  }
+
+  function parseArgs () {
+    var args = [], len = arguments.length;
+    while ( len-- ) args[ len ] = arguments[ len ];
+
+    var locale = null;
+    var params = null;
+    if (args.length === 1) {
+      if (isObject(args[0]) || isArray(args[0])) {
+        params = args[0];
+      } else if (typeof args[0] === 'string') {
+        locale = args[0];
+      }
+    } else if (args.length === 2) {
+      if (typeof args[0] === 'string') {
+        locale = args[0];
+      }
+      /* istanbul ignore if */
+      if (isObject(args[1]) || isArray(args[1])) {
+        params = args[1];
+      }
+    }
+
+    return { locale: locale, params: params }
+  }
+
+  function looseClone (obj) {
+    return JSON.parse(JSON.stringify(obj))
+  }
+
+  function remove (arr, item) {
+    if (arr.length) {
+      var index = arr.indexOf(item);
+      if (index > -1) {
+        return arr.splice(index, 1)
+      }
+    }
+  }
+
+  function includes (arr, item) {
+    return !!~arr.indexOf(item)
+  }
+
+  var hasOwnProperty = Object.prototype.hasOwnProperty;
+  function hasOwn (obj, key) {
+    return hasOwnProperty.call(obj, key)
+  }
+
+  function merge (target) {
+    var arguments$1 = arguments;
+
+    var output = Object(target);
+    for (var i = 1; i < arguments.length; i++) {
+      var source = arguments$1[i];
+      if (source !== undefined && source !== null) {
+        var key = (void 0);
+        for (key in source) {
+          if (hasOwn(source, key)) {
+            if (isObject(source[key])) {
+              output[key] = merge(output[key], source[key]);
+            } else {
+              output[key] = source[key];
+            }
+          }
+        }
+      }
+    }
+    return output
+  }
+
+  function looseEqual (a, b) {
+    if (a === b) { return true }
+    var isObjectA = isObject(a);
+    var isObjectB = isObject(b);
+    if (isObjectA && isObjectB) {
+      try {
+        var isArrayA = isArray(a);
+        var isArrayB = isArray(b);
+        if (isArrayA && isArrayB) {
+          return a.length === b.length && a.every(function (e, i) {
+            return looseEqual(e, b[i])
+          })
+        } else if (!isArrayA && !isArrayB) {
+          var keysA = Object.keys(a);
+          var keysB = Object.keys(b);
+          return keysA.length === keysB.length && keysA.every(function (key) {
+            return looseEqual(a[key], b[key])
+          })
+        } else {
+          /* istanbul ignore next */
+          return false
+        }
+      } catch (e) {
+        /* istanbul ignore next */
+        return false
+      }
+    } else if (!isObjectA && !isObjectB) {
+      return String(a) === String(b)
+    } else {
+      return false
+    }
+  }
+
+  /*  */
+
+  function extend (Vue) {
+    if (!Vue.prototype.hasOwnProperty('$i18n')) {
+      // $FlowFixMe
+      Object.defineProperty(Vue.prototype, '$i18n', {
+        get: function get () { return this._i18n }
+      });
+    }
+
+    Vue.prototype.$t = function (key) {
+      var values = [], len = arguments.length - 1;
+      while ( len-- > 0 ) values[ len ] = arguments[ len + 1 ];
+
+      var i18n = this.$i18n;
+      return i18n._t.apply(i18n, [ key, i18n.locale, i18n._getMessages(), this ].concat( values ))
+    };
+
+    Vue.prototype.$tc = function (key, choice) {
+      var values = [], len = arguments.length - 2;
+      while ( len-- > 0 ) values[ len ] = arguments[ len + 2 ];
+
+      var i18n = this.$i18n;
+      return i18n._tc.apply(i18n, [ key, i18n.locale, i18n._getMessages(), this, choice ].concat( values ))
+    };
+
+    Vue.prototype.$te = function (key, locale) {
+      var i18n = this.$i18n;
+      return i18n._te(key, i18n.locale, i18n._getMessages(), locale)
+    };
+
+    Vue.prototype.$d = function (value) {
+      var ref;
+
+      var args = [], len = arguments.length - 1;
+      while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+      return (ref = this.$i18n).d.apply(ref, [ value ].concat( args ))
+    };
+
+    Vue.prototype.$n = function (value) {
+      var ref;
+
+      var args = [], len = arguments.length - 1;
+      while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+      return (ref = this.$i18n).n.apply(ref, [ value ].concat( args ))
+    };
+  }
+
+  /*  */
+
+  var mixin = {
+    beforeCreate: function beforeCreate () {
+      var options = this.$options;
+      options.i18n = options.i18n || (options.__i18n ? {} : null);
+
+      if (options.i18n) {
+        if (options.i18n instanceof VueI18n) {
+          // init locale messages via custom blocks
+          if (options.__i18n) {
+            try {
+              var localeMessages = {};
+              options.__i18n.forEach(function (resource) {
+                localeMessages = merge(localeMessages, JSON.parse(resource));
+              });
+              Object.keys(localeMessages).forEach(function (locale) {
+                options.i18n.mergeLocaleMessage(locale, localeMessages[locale]);
+              });
+            } catch (e) {
+              {
+                error("Cannot parse locale messages via custom blocks.", e);
+              }
+            }
+          }
+          this._i18n = options.i18n;
+          this._i18nWatcher = this._i18n.watchI18nData();
+        } else if (isPlainObject(options.i18n)) {
+          var rootI18n = this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n
+            ? this.$root.$i18n
+            : null;
+          // component local i18n
+          if (rootI18n) {
+            options.i18n.root = this.$root;
+            options.i18n.formatter = rootI18n.formatter;
+            options.i18n.fallbackLocale = rootI18n.fallbackLocale;
+            options.i18n.formatFallbackMessages = rootI18n.formatFallbackMessages;
+            options.i18n.silentTranslationWarn = rootI18n.silentTranslationWarn;
+            options.i18n.silentFallbackWarn = rootI18n.silentFallbackWarn;
+            options.i18n.pluralizationRules = rootI18n.pluralizationRules;
+            options.i18n.preserveDirectiveContent = rootI18n.preserveDirectiveContent;
+          }
+
+          // init locale messages via custom blocks
+          if (options.__i18n) {
+            try {
+              var localeMessages$1 = {};
+              options.__i18n.forEach(function (resource) {
+                localeMessages$1 = merge(localeMessages$1, JSON.parse(resource));
+              });
+              options.i18n.messages = localeMessages$1;
+            } catch (e) {
+              {
+                warn("Cannot parse locale messages via custom blocks.", e);
+              }
+            }
+          }
+
+          var ref = options.i18n;
+          var sharedMessages = ref.sharedMessages;
+          if (sharedMessages && isPlainObject(sharedMessages)) {
+            options.i18n.messages = merge(options.i18n.messages, sharedMessages);
+          }
+
+          this._i18n = new VueI18n(options.i18n);
+          this._i18nWatcher = this._i18n.watchI18nData();
+
+          if (options.i18n.sync === undefined || !!options.i18n.sync) {
+            this._localeWatcher = this.$i18n.watchLocale();
+          }
+
+          if (rootI18n) {
+            rootI18n.onComponentInstanceCreated(this._i18n);
+          }
+        } else {
+          {
+            warn("Cannot be interpreted 'i18n' option.");
+          }
+        }
+      } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
+        // root i18n
+        this._i18n = this.$root.$i18n;
+      } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
+        // parent i18n
+        this._i18n = options.parent.$i18n;
+      }
+    },
+
+    beforeMount: function beforeMount () {
+      var options = this.$options;
+      options.i18n = options.i18n || (options.__i18n ? {} : null);
+
+      if (options.i18n) {
+        if (options.i18n instanceof VueI18n) {
+          // init locale messages via custom blocks
+          this._i18n.subscribeDataChanging(this);
+          this._subscribing = true;
+        } else if (isPlainObject(options.i18n)) {
+          this._i18n.subscribeDataChanging(this);
+          this._subscribing = true;
+        } else {
+          {
+            warn("Cannot be interpreted 'i18n' option.");
+          }
+        }
+      } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
+        this._i18n.subscribeDataChanging(this);
+        this._subscribing = true;
+      } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
+        this._i18n.subscribeDataChanging(this);
+        this._subscribing = true;
+      }
+    },
+
+    beforeDestroy: function beforeDestroy () {
+      if (!this._i18n) { return }
+
+      var self = this;
+      this.$nextTick(function () {
+        if (self._subscribing) {
+          self._i18n.unsubscribeDataChanging(self);
+          delete self._subscribing;
+        }
+
+        if (self._i18nWatcher) {
+          self._i18nWatcher();
+          self._i18n.destroyVM();
+          delete self._i18nWatcher;
+        }
+
+        if (self._localeWatcher) {
+          self._localeWatcher();
+          delete self._localeWatcher;
+        }
+      });
+    }
+  };
+
+  /*  */
+
+  var interpolationComponent = {
+    name: 'i18n',
+    functional: true,
+    props: {
+      tag: {
+        type: [String, Boolean, Object],
+        default: 'span'
+      },
+      path: {
+        type: String,
+        required: true
+      },
+      locale: {
+        type: String
+      },
+      places: {
+        type: [Array, Object]
+      }
+    },
+    render: function render (h, ref) {
+      var data = ref.data;
+      var parent = ref.parent;
+      var props = ref.props;
+      var slots = ref.slots;
+
+      var $i18n = parent.$i18n;
+      if (!$i18n) {
+        {
+          warn('Cannot find VueI18n instance!');
+        }
+        return
+      }
+
+      var path = props.path;
+      var locale = props.locale;
+      var places = props.places;
+      var params = slots();
+      var children = $i18n.i(
+        path,
+        locale,
+        onlyHasDefaultPlace(params) || places
+          ? useLegacyPlaces(params.default, places)
+          : params
+      );
+
+      var tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span';
+      return tag ? h(tag, data, children) : children
+    }
+  };
+
+  function onlyHasDefaultPlace (params) {
+    var prop;
+    for (prop in params) {
+      if (prop !== 'default') { return false }
+    }
+    return Boolean(prop)
+  }
+
+  function useLegacyPlaces (children, places) {
+    var params = places ? createParamsFromPlaces(places) : {};
+
+    if (!children) { return params }
+
+    // Filter empty text nodes
+    children = children.filter(function (child) {
+      return child.tag || child.text.trim() !== ''
+    });
+
+    var everyPlace = children.every(vnodeHasPlaceAttribute);
+    if (everyPlace) {
+      warn('`place` attribute is deprecated in next major version. Please switch to Vue slots.');
+    }
+
+    return children.reduce(
+      everyPlace ? assignChildPlace : assignChildIndex,
+      params
+    )
+  }
+
+  function createParamsFromPlaces (places) {
+    {
+      warn('`places` prop is deprecated in next major version. Please switch to Vue slots.');
+    }
+
+    return Array.isArray(places)
+      ? places.reduce(assignChildIndex, {})
+      : Object.assign({}, places)
+  }
+
+  function assignChildPlace (params, child) {
+    if (child.data && child.data.attrs && child.data.attrs.place) {
+      params[child.data.attrs.place] = child;
+    }
+    return params
+  }
+
+  function assignChildIndex (params, child, index) {
+    params[index] = child;
+    return params
+  }
+
+  function vnodeHasPlaceAttribute (vnode) {
+    return Boolean(vnode.data && vnode.data.attrs && vnode.data.attrs.place)
+  }
+
+  /*  */
+
+  var numberComponent = {
+    name: 'i18n-n',
+    functional: true,
+    props: {
+      tag: {
+        type: [String, Boolean, Object],
+        default: 'span'
+      },
+      value: {
+        type: Number,
+        required: true
+      },
+      format: {
+        type: [String, Object]
+      },
+      locale: {
+        type: String
+      }
+    },
+    render: function render (h, ref) {
+      var props = ref.props;
+      var parent = ref.parent;
+      var data = ref.data;
+
+      var i18n = parent.$i18n;
+
+      if (!i18n) {
+        {
+          warn('Cannot find VueI18n instance!');
+        }
+        return null
+      }
+
+      var key = null;
+      var options = null;
+
+      if (isString(props.format)) {
+        key = props.format;
+      } else if (isObject(props.format)) {
+        if (props.format.key) {
+          key = props.format.key;
+        }
+
+        // Filter out number format options only
+        options = Object.keys(props.format).reduce(function (acc, prop) {
+          var obj;
+
+          if (includes(numberFormatKeys, prop)) {
+            return Object.assign({}, acc, ( obj = {}, obj[prop] = props.format[prop], obj ))
+          }
+          return acc
+        }, null);
+      }
+
+      var locale = props.locale || i18n.locale;
+      var parts = i18n._ntp(props.value, locale, key, options);
+
+      var values = parts.map(function (part, index) {
+        var obj;
+
+        var slot = data.scopedSlots && data.scopedSlots[part.type];
+        return slot ? slot(( obj = {}, obj[part.type] = part.value, obj.index = index, obj.parts = parts, obj )) : part.value
+      });
+
+      var tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span';
+      return tag
+        ? h(tag, {
+          attrs: data.attrs,
+          'class': data['class'],
+          staticClass: data.staticClass
+        }, values)
+        : values
+    }
+  };
+
+  /*  */
+
+  function bind (el, binding, vnode) {
+    if (!assert(el, vnode)) { return }
+
+    t(el, binding, vnode);
+  }
+
+  function update (el, binding, vnode, oldVNode) {
+    if (!assert(el, vnode)) { return }
+
+    var i18n = vnode.context.$i18n;
+    if (localeEqual(el, vnode) &&
+      (looseEqual(binding.value, binding.oldValue) &&
+       looseEqual(el._localeMessage, i18n.getLocaleMessage(i18n.locale)))) { return }
+
+    t(el, binding, vnode);
+  }
+
+  function unbind (el, binding, vnode, oldVNode) {
+    var vm = vnode.context;
+    if (!vm) {
+      warn('Vue instance does not exists in VNode context');
+      return
+    }
+
+    var i18n = vnode.context.$i18n || {};
+    if (!binding.modifiers.preserve && !i18n.preserveDirectiveContent) {
+      el.textContent = '';
+    }
+    el._vt = undefined;
+    delete el['_vt'];
+    el._locale = undefined;
+    delete el['_locale'];
+    el._localeMessage = undefined;
+    delete el['_localeMessage'];
+  }
+
+  function assert (el, vnode) {
+    var vm = vnode.context;
+    if (!vm) {
+      warn('Vue instance does not exists in VNode context');
+      return false
+    }
+
+    if (!vm.$i18n) {
+      warn('VueI18n instance does not exists in Vue instance');
+      return false
+    }
+
+    return true
+  }
+
+  function localeEqual (el, vnode) {
+    var vm = vnode.context;
+    return el._locale === vm.$i18n.locale
+  }
+
+  function t (el, binding, vnode) {
+    var ref$1, ref$2;
+
+    var value = binding.value;
+
+    var ref = parseValue(value);
+    var path = ref.path;
+    var locale = ref.locale;
+    var args = ref.args;
+    var choice = ref.choice;
+    if (!path && !locale && !args) {
+      warn('value type not supported');
+      return
+    }
+
+    if (!path) {
+      warn('`path` is required in v-t directive');
+      return
+    }
+
+    var vm = vnode.context;
+    if (choice != null) {
+      el._vt = el.textContent = (ref$1 = vm.$i18n).tc.apply(ref$1, [ path, choice ].concat( makeParams(locale, args) ));
+    } else {
+      el._vt = el.textContent = (ref$2 = vm.$i18n).t.apply(ref$2, [ path ].concat( makeParams(locale, args) ));
+    }
+    el._locale = vm.$i18n.locale;
+    el._localeMessage = vm.$i18n.getLocaleMessage(vm.$i18n.locale);
+  }
+
+  function parseValue (value) {
+    var path;
+    var locale;
+    var args;
+    var choice;
+
+    if (isString(value)) {
+      path = value;
+    } else if (isPlainObject(value)) {
+      path = value.path;
+      locale = value.locale;
+      args = value.args;
+      choice = value.choice;
+    }
+
+    return { path: path, locale: locale, args: args, choice: choice }
+  }
+
+  function makeParams (locale, args) {
+    var params = [];
+
+    locale && params.push(locale);
+    if (args && (Array.isArray(args) || isPlainObject(args))) {
+      params.push(args);
+    }
+
+    return params
+  }
+
+  var Vue;
+
+  function install (_Vue) {
+    /* istanbul ignore if */
+    if (install.installed && _Vue === Vue) {
+      warn('already installed.');
+      return
+    }
+    install.installed = true;
+
+    Vue = _Vue;
+
+    var version = (Vue.version && Number(Vue.version.split('.')[0])) || -1;
+    /* istanbul ignore if */
+    if (version < 2) {
+      warn(("vue-i18n (" + (install.version) + ") need to use Vue 2.0 or later (Vue: " + (Vue.version) + ")."));
+      return
+    }
+
+    extend(Vue);
+    Vue.mixin(mixin);
+    Vue.directive('t', { bind: bind, update: update, unbind: unbind });
+    Vue.component(interpolationComponent.name, interpolationComponent);
+    Vue.component(numberComponent.name, numberComponent);
+
+    // use simple mergeStrategies to prevent i18n instance lose '__proto__'
+    var strats = Vue.config.optionMergeStrategies;
+    strats.i18n = function (parentVal, childVal) {
+      return childVal === undefined
+        ? parentVal
+        : childVal
+    };
+  }
+
+  /*  */
+
+  var BaseFormatter = function BaseFormatter () {
+    this._caches = Object.create(null);
+  };
+
+  BaseFormatter.prototype.interpolate = function interpolate (message, values) {
+    if (!values) {
+      return [message]
+    }
+    var tokens = this._caches[message];
+    if (!tokens) {
+      tokens = parse(message);
+      this._caches[message] = tokens;
+    }
+    return compile(tokens, values)
+  };
+
+
+
+  var RE_TOKEN_LIST_VALUE = /^(?:\d)+/;
+  var RE_TOKEN_NAMED_VALUE = /^(?:\w)+/;
+
+  function parse (format) {
+    var tokens = [];
+    var position = 0;
+
+    var text = '';
+    while (position < format.length) {
+      var char = format[position++];
+      if (char === '{') {
+        if (text) {
+          tokens.push({ type: 'text', value: text });
+        }
+
+        text = '';
+        var sub = '';
+        char = format[position++];
+        while (char !== undefined && char !== '}') {
+          sub += char;
+          char = format[position++];
+        }
+        var isClosed = char === '}';
+
+        var type = RE_TOKEN_LIST_VALUE.test(sub)
+          ? 'list'
+          : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
+            ? 'named'
+            : 'unknown';
+        tokens.push({ value: sub, type: type });
+      } else if (char === '%') {
+        // when found rails i18n syntax, skip text capture
+        if (format[(position)] !== '{') {
+          text += char;
+        }
+      } else {
+        text += char;
+      }
+    }
+
+    text && tokens.push({ type: 'text', value: text });
+
+    return tokens
+  }
+
+  function compile (tokens, values) {
+    var compiled = [];
+    var index = 0;
+
+    var mode = Array.isArray(values)
+      ? 'list'
+      : isObject(values)
+        ? 'named'
+        : 'unknown';
+    if (mode === 'unknown') { return compiled }
+
+    while (index < tokens.length) {
+      var token = tokens[index];
+      switch (token.type) {
+        case 'text':
+          compiled.push(token.value);
+          break
+        case 'list':
+          compiled.push(values[parseInt(token.value, 10)]);
+          break
+        case 'named':
+          if (mode === 'named') {
+            compiled.push((values)[token.value]);
+          } else {
+            {
+              warn(("Type of token '" + (token.type) + "' and format of value '" + mode + "' don't match!"));
+            }
+          }
+          break
+        case 'unknown':
+          {
+            warn("Detect 'unknown' type of token!");
+          }
+          break
+      }
+      index++;
+    }
+
+    return compiled
+  }
+
+  /*  */
+
+  /**
+   *  Path parser
+   *  - Inspired:
+   *    Vue.js Path parser
+   */
+
+  // actions
+  var APPEND = 0;
+  var PUSH = 1;
+  var INC_SUB_PATH_DEPTH = 2;
+  var PUSH_SUB_PATH = 3;
+
+  // states
+  var BEFORE_PATH = 0;
+  var IN_PATH = 1;
+  var BEFORE_IDENT = 2;
+  var IN_IDENT = 3;
+  var IN_SUB_PATH = 4;
+  var IN_SINGLE_QUOTE = 5;
+  var IN_DOUBLE_QUOTE = 6;
+  var AFTER_PATH = 7;
+  var ERROR = 8;
+
+  var pathStateMachine = [];
+
+  pathStateMachine[BEFORE_PATH] = {
+    'ws': [BEFORE_PATH],
+    'ident': [IN_IDENT, APPEND],
+    '[': [IN_SUB_PATH],
+    'eof': [AFTER_PATH]
+  };
+
+  pathStateMachine[IN_PATH] = {
+    'ws': [IN_PATH],
+    '.': [BEFORE_IDENT],
+    '[': [IN_SUB_PATH],
+    'eof': [AFTER_PATH]
+  };
+
+  pathStateMachine[BEFORE_IDENT] = {
+    'ws': [BEFORE_IDENT],
+    'ident': [IN_IDENT, APPEND],
+    '0': [IN_IDENT, APPEND],
+    'number': [IN_IDENT, APPEND]
+  };
+
+  pathStateMachine[IN_IDENT] = {
+    'ident': [IN_IDENT, APPEND],
+    '0': [IN_IDENT, APPEND],
+    'number': [IN_IDENT, APPEND],
+    'ws': [IN_PATH, PUSH],
+    '.': [BEFORE_IDENT, PUSH],
+    '[': [IN_SUB_PATH, PUSH],
+    'eof': [AFTER_PATH, PUSH]
+  };
+
+  pathStateMachine[IN_SUB_PATH] = {
+    "'": [IN_SINGLE_QUOTE, APPEND],
+    '"': [IN_DOUBLE_QUOTE, APPEND],
+    '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH],
+    ']': [IN_PATH, PUSH_SUB_PATH],
+    'eof': ERROR,
+    'else': [IN_SUB_PATH, APPEND]
+  };
+
+  pathStateMachine[IN_SINGLE_QUOTE] = {
+    "'": [IN_SUB_PATH, APPEND],
+    'eof': ERROR,
+    'else': [IN_SINGLE_QUOTE, APPEND]
+  };
+
+  pathStateMachine[IN_DOUBLE_QUOTE] = {
+    '"': [IN_SUB_PATH, APPEND],
+    'eof': ERROR,
+    'else': [IN_DOUBLE_QUOTE, APPEND]
+  };
+
+  /**
+   * Check if an expression is a literal value.
+   */
+
+  var literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
+  function isLiteral (exp) {
+    return literalValueRE.test(exp)
+  }
+
+  /**
+   * Strip quotes from a string
+   */
+
+  function stripQuotes (str) {
+    var a = str.charCodeAt(0);
+    var b = str.charCodeAt(str.length - 1);
+    return a === b && (a === 0x22 || a === 0x27)
+      ? str.slice(1, -1)
+      : str
+  }
+
+  /**
+   * Determine the type of a character in a keypath.
+   */
+
+  function getPathCharType (ch) {
+    if (ch === undefined || ch === null) { return 'eof' }
+
+    var code = ch.charCodeAt(0);
+
+    switch (code) {
+      case 0x5B: // [
+      case 0x5D: // ]
+      case 0x2E: // .
+      case 0x22: // "
+      case 0x27: // '
+        return ch
+
+      case 0x5F: // _
+      case 0x24: // $
+      case 0x2D: // -
+        return 'ident'
+
+      case 0x09: // Tab
+      case 0x0A: // Newline
+      case 0x0D: // Return
+      case 0xA0:  // No-break space
+      case 0xFEFF:  // Byte Order Mark
+      case 0x2028:  // Line Separator
+      case 0x2029:  // Paragraph Separator
+        return 'ws'
+    }
+
+    return 'ident'
+  }
+
+  /**
+   * Format a subPath, return its plain form if it is
+   * a literal string or number. Otherwise prepend the
+   * dynamic indicator (*).
+   */
+
+  function formatSubPath (path) {
+    var trimmed = path.trim();
+    // invalid leading 0
+    if (path.charAt(0) === '0' && isNaN(path)) { return false }
+
+    return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed
+  }
+
+  /**
+   * Parse a string path into an array of segments
+   */
+
+  function parse$1 (path) {
+    var keys = [];
+    var index = -1;
+    var mode = BEFORE_PATH;
+    var subPathDepth = 0;
+    var c;
+    var key;
+    var newChar;
+    var type;
+    var transition;
+    var action;
+    var typeMap;
+    var actions = [];
+
+    actions[PUSH] = function () {
+      if (key !== undefined) {
+        keys.push(key);
+        key = undefined;
+      }
+    };
+
+    actions[APPEND] = function () {
+      if (key === undefined) {
+        key = newChar;
+      } else {
+        key += newChar;
+      }
+    };
+
+    actions[INC_SUB_PATH_DEPTH] = function () {
+      actions[APPEND]();
+      subPathDepth++;
+    };
+
+    actions[PUSH_SUB_PATH] = function () {
+      if (subPathDepth > 0) {
+        subPathDepth--;
+        mode = IN_SUB_PATH;
+        actions[APPEND]();
+      } else {
+        subPathDepth = 0;
+        if (key === undefined) { return false }
+        key = formatSubPath(key);
+        if (key === false) {
+          return false
+        } else {
+          actions[PUSH]();
+        }
+      }
+    };
+
+    function maybeUnescapeQuote () {
+      var nextChar = path[index + 1];
+      if ((mode === IN_SINGLE_QUOTE && nextChar === "'") ||
+        (mode === IN_DOUBLE_QUOTE && nextChar === '"')) {
+        index++;
+        newChar = '\\' + nextChar;
+        actions[APPEND]();
+        return true
+      }
+    }
+
+    while (mode !== null) {
+      index++;
+      c = path[index];
+
+      if (c === '\\' && maybeUnescapeQuote()) {
+        continue
+      }
+
+      type = getPathCharType(c);
+      typeMap = pathStateMachine[mode];
+      transition = typeMap[type] || typeMap['else'] || ERROR;
+
+      if (transition === ERROR) {
+        return // parse error
+      }
+
+      mode = transition[0];
+      action = actions[transition[1]];
+      if (action) {
+        newChar = transition[2];
+        newChar = newChar === undefined
+          ? c
+          : newChar;
+        if (action() === false) {
+          return
+        }
+      }
+
+      if (mode === AFTER_PATH) {
+        return keys
+      }
+    }
+  }
+
+
+
+
+
+  var I18nPath = function I18nPath () {
+    this._cache = Object.create(null);
+  };
+
+  /**
+   * External parse that check for a cache hit first
+   */
+  I18nPath.prototype.parsePath = function parsePath (path) {
+    var hit = this._cache[path];
+    if (!hit) {
+      hit = parse$1(path);
+      if (hit) {
+        this._cache[path] = hit;
+      }
+    }
+    return hit || []
+  };
+
+  /**
+   * Get path value from path string
+   */
+  I18nPath.prototype.getPathValue = function getPathValue (obj, path) {
+    if (!isObject(obj)) { return null }
+
+    var paths = this.parsePath(path);
+    if (paths.length === 0) {
+      return null
+    } else {
+      var length = paths.length;
+      var last = obj;
+      var i = 0;
+      while (i < length) {
+        var value = last[paths[i]];
+        if (value === undefined) {
+          return null
+        }
+        last = value;
+        i++;
+      }
+
+      return last
+    }
+  };
+
+  /*  */
+
+
+
+  var htmlTagMatcher = /<\/?[\w\s="/.':;#-\/]+>/;
+  var linkKeyMatcher = /(?:@(?:\.[a-z]+)?:(?:[\w\-_|.]+|\([\w\-_|.]+\)))/g;
+  var linkKeyPrefixMatcher = /^@(?:\.([a-z]+))?:/;
+  var bracketsMatcher = /[()]/g;
+  var defaultModifiers = {
+    'upper': function (str) { return str.toLocaleUpperCase(); },
+    'lower': function (str) { return str.toLocaleLowerCase(); },
+    'capitalize': function (str) { return ("" + (str.charAt(0).toLocaleUpperCase()) + (str.substr(1))); }
+  };
+
+  var defaultFormatter = new BaseFormatter();
+
+  var VueI18n = function VueI18n (options) {
+    var this$1 = this;
+    if ( options === void 0 ) options = {};
+
+    // Auto install if it is not done yet and `window` has `Vue`.
+    // To allow users to avoid auto-installation in some cases,
+    // this code should be placed here. See #290
+    /* istanbul ignore if */
+    if (!Vue && typeof window !== 'undefined' && window.Vue) {
+      install(window.Vue);
+    }
+
+    var locale = options.locale || 'en-US';
+    var fallbackLocale = options.fallbackLocale === false
+      ? false
+      : options.fallbackLocale || 'en-US';
+    var messages = options.messages || {};
+    var dateTimeFormats = options.dateTimeFormats || {};
+    var numberFormats = options.numberFormats || {};
+
+    this._vm = null;
+    this._formatter = options.formatter || defaultFormatter;
+    this._modifiers = options.modifiers || {};
+    this._missing = options.missing || null;
+    this._root = options.root || null;
+    this._sync = options.sync === undefined ? true : !!options.sync;
+    this._fallbackRoot = options.fallbackRoot === undefined
+      ? true
+      : !!options.fallbackRoot;
+    this._formatFallbackMessages = options.formatFallbackMessages === undefined
+      ? false
+      : !!options.formatFallbackMessages;
+    this._silentTranslationWarn = options.silentTranslationWarn === undefined
+      ? false
+      : options.silentTranslationWarn;
+    this._silentFallbackWarn = options.silentFallbackWarn === undefined
+      ? false
+      : !!options.silentFallbackWarn;
+    this._dateTimeFormatters = {};
+    this._numberFormatters = {};
+    this._path = new I18nPath();
+    this._dataListeners = [];
+    this._componentInstanceCreatedListener = options.componentInstanceCreatedListener || null;
+    this._preserveDirectiveContent = options.preserveDirectiveContent === undefined
+      ? false
+      : !!options.preserveDirectiveContent;
+    this.pluralizationRules = options.pluralizationRules || {};
+    this._warnHtmlInMessage = options.warnHtmlInMessage || 'off';
+    this._postTranslation = options.postTranslation || null;
+
+    /**
+     * @param choice {number} a choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)`
+     * @param choicesLength {number} an overall amount of available choices
+     * @returns a final choice index
+    */
+    this.getChoiceIndex = function (choice, choicesLength) {
+      var thisPrototype = Object.getPrototypeOf(this$1);
+      if (thisPrototype && thisPrototype.getChoiceIndex) {
+        var prototypeGetChoiceIndex = (thisPrototype.getChoiceIndex);
+        return (prototypeGetChoiceIndex).call(this$1, choice, choicesLength)
+      }
+
+      // Default (old) getChoiceIndex implementation - english-compatible
+      var defaultImpl = function (_choice, _choicesLength) {
+        _choice = Math.abs(_choice);
+
+        if (_choicesLength === 2) {
+          return _choice
+            ? _choice > 1
+              ? 1
+              : 0
+            : 1
+        }
+
+        return _choice ? Math.min(_choice, 2) : 0
+      };
+
+      if (this$1.locale in this$1.pluralizationRules) {
+        return this$1.pluralizationRules[this$1.locale].apply(this$1, [choice, choicesLength])
+      } else {
+        return defaultImpl(choice, choicesLength)
+      }
+    };
+
+
+    this._exist = function (message, key) {
+      if (!message || !key) { return false }
+      if (!isNull(this$1._path.getPathValue(message, key))) { return true }
+      // fallback for flat key
+      if (message[key]) { return true }
+      return false
+    };
+
+    if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+      Object.keys(messages).forEach(function (locale) {
+        this$1._checkLocaleMessage(locale, this$1._warnHtmlInMessage, messages[locale]);
+      });
+    }
+
+    this._initVM({
+      locale: locale,
+      fallbackLocale: fallbackLocale,
+      messages: messages,
+      dateTimeFormats: dateTimeFormats,
+      numberFormats: numberFormats
+    });
+  };
+
+  var prototypeAccessors = { vm: { configurable: true },messages: { configurable: true },dateTimeFormats: { configurable: true },numberFormats: { configurable: true },availableLocales: { configurable: true },locale: { configurable: true },fallbackLocale: { configurable: true },formatFallbackMessages: { configurable: true },missing: { configurable: true },formatter: { configurable: true },silentTranslationWarn: { configurable: true },silentFallbackWarn: { configurable: true },preserveDirectiveContent: { configurable: true },warnHtmlInMessage: { configurable: true },postTranslation: { configurable: true } };
+
+  VueI18n.prototype._checkLocaleMessage = function _checkLocaleMessage (locale, level, message) {
+    var paths = [];
+
+    var fn = function (level, locale, message, paths) {
+      if (isPlainObject(message)) {
+        Object.keys(message).forEach(function (key) {
+          var val = message[key];
+          if (isPlainObject(val)) {
+            paths.push(key);
+            paths.push('.');
+            fn(level, locale, val, paths);
+            paths.pop();
+            paths.pop();
+          } else {
+            paths.push(key);
+            fn(level, locale, val, paths);
+            paths.pop();
+          }
+        });
+      } else if (isArray(message)) {
+        message.forEach(function (item, index) {
+          if (isPlainObject(item)) {
+            paths.push(("[" + index + "]"));
+            paths.push('.');
+            fn(level, locale, item, paths);
+            paths.pop();
+            paths.pop();
+          } else {
+            paths.push(("[" + index + "]"));
+            fn(level, locale, item, paths);
+            paths.pop();
+          }
+        });
+      } else if (isString(message)) {
+        var ret = htmlTagMatcher.test(message);
+        if (ret) {
+          var msg = "Detected HTML in message '" + message + "' of keypath '" + (paths.join('')) + "' at '" + locale + "'. Consider component interpolation with '<i18n>' to avoid XSS. See https://bit.ly/2ZqJzkp";
+          if (level === 'warn') {
+            warn(msg);
+          } else if (level === 'error') {
+            error(msg);
+          }
+        }
+      }
+    };
+
+    fn(level, locale, message, paths);
+  };
+
+  VueI18n.prototype._initVM = function _initVM (data) {
+    var silent = Vue.config.silent;
+    Vue.config.silent = true;
+    this._vm = new Vue({ data: data });
+    Vue.config.silent = silent;
+  };
+
+  VueI18n.prototype.destroyVM = function destroyVM () {
+    this._vm.$destroy();
+  };
+
+  VueI18n.prototype.subscribeDataChanging = function subscribeDataChanging (vm) {
+    this._dataListeners.push(vm);
+  };
+
+  VueI18n.prototype.unsubscribeDataChanging = function unsubscribeDataChanging (vm) {
+    remove(this._dataListeners, vm);
+  };
+
+  VueI18n.prototype.watchI18nData = function watchI18nData () {
+    var self = this;
+    return this._vm.$watch('$data', function () {
+      var i = self._dataListeners.length;
+      while (i--) {
+        Vue.nextTick(function () {
+          self._dataListeners[i] && self._dataListeners[i].$forceUpdate();
+        });
+      }
+    }, { deep: true })
+  };
+
+  VueI18n.prototype.watchLocale = function watchLocale () {
+    /* istanbul ignore if */
+    if (!this._sync || !this._root) { return null }
+    var target = this._vm;
+    return this._root.$i18n.vm.$watch('locale', function (val) {
+      target.$set(target, 'locale', val);
+      target.$forceUpdate();
+    }, { immediate: true })
+  };
+
+  VueI18n.prototype.onComponentInstanceCreated = function onComponentInstanceCreated (newI18n) {
+    if (this._componentInstanceCreatedListener) {
+      this._componentInstanceCreatedListener(newI18n, this);
+    }
+  };
+
+  prototypeAccessors.vm.get = function () { return this._vm };
+
+  prototypeAccessors.messages.get = function () { return looseClone(this._getMessages()) };
+  prototypeAccessors.dateTimeFormats.get = function () { return looseClone(this._getDateTimeFormats()) };
+  prototypeAccessors.numberFormats.get = function () { return looseClone(this._getNumberFormats()) };
+  prototypeAccessors.availableLocales.get = function () { return Object.keys(this.messages).sort() };
+
+  prototypeAccessors.locale.get = function () { return this._vm.locale };
+  prototypeAccessors.locale.set = function (locale) {
+    this._vm.$set(this._vm, 'locale', locale);
+  };
+
+  prototypeAccessors.fallbackLocale.get = function () { return this._vm.fallbackLocale };
+  prototypeAccessors.fallbackLocale.set = function (locale) {
+    this._localeChainCache = {};
+    this._vm.$set(this._vm, 'fallbackLocale', locale);
+  };
+
+  prototypeAccessors.formatFallbackMessages.get = function () { return this._formatFallbackMessages };
+  prototypeAccessors.formatFallbackMessages.set = function (fallback) { this._formatFallbackMessages = fallback; };
+
+  prototypeAccessors.missing.get = function () { return this._missing };
+  prototypeAccessors.missing.set = function (handler) { this._missing = handler; };
+
+  prototypeAccessors.formatter.get = function () { return this._formatter };
+  prototypeAccessors.formatter.set = function (formatter) { this._formatter = formatter; };
+
+  prototypeAccessors.silentTranslationWarn.get = function () { return this._silentTranslationWarn };
+  prototypeAccessors.silentTranslationWarn.set = function (silent) { this._silentTranslationWarn = silent; };
+
+  prototypeAccessors.silentFallbackWarn.get = function () { return this._silentFallbackWarn };
+  prototypeAccessors.silentFallbackWarn.set = function (silent) { this._silentFallbackWarn = silent; };
+
+  prototypeAccessors.preserveDirectiveContent.get = function () { return this._preserveDirectiveContent };
+  prototypeAccessors.preserveDirectiveContent.set = function (preserve) { this._preserveDirectiveContent = preserve; };
+
+  prototypeAccessors.warnHtmlInMessage.get = function () { return this._warnHtmlInMessage };
+  prototypeAccessors.warnHtmlInMessage.set = function (level) {
+      var this$1 = this;
+
+    var orgLevel = this._warnHtmlInMessage;
+    this._warnHtmlInMessage = level;
+    if (orgLevel !== level && (level === 'warn' || level === 'error')) {
+      var messages = this._getMessages();
+      Object.keys(messages).forEach(function (locale) {
+        this$1._checkLocaleMessage(locale, this$1._warnHtmlInMessage, messages[locale]);
+      });
+    }
+  };
+
+  prototypeAccessors.postTranslation.get = function () { return this._postTranslation };
+  prototypeAccessors.postTranslation.set = function (handler) { this._postTranslation = handler; };
+
+  VueI18n.prototype._getMessages = function _getMessages () { return this._vm.messages };
+  VueI18n.prototype._getDateTimeFormats = function _getDateTimeFormats () { return this._vm.dateTimeFormats };
+  VueI18n.prototype._getNumberFormats = function _getNumberFormats () { return this._vm.numberFormats };
+
+  VueI18n.prototype._warnDefault = function _warnDefault (locale, key, result, vm, values, interpolateMode) {
+    if (!isNull(result)) { return result }
+    if (this._missing) {
+      var missingRet = this._missing.apply(null, [locale, key, vm, values]);
+      if (isString(missingRet)) {
+        return missingRet
+      }
+    } else {
+      if (!this._isSilentTranslationWarn(key)) {
+        warn(
+          "Cannot translate the value of keypath '" + key + "'. " +
+          'Use the value of keypath as default.'
+        );
+      }
+    }
+
+    if (this._formatFallbackMessages) {
+      var parsedArgs = parseArgs.apply(void 0, values);
+      return this._render(key, interpolateMode, parsedArgs.params, key)
+    } else {
+      return key
+    }
+  };
+
+  VueI18n.prototype._isFallbackRoot = function _isFallbackRoot (val) {
+    return !val && !isNull(this._root) && this._fallbackRoot
+  };
+
+  VueI18n.prototype._isSilentFallbackWarn = function _isSilentFallbackWarn (key) {
+    return this._silentFallbackWarn instanceof RegExp
+      ? this._silentFallbackWarn.test(key)
+      : this._silentFallbackWarn
+  };
+
+  VueI18n.prototype._isSilentFallback = function _isSilentFallback (locale, key) {
+    return this._isSilentFallbackWarn(key) && (this._isFallbackRoot() || locale !== this.fallbackLocale)
+  };
+
+  VueI18n.prototype._isSilentTranslationWarn = function _isSilentTranslationWarn (key) {
+    return this._silentTranslationWarn instanceof RegExp
+      ? this._silentTranslationWarn.test(key)
+      : this._silentTranslationWarn
+  };
+
+  VueI18n.prototype._interpolate = function _interpolate (
+    locale,
+    message,
+    key,
+    host,
+    interpolateMode,
+    values,
+    visitedLinkStack
+  ) {
+    if (!message) { return null }
+
+    var pathRet = this._path.getPathValue(message, key);
+    if (isArray(pathRet) || isPlainObject(pathRet)) { return pathRet }
+
+    var ret;
+    if (isNull(pathRet)) {
+      /* istanbul ignore else */
+      if (isPlainObject(message)) {
+        ret = message[key];
+        if (!(isString(ret) || isFunction(ret))) {
+          if (!this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
+            warn(("Value of key '" + key + "' is not a string or function !"));
+          }
+          return null
+        }
+      } else {
+        return null
+      }
+    } else {
+      /* istanbul ignore else */
+      if (isString(pathRet) || isFunction(pathRet)) {
+        ret = pathRet;
+      } else {
+        if (!this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
+          warn(("Value of key '" + key + "' is not a string or function!"));
+        }
+        return null
+      }
+    }
+
+    // Check for the existence of links within the translated string
+    if (isString(ret) && (ret.indexOf('@:') >= 0 || ret.indexOf('@.') >= 0)) {
+      ret = this._link(locale, message, ret, host, 'raw', values, visitedLinkStack);
+    }
+
+    return this._render(ret, interpolateMode, values, key)
+  };
+
+  VueI18n.prototype._link = function _link (
+    locale,
+    message,
+    str,
+    host,
+    interpolateMode,
+    values,
+    visitedLinkStack
+  ) {
+    var ret = str;
+
+    // Match all the links within the local
+    // We are going to replace each of
+    // them with its translation
+    var matches = ret.match(linkKeyMatcher);
+    for (var idx in matches) {
+      // ie compatible: filter custom array
+      // prototype method
+      if (!matches.hasOwnProperty(idx)) {
+        continue
+      }
+      var link = matches[idx];
+      var linkKeyPrefixMatches = link.match(linkKeyPrefixMatcher);
+      var linkPrefix = linkKeyPrefixMatches[0];
+        var formatterName = linkKeyPrefixMatches[1];
+
+      // Remove the leading @:, @.case: and the brackets
+      var linkPlaceholder = link.replace(linkPrefix, '').replace(bracketsMatcher, '');
+
+      if (includes(visitedLinkStack, linkPlaceholder)) {
+        {
+          warn(("Circular reference found. \"" + link + "\" is already visited in the chain of " + (visitedLinkStack.reverse().join(' <- '))));
+        }
+        return ret
+      }
+      visitedLinkStack.push(linkPlaceholder);
+
+      // Translate the link
+      var translated = this._interpolate(
+        locale, message, linkPlaceholder, host,
+        interpolateMode === 'raw' ? 'string' : interpolateMode,
+        interpolateMode === 'raw' ? undefined : values,
+        visitedLinkStack
+      );
+
+      if (this._isFallbackRoot(translated)) {
+        if (!this._isSilentTranslationWarn(linkPlaceholder)) {
+          warn(("Fall back to translate the link placeholder '" + linkPlaceholder + "' with root locale."));
+        }
+        /* istanbul ignore if */
+        if (!this._root) { throw Error('unexpected error') }
+        var root = this._root.$i18n;
+        translated = root._translate(
+          root._getMessages(), root.locale, root.fallbackLocale,
+          linkPlaceholder, host, interpolateMode, values
+        );
+      }
+      translated = this._warnDefault(
+        locale, linkPlaceholder, translated, host,
+        isArray(values) ? values : [values],
+        interpolateMode
+      );
+
+      if (this._modifiers.hasOwnProperty(formatterName)) {
+        translated = this._modifiers[formatterName](translated);
+      } else if (defaultModifiers.hasOwnProperty(formatterName)) {
+        translated = defaultModifiers[formatterName](translated);
+      }
+
+      visitedLinkStack.pop();
+
+      // Replace the link with the translated
+      ret = !translated ? ret : ret.replace(link, translated);
+    }
+
+    return ret
+  };
+
+  VueI18n.prototype._createMessageContext = function _createMessageContext (values) {
+    var _list = isArray(values) ? values : [];
+    var _named = isObject(values) ? values : {};
+    var list = function (index) { return _list[index]; };
+    var named = function (key) { return _named[key]; };
+    return {
+      list: list,
+      named: named
+    }
+  };
+
+  VueI18n.prototype._render = function _render (message, interpolateMode, values, path) {
+    if (isFunction(message)) {
+      return message(this._createMessageContext(values))
+    }
+
+    var ret = this._formatter.interpolate(message, values, path);
+
+    // If the custom formatter refuses to work - apply the default one
+    if (!ret) {
+      ret = defaultFormatter.interpolate(message, values, path);
+    }
+
+    // if interpolateMode is **not** 'string' ('row'),
+    // return the compiled data (e.g. ['foo', VNode, 'bar']) with formatter
+    return interpolateMode === 'string' && !isString(ret) ? ret.join('') : ret
+  };
+
+  VueI18n.prototype._appendItemToChain = function _appendItemToChain (chain, item, blocks) {
+    var follow = false;
+    if (!includes(chain, item)) {
+      follow = true;
+      if (item) {
+        follow = item[item.length - 1] !== '!';
+        item = item.replace(/!/g, '');
+        chain.push(item);
+        if (blocks && blocks[item]) {
+          follow = blocks[item];
+        }
+      }
+    }
+    return follow
+  };
+
+  VueI18n.prototype._appendLocaleToChain = function _appendLocaleToChain (chain, locale, blocks) {
+    var follow;
+    var tokens = locale.split('-');
+    do {
+      var item = tokens.join('-');
+      follow = this._appendItemToChain(chain, item, blocks);
+      tokens.splice(-1, 1);
+    } while (tokens.length && (follow === true))
+    return follow
+  };
+
+  VueI18n.prototype._appendBlockToChain = function _appendBlockToChain (chain, block, blocks) {
+    var follow = true;
+    for (var i = 0; (i < block.length) && (isBoolean(follow)); i++) {
+      var locale = block[i];
+      if (isString(locale)) {
+        follow = this._appendLocaleToChain(chain, locale, blocks);
+      }
+    }
+    return follow
+  };
+
+  VueI18n.prototype._getLocaleChain = function _getLocaleChain (start, fallbackLocale) {
+    if (start === '') { return [] }
+
+    if (!this._localeChainCache) {
+      this._localeChainCache = {};
+    }
+
+    var chain = this._localeChainCache[start];
+    if (!chain) {
+      if (!fallbackLocale) {
+        fallbackLocale = this.fallbackLocale;
+      }
+      chain = [];
+
+      // first block defined by start
+      var block = [start];
+
+      // while any intervening block found
+      while (isArray(block)) {
+        block = this._appendBlockToChain(
+          chain,
+          block,
+          fallbackLocale
+        );
+      }
+
+      // last block defined by default
+      var defaults;
+      if (isArray(fallbackLocale)) {
+        defaults = fallbackLocale;
+      } else if (isObject(fallbackLocale)) {
+        /* $FlowFixMe */
+        if (fallbackLocale['default']) {
+          defaults = fallbackLocale['default'];
+        } else {
+          defaults = null;
+        }
+      } else {
+        defaults = fallbackLocale;
+      }
+
+      // convert defaults to array
+      if (isString(defaults)) {
+        block = [defaults];
+      } else {
+        block = defaults;
+      }
+      if (block) {
+        this._appendBlockToChain(
+          chain,
+          block,
+          null
+        );
+      }
+      this._localeChainCache[start] = chain;
+    }
+    return chain
+  };
+
+  VueI18n.prototype._translate = function _translate (
+    messages,
+    locale,
+    fallback,
+    key,
+    host,
+    interpolateMode,
+    args
+  ) {
+    var chain = this._getLocaleChain(locale, fallback);
+    var res;
+    for (var i = 0; i < chain.length; i++) {
+      var step = chain[i];
+      res =
+        this._interpolate(step, messages[step], key, host, interpolateMode, args, [key]);
+      if (!isNull(res)) {
+        if (step !== locale && "development" !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+          warn(("Fall back to translate the keypath '" + key + "' with '" + step + "' locale."));
+        }
+        return res
+      }
+    }
+    return null
+  };
+
+  VueI18n.prototype._t = function _t (key, _locale, messages, host) {
+      var ref;
+
+      var values = [], len = arguments.length - 4;
+      while ( len-- > 0 ) values[ len ] = arguments[ len + 4 ];
+    if (!key) { return '' }
+
+    var parsedArgs = parseArgs.apply(void 0, values);
+    var locale = parsedArgs.locale || _locale;
+
+    var ret = this._translate(
+      messages, locale, this.fallbackLocale, key,
+      host, 'string', parsedArgs.params
+    );
+    if (this._isFallbackRoot(ret)) {
+      if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(("Fall back to translate the keypath '" + key + "' with root locale."));
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return (ref = this._root).$t.apply(ref, [ key ].concat( values ))
+    } else {
+      ret = this._warnDefault(locale, key, ret, host, values, 'string');
+      if (this._postTranslation && ret !== null && ret !== undefined) {
+        ret = this._postTranslation(ret, key);
+      }
+      return ret
+    }
+  };
+
+  VueI18n.prototype.t = function t (key) {
+      var ref;
+
+      var values = [], len = arguments.length - 1;
+      while ( len-- > 0 ) values[ len ] = arguments[ len + 1 ];
+    return (ref = this)._t.apply(ref, [ key, this.locale, this._getMessages(), null ].concat( values ))
+  };
+
+  VueI18n.prototype._i = function _i (key, locale, messages, host, values) {
+    var ret =
+      this._translate(messages, locale, this.fallbackLocale, key, host, 'raw', values);
+    if (this._isFallbackRoot(ret)) {
+      if (!this._isSilentTranslationWarn(key)) {
+        warn(("Fall back to interpolate the keypath '" + key + "' with root locale."));
+      }
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n.i(key, locale, values)
+    } else {
+      return this._warnDefault(locale, key, ret, host, [values], 'raw')
+    }
+  };
+
+  VueI18n.prototype.i = function i (key, locale, values) {
+    /* istanbul ignore if */
+    if (!key) { return '' }
+
+    if (!isString(locale)) {
+      locale = this.locale;
+    }
+
+    return this._i(key, locale, this._getMessages(), null, values)
+  };
+
+  VueI18n.prototype._tc = function _tc (
+    key,
+    _locale,
+    messages,
+    host,
+    choice
+  ) {
+      var ref;
+
+      var values = [], len = arguments.length - 5;
+      while ( len-- > 0 ) values[ len ] = arguments[ len + 5 ];
+    if (!key) { return '' }
+    if (choice === undefined) {
+      choice = 1;
+    }
+
+    var predefined = { 'count': choice, 'n': choice };
+    var parsedArgs = parseArgs.apply(void 0, values);
+    parsedArgs.params = Object.assign(predefined, parsedArgs.params);
+    values = parsedArgs.locale === null ? [parsedArgs.params] : [parsedArgs.locale, parsedArgs.params];
+    return this.fetchChoice((ref = this)._t.apply(ref, [ key, _locale, messages, host ].concat( values )), choice)
+  };
+
+  VueI18n.prototype.fetchChoice = function fetchChoice (message, choice) {
+    /* istanbul ignore if */
+    if (!message && !isString(message)) { return null }
+    var choices = message.split('|');
+
+    choice = this.getChoiceIndex(choice, choices.length);
+    if (!choices[choice]) { return message }
+    return choices[choice].trim()
+  };
+
+  VueI18n.prototype.tc = function tc (key, choice) {
+      var ref;
+
+      var values = [], len = arguments.length - 2;
+      while ( len-- > 0 ) values[ len ] = arguments[ len + 2 ];
+    return (ref = this)._tc.apply(ref, [ key, this.locale, this._getMessages(), null, choice ].concat( values ))
+  };
+
+  VueI18n.prototype._te = function _te (key, locale, messages) {
+      var args = [], len = arguments.length - 3;
+      while ( len-- > 0 ) args[ len ] = arguments[ len + 3 ];
+
+    var _locale = parseArgs.apply(void 0, args).locale || locale;
+    return this._exist(messages[_locale], key)
+  };
+
+  VueI18n.prototype.te = function te (key, locale) {
+    return this._te(key, this.locale, this._getMessages(), locale)
+  };
+
+  VueI18n.prototype.getLocaleMessage = function getLocaleMessage (locale) {
+    return looseClone(this._vm.messages[locale] || {})
+  };
+
+  VueI18n.prototype.setLocaleMessage = function setLocaleMessage (locale, message) {
+    if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+      this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
+    }
+    this._vm.$set(this._vm.messages, locale, message);
+  };
+
+  VueI18n.prototype.mergeLocaleMessage = function mergeLocaleMessage (locale, message) {
+    if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+      this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
+    }
+    this._vm.$set(this._vm.messages, locale, merge({}, this._vm.messages[locale] || {}, message));
+  };
+
+  VueI18n.prototype.getDateTimeFormat = function getDateTimeFormat (locale) {
+    return looseClone(this._vm.dateTimeFormats[locale] || {})
+  };
+
+  VueI18n.prototype.setDateTimeFormat = function setDateTimeFormat (locale, format) {
+    this._vm.$set(this._vm.dateTimeFormats, locale, format);
+    this._clearDateTimeFormat(locale, format);
+  };
+
+  VueI18n.prototype.mergeDateTimeFormat = function mergeDateTimeFormat (locale, format) {
+    this._vm.$set(this._vm.dateTimeFormats, locale, merge(this._vm.dateTimeFormats[locale] || {}, format));
+    this._clearDateTimeFormat(locale, format);
+  };
+
+  VueI18n.prototype._clearDateTimeFormat = function _clearDateTimeFormat (locale, format) {
+    for (var key in format) {
+      var id = locale + "__" + key;
+
+      if (!this._dateTimeFormatters.hasOwnProperty(id)) {
+        continue
+      }
+
+      delete this._dateTimeFormatters[id];
+    }
+  };
+
+  VueI18n.prototype._localizeDateTime = function _localizeDateTime (
+    value,
+    locale,
+    fallback,
+    dateTimeFormats,
+    key
+  ) {
+    var _locale = locale;
+    var formats = dateTimeFormats[_locale];
+
+    var chain = this._getLocaleChain(locale, fallback);
+    for (var i = 0; i < chain.length; i++) {
+      var current = _locale;
+      var step = chain[i];
+      formats = dateTimeFormats[step];
+      _locale = step;
+      // fallback locale
+      if (isNull(formats) || isNull(formats[key])) {
+        if (step !== locale && "development" !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+          warn(("Fall back to '" + step + "' datetime formats from '" + current + "' datetime formats."));
+        }
+      } else {
+        break
+      }
+    }
+
+    if (isNull(formats) || isNull(formats[key])) {
+      return null
+    } else {
+      var format = formats[key];
+      var id = _locale + "__" + key;
+      var formatter = this._dateTimeFormatters[id];
+      if (!formatter) {
+        formatter = this._dateTimeFormatters[id] = new Intl.DateTimeFormat(_locale, format);
+      }
+      return formatter.format(value)
+    }
+  };
+
+  VueI18n.prototype._d = function _d (value, locale, key) {
+    /* istanbul ignore if */
+    if (!VueI18n.availabilities.dateTimeFormat) {
+      warn('Cannot format a Date value due to not supported Intl.DateTimeFormat.');
+      return ''
+    }
+
+    if (!key) {
+      return new Intl.DateTimeFormat(locale).format(value)
+    }
+
+    var ret =
+      this._localizeDateTime(value, locale, this.fallbackLocale, this._getDateTimeFormats(), key);
+    if (this._isFallbackRoot(ret)) {
+      if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(("Fall back to datetime localization of root: key '" + key + "'."));
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n.d(value, key, locale)
+    } else {
+      return ret || ''
+    }
+  };
+
+  VueI18n.prototype.d = function d (value) {
+      var args = [], len = arguments.length - 1;
+      while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+
+    var locale = this.locale;
+    var key = null;
+
+    if (args.length === 1) {
+      if (isString(args[0])) {
+        key = args[0];
+      } else if (isObject(args[0])) {
+        if (args[0].locale) {
+          locale = args[0].locale;
+        }
+        if (args[0].key) {
+          key = args[0].key;
+        }
+      }
+    } else if (args.length === 2) {
+      if (isString(args[0])) {
+        key = args[0];
+      }
+      if (isString(args[1])) {
+        locale = args[1];
+      }
+    }
+
+    return this._d(value, locale, key)
+  };
+
+  VueI18n.prototype.getNumberFormat = function getNumberFormat (locale) {
+    return looseClone(this._vm.numberFormats[locale] || {})
+  };
+
+  VueI18n.prototype.setNumberFormat = function setNumberFormat (locale, format) {
+    this._vm.$set(this._vm.numberFormats, locale, format);
+    this._clearNumberFormat(locale, format);
+  };
+
+  VueI18n.prototype.mergeNumberFormat = function mergeNumberFormat (locale, format) {
+    this._vm.$set(this._vm.numberFormats, locale, merge(this._vm.numberFormats[locale] || {}, format));
+    this._clearNumberFormat(locale, format);
+  };
+
+  VueI18n.prototype._clearNumberFormat = function _clearNumberFormat (locale, format) {
+    for (var key in format) {
+      var id = locale + "__" + key;
+
+      if (!this._numberFormatters.hasOwnProperty(id)) {
+        continue
+      }
+
+      delete this._numberFormatters[id];
+    }
+  };
+
+  VueI18n.prototype._getNumberFormatter = function _getNumberFormatter (
+    value,
+    locale,
+    fallback,
+    numberFormats,
+    key,
+    options
+  ) {
+    var _locale = locale;
+    var formats = numberFormats[_locale];
+
+    var chain = this._getLocaleChain(locale, fallback);
+    for (var i = 0; i < chain.length; i++) {
+      var current = _locale;
+      var step = chain[i];
+      formats = numberFormats[step];
+      _locale = step;
+      // fallback locale
+      if (isNull(formats) || isNull(formats[key])) {
+        if (step !== locale && "development" !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+          warn(("Fall back to '" + step + "' number formats from '" + current + "' number formats."));
+        }
+      } else {
+        break
+      }
+    }
+
+    if (isNull(formats) || isNull(formats[key])) {
+      return null
+    } else {
+      var format = formats[key];
+
+      var formatter;
+      if (options) {
+        // If options specified - create one time number formatter
+        formatter = new Intl.NumberFormat(_locale, Object.assign({}, format, options));
+      } else {
+        var id = _locale + "__" + key;
+        formatter = this._numberFormatters[id];
+        if (!formatter) {
+          formatter = this._numberFormatters[id] = new Intl.NumberFormat(_locale, format);
+        }
+      }
+      return formatter
+    }
+  };
+
+  VueI18n.prototype._n = function _n (value, locale, key, options) {
+    /* istanbul ignore if */
+    if (!VueI18n.availabilities.numberFormat) {
+      {
+        warn('Cannot format a Number value due to not supported Intl.NumberFormat.');
+      }
+      return ''
+    }
+
+    if (!key) {
+      var nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
+      return nf.format(value)
+    }
+
+    var formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
+    var ret = formatter && formatter.format(value);
+    if (this._isFallbackRoot(ret)) {
+      if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(("Fall back to number localization of root: key '" + key + "'."));
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n.n(value, Object.assign({}, { key: key, locale: locale }, options))
+    } else {
+      return ret || ''
+    }
+  };
+
+  VueI18n.prototype.n = function n (value) {
+      var args = [], len = arguments.length - 1;
+      while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
+
+    var locale = this.locale;
+    var key = null;
+    var options = null;
+
+    if (args.length === 1) {
+      if (isString(args[0])) {
+        key = args[0];
+      } else if (isObject(args[0])) {
+        if (args[0].locale) {
+          locale = args[0].locale;
+        }
+        if (args[0].key) {
+          key = args[0].key;
+        }
+
+        // Filter out number format options only
+        options = Object.keys(args[0]).reduce(function (acc, key) {
+            var obj;
+
+          if (includes(numberFormatKeys, key)) {
+            return Object.assign({}, acc, ( obj = {}, obj[key] = args[0][key], obj ))
+          }
+          return acc
+        }, null);
+      }
+    } else if (args.length === 2) {
+      if (isString(args[0])) {
+        key = args[0];
+      }
+      if (isString(args[1])) {
+        locale = args[1];
+      }
+    }
+
+    return this._n(value, locale, key, options)
+  };
+
+  VueI18n.prototype._ntp = function _ntp (value, locale, key, options) {
+    /* istanbul ignore if */
+    if (!VueI18n.availabilities.numberFormat) {
+      {
+        warn('Cannot format to parts a Number value due to not supported Intl.NumberFormat.');
+      }
+      return []
+    }
+
+    if (!key) {
+      var nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
+      return nf.formatToParts(value)
+    }
+
+    var formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
+    var ret = formatter && formatter.formatToParts(value);
+    if (this._isFallbackRoot(ret)) {
+      if (!this._isSilentTranslationWarn(key)) {
+        warn(("Fall back to format number to parts of root: key '" + key + "' ."));
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n._ntp(value, locale, key, options)
+    } else {
+      return ret || []
+    }
+  };
+
+  Object.defineProperties( VueI18n.prototype, prototypeAccessors );
+
+  var availabilities;
+  // $FlowFixMe
+  Object.defineProperty(VueI18n, 'availabilities', {
+    get: function get () {
+      if (!availabilities) {
+        var intlDefined = typeof Intl !== 'undefined';
+        availabilities = {
+          dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
+          numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
+        };
+      }
+
+      return availabilities
+    }
+  });
+
+  VueI18n.install = install;
+  VueI18n.version = '8.21.0';
+
+  return VueI18n;
+
+})));

File diff suppressed because it is too large
+ 5 - 0
plugin/vue-i18n/dist/vue-i18n.min.js


+ 176 - 0
plugin/vue-i18n/package.json

@@ -0,0 +1,176 @@
+{
+  "_args": [
+    [
+      "vue-i18n@8.21.0",
+      "D:\\2023\\4\\wwbsr"
+    ]
+  ],
+  "_from": "vue-i18n@8.21.0",
+  "_id": "vue-i18n@8.21.0",
+  "_inBundle": false,
+  "_integrity": "sha1-UmRQUl/buch3aFtbpsuVc7c9OUA=",
+  "_location": "/vue-i18n",
+  "_phantomChildren": {},
+  "_requested": {
+    "type": "version",
+    "registry": true,
+    "raw": "vue-i18n@8.21.0",
+    "name": "vue-i18n",
+    "escapedName": "vue-i18n",
+    "rawSpec": "8.21.0",
+    "saveSpec": null,
+    "fetchSpec": "8.21.0"
+  },
+  "_requiredBy": [
+    "/"
+  ],
+  "_resolved": "https://registry.npm.taobao.org/vue-i18n/download/vue-i18n-8.21.0.tgz?cache=0&sync_timestamp=1597336528269&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-i18n%2Fdownload%2Fvue-i18n-8.21.0.tgz",
+  "_spec": "8.21.0",
+  "_where": "D:\\2023\\4\\wwbsr",
+  "author": {
+    "name": "kazuya kawaguchi",
+    "email": "kawakazu80@gmail.com"
+  },
+  "bugs": {
+    "url": "https://github.com/kazupon/vue-i18n/issues"
+  },
+  "changelog": {
+    "labels": {
+      "Type: Feature": ":star: New Features",
+      "Type: Bug": ":bug: Bug Fixes",
+      "Type: Security": ":lock: Security Fixes",
+      "Type: Performance": ":chart_with_upwards_trend: Performance Fixes",
+      "Type: Improvement": ":zap: Improved Features",
+      "Type: Breaking": ":boom: Breaking Change",
+      "Type: Deprecated": ":warning: Deprecated Features",
+      "Type: I18n": ":globe_with_meridians: Internationalization",
+      "Type: A11y": ":wheelchair: Accessibility",
+      "Type: Documentation": ":pencil: Documentation"
+    }
+  },
+  "description": "Internationalization plugin for Vue.js",
+  "devDependencies": {
+    "@babel/core": "^7.1.0",
+    "@babel/plugin-proposal-class-properties": "^7.1.0",
+    "@babel/plugin-syntax-flow": "^7.0.0",
+    "@babel/plugin-transform-flow-strip-types": "^7.0.0",
+    "@typescript-eslint/eslint-plugin": "^3.0.0",
+    "@typescript-eslint/parser": "^3.0.0",
+    "@vue/babel-preset-app": "^4.4.1",
+    "babel-eslint": "^10.1.0",
+    "babel-loader": "^8.1.0",
+    "babel-plugin-istanbul": "^6.0.0",
+    "babel-preset-power-assert": "^3.0.0",
+    "buble": "^0.19.3",
+    "chromedriver": "^83.0.0",
+    "core-js": "^3.6.5",
+    "cross-env": "^7.0.2",
+    "cross-spawn": "^7.0.3",
+    "eslint": "^6.8.0",
+    "eslint-loader": "^4.0.2",
+    "eslint-plugin-flowtype": "^4.7.0",
+    "eslint-plugin-ie11": "^1.0.0",
+    "eslint-plugin-no-autofix": "^1.0.1",
+    "eslint-plugin-vue": "^6.2.2",
+    "eslint-plugin-vue-libs": "^4.0.0",
+    "flow-bin": "^0.38.0",
+    "http-server": "^0.12.3",
+    "intl": "^1.2.5",
+    "karma": "^5.0.9",
+    "karma-chrome-launcher": "^3.1.0",
+    "karma-coverage": "^2.0.2",
+    "karma-firefox-launcher": "^1.1.0",
+    "karma-mocha": "^2.0.1",
+    "karma-mocha-reporter": "^2.2.5",
+    "karma-safari-launcher": "^1.0.0",
+    "karma-sauce-launcher": "^4.1.5",
+    "karma-sourcemap-loader": "^0.3.7",
+    "karma-webpack": "^4.0.2",
+    "lerna-changelog": "^1.0.0",
+    "lerna-changelog-label-schema": "^3.0.0",
+    "mocha": "^7.2.0",
+    "mocha-loader": "^5.0.0",
+    "nightwatch": "^1.3.5",
+    "nightwatch-helpers": "^1.2.0",
+    "power-assert": "^1.6.0",
+    "rollup": "^0.66.0",
+    "rollup-plugin-buble": "^0.19.2",
+    "rollup-plugin-commonjs": "^9.1.8",
+    "rollup-plugin-flow-no-whitespace": "^1.0.0",
+    "rollup-plugin-node-resolve": "^3.4.0",
+    "rollup-plugin-replace": "^2.0.0",
+    "selenium-server": "^3.141.59",
+    "shipjs": "^0.17.0",
+    "sinon": "^9.0.2",
+    "terser": "^3.17.0",
+    "typescript": "^3.9.3",
+    "vue": "^2.5.17",
+    "vue-github-button": "^1.1.2",
+    "vue-template-compiler": "^2.5.17",
+    "vuepress": "^1.5.0",
+    "webpack": "^4.43.0",
+    "webpack-cli": "^3.1.1",
+    "webpack-dev-middleware": "^3.7.2",
+    "webpack-dev-server": "^3.11.0"
+  },
+  "files": [
+    "dist/vue-i18n.js",
+    "dist/vue-i18n.min.js",
+    "dist/vue-i18n.common.js",
+    "dist/vue-i18n.esm.js",
+    "dist/vue-i18n.esm.browser.js",
+    "dist/vue-i18n.esm.browser.min.js",
+    "src/**/*.js",
+    "types/*.d.ts",
+    "decls",
+    "vetur/tags.json",
+    "vetur/attributes.json"
+  ],
+  "homepage": "https://github.com/kazupon/vue-i18n#readme",
+  "keywords": [
+    "i18n",
+    "internationalization",
+    "plugin",
+    "vue",
+    "vue.js"
+  ],
+  "license": "MIT",
+  "main": "dist/vue-i18n.common.js",
+  "module": "dist/vue-i18n.esm.js",
+  "name": "vue-i18n",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/kazupon/vue-i18n.git"
+  },
+  "scripts": {
+    "build": "node config/build.js",
+    "clean": "rm -rf coverage && rm -rf dist/*.js* && rm ./*.log",
+    "coverage": "cat ./coverage/lcov.info",
+    "dev": "cross-env BABEL_ENV=test webpack-dev-server --inline --hot --open --content-base ./test/unit/ --config config/webpack.dev.conf.js",
+    "docs:build": "cross-env NODE_ENV=production node config/version.js && cross-env NODE_ENV=production vuepress build vuepress -d docs",
+    "docs:clean": "rm -rf docs/**",
+    "docs:dev": "vuepress dev vuepress",
+    "flow": "flow check",
+    "lint": "eslint --fix src test types/**/*.ts",
+    "release:prepare": "shipjs prepare",
+    "release:trigger": "shipjs trigger",
+    "sauce": "npm run sauce:coolkids && npm run sauce:ie && npm run sauce:mobile",
+    "sauce:coolkids": "karma start config/karma.sauce.conf.js -- 0",
+    "sauce:ie": "karma start config/karma.sauce.conf.js -- 1",
+    "sauce:mobile": "karma start config/karma.sauce.conf.js -- 2",
+    "test": "npm run lint && npm run flow && npm run test:types && npm run test:cover && npm run test:e2e",
+    "test:cover": "cross-env BABEL_ENV=test karma start config/karma.cover.conf.js",
+    "test:e2e": "npm run build && node test/e2e/runner.js",
+    "test:types": "tsc -p types",
+    "test:unit": "cross-env BABEL_ENV=test karma start config/karma.unit.conf.js",
+    "test:unit:ci": "cross-env BABEL_ENV=test karma start config/karma.unit.ci.conf.js"
+  },
+  "sideEffects": false,
+  "types": "types/index.d.ts",
+  "unpkg": "dist/vue-i18n.js",
+  "version": "8.21.0",
+  "vetur": {
+    "tags": "vetur/tags.json",
+    "attributes": "vetur/attributes.json"
+  }
+}

+ 101 - 0
plugin/vue-i18n/src/components/interpolation.js

@@ -0,0 +1,101 @@
+/* @flow */
+
+import { warn } from '../util'
+
+export default {
+  name: 'i18n',
+  functional: true,
+  props: {
+    tag: {
+      type: [String, Boolean, Object],
+      default: 'span'
+    },
+    path: {
+      type: String,
+      required: true
+    },
+    locale: {
+      type: String
+    },
+    places: {
+      type: [Array, Object]
+    }
+  },
+  render (h: Function, { data, parent, props, slots }: Object) {
+    const { $i18n } = parent
+    if (!$i18n) {
+      if (process.env.NODE_ENV !== 'production') {
+        warn('Cannot find VueI18n instance!')
+      }
+      return
+    }
+
+    const { path, locale, places } = props
+    const params = slots()
+    const children = $i18n.i(
+      path,
+      locale,
+      onlyHasDefaultPlace(params) || places
+        ? useLegacyPlaces(params.default, places)
+        : params
+    )
+
+    const tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span'
+    return tag ? h(tag, data, children) : children
+  }
+}
+
+function onlyHasDefaultPlace (params) {
+  let prop
+  for (prop in params) {
+    if (prop !== 'default') { return false }
+  }
+  return Boolean(prop)
+}
+
+function useLegacyPlaces (children, places) {
+  const params = places ? createParamsFromPlaces(places) : {}
+
+  if (!children) { return params }
+
+  // Filter empty text nodes
+  children = children.filter(child => {
+    return child.tag || child.text.trim() !== ''
+  })
+
+  const everyPlace = children.every(vnodeHasPlaceAttribute)
+  if (process.env.NODE_ENV !== 'production' && everyPlace) {
+    warn('`place` attribute is deprecated in next major version. Please switch to Vue slots.')
+  }
+
+  return children.reduce(
+    everyPlace ? assignChildPlace : assignChildIndex,
+    params
+  )
+}
+
+function createParamsFromPlaces (places) {
+  if (process.env.NODE_ENV !== 'production') {
+    warn('`places` prop is deprecated in next major version. Please switch to Vue slots.')
+  }
+
+  return Array.isArray(places)
+    ? places.reduce(assignChildIndex, {})
+    : Object.assign({}, places)
+}
+
+function assignChildPlace (params, child) {
+  if (child.data && child.data.attrs && child.data.attrs.place) {
+    params[child.data.attrs.place] = child
+  }
+  return params
+}
+
+function assignChildIndex (params, child, index) {
+  params[index] = child
+  return params
+}
+
+function vnodeHasPlaceAttribute (vnode) {
+  return Boolean(vnode.data && vnode.data.attrs && vnode.data.attrs.place)
+}

+ 70 - 0
plugin/vue-i18n/src/components/number.js

@@ -0,0 +1,70 @@
+/* @flow */
+
+import { warn, isString, isObject, includes, numberFormatKeys } from '../util'
+
+export default {
+  name: 'i18n-n',
+  functional: true,
+  props: {
+    tag: {
+      type: [String, Boolean, Object],
+      default: 'span'
+    },
+    value: {
+      type: Number,
+      required: true
+    },
+    format: {
+      type: [String, Object]
+    },
+    locale: {
+      type: String
+    }
+  },
+  render (h: Function, { props, parent, data }: Object) {
+    const i18n = parent.$i18n
+
+    if (!i18n) {
+      if (process.env.NODE_ENV !== 'production') {
+        warn('Cannot find VueI18n instance!')
+      }
+      return null
+    }
+
+    let key: ?string = null
+    let options: ?NumberFormatOptions = null
+
+    if (isString(props.format)) {
+      key = props.format
+    } else if (isObject(props.format)) {
+      if (props.format.key) {
+        key = props.format.key
+      }
+
+      // Filter out number format options only
+      options = Object.keys(props.format).reduce((acc, prop) => {
+        if (includes(numberFormatKeys, prop)) {
+          return Object.assign({}, acc, { [prop]: props.format[prop] })
+        }
+        return acc
+      }, null)
+    }
+
+    const locale: Locale = props.locale || i18n.locale
+    const parts: NumberFormatToPartsResult = i18n._ntp(props.value, locale, key, options)
+
+    const values = parts.map((part, index) => {
+      const slot: ?Function = data.scopedSlots && data.scopedSlots[part.type]
+      return slot ? slot({ [part.type]: part.value, index, parts }) : part.value
+    })
+
+    const tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span'
+    return tag
+      ? h(tag, {
+        attrs: data.attrs,
+        'class': data['class'],
+        staticClass: data.staticClass
+      }, values)
+      : values
+  }
+}

+ 112 - 0
plugin/vue-i18n/src/directive.js

@@ -0,0 +1,112 @@
+/* @flow */
+
+import { warn, isString, isPlainObject, looseEqual } from './util'
+
+export function bind (el: any, binding: Object, vnode: any): void {
+  if (!assert(el, vnode)) { return }
+
+  t(el, binding, vnode)
+}
+
+export function update (el: any, binding: Object, vnode: any, oldVNode: any): void {
+  if (!assert(el, vnode)) { return }
+
+  const i18n: any = vnode.context.$i18n
+  if (localeEqual(el, vnode) &&
+    (looseEqual(binding.value, binding.oldValue) &&
+     looseEqual(el._localeMessage, i18n.getLocaleMessage(i18n.locale)))) { return }
+
+  t(el, binding, vnode)
+}
+
+export function unbind (el: any, binding: Object, vnode: any, oldVNode: any): void {
+  const vm: any = vnode.context
+  if (!vm) {
+    warn('Vue instance does not exists in VNode context')
+    return
+  }
+
+  const i18n: any = vnode.context.$i18n || {}
+  if (!binding.modifiers.preserve && !i18n.preserveDirectiveContent) {
+    el.textContent = ''
+  }
+  el._vt = undefined
+  delete el['_vt']
+  el._locale = undefined
+  delete el['_locale']
+  el._localeMessage = undefined
+  delete el['_localeMessage']
+}
+
+function assert (el: any, vnode: any): boolean {
+  const vm: any = vnode.context
+  if (!vm) {
+    warn('Vue instance does not exists in VNode context')
+    return false
+  }
+
+  if (!vm.$i18n) {
+    warn('VueI18n instance does not exists in Vue instance')
+    return false
+  }
+
+  return true
+}
+
+function localeEqual (el: any, vnode: any): boolean {
+  const vm: any = vnode.context
+  return el._locale === vm.$i18n.locale
+}
+
+function t (el: any, binding: Object, vnode: any): void {
+  const value: any = binding.value
+
+  const { path, locale, args, choice } = parseValue(value)
+  if (!path && !locale && !args) {
+    warn('value type not supported')
+    return
+  }
+
+  if (!path) {
+    warn('`path` is required in v-t directive')
+    return
+  }
+
+  const vm: any = vnode.context
+  if (choice != null) {
+    el._vt = el.textContent = vm.$i18n.tc(path, choice, ...makeParams(locale, args))
+  } else {
+    el._vt = el.textContent = vm.$i18n.t(path, ...makeParams(locale, args))
+  }
+  el._locale = vm.$i18n.locale
+  el._localeMessage = vm.$i18n.getLocaleMessage(vm.$i18n.locale)
+}
+
+function parseValue (value: any): Object {
+  let path: ?string
+  let locale: ?Locale
+  let args: any
+  let choice: ?number
+
+  if (isString(value)) {
+    path = value
+  } else if (isPlainObject(value)) {
+    path = value.path
+    locale = value.locale
+    args = value.args
+    choice = value.choice
+  }
+
+  return { path, locale, args, choice }
+}
+
+function makeParams (locale: Locale, args: any): Array<any> {
+  const params: Array<any> = []
+
+  locale && params.push(locale)
+  if (args && (Array.isArray(args) || isPlainObject(args))) {
+    params.push(args)
+  }
+
+  return params
+}

+ 33 - 0
plugin/vue-i18n/src/extend.js

@@ -0,0 +1,33 @@
+/* @flow */
+
+export default function extend (Vue: any): void {
+  if (!Vue.prototype.hasOwnProperty('$i18n')) {
+    // $FlowFixMe
+    Object.defineProperty(Vue.prototype, '$i18n', {
+      get () { return this._i18n }
+    })
+  }
+
+  Vue.prototype.$t = function (key: Path, ...values: any): TranslateResult {
+    const i18n = this.$i18n
+    return i18n._t(key, i18n.locale, i18n._getMessages(), this, ...values)
+  }
+
+  Vue.prototype.$tc = function (key: Path, choice?: number, ...values: any): TranslateResult {
+    const i18n = this.$i18n
+    return i18n._tc(key, i18n.locale, i18n._getMessages(), this, choice, ...values)
+  }
+
+  Vue.prototype.$te = function (key: Path, locale?: Locale): boolean {
+    const i18n = this.$i18n
+    return i18n._te(key, i18n.locale, i18n._getMessages(), locale)
+  }
+
+  Vue.prototype.$d = function (value: number | Date, ...args: any): DateTimeFormatResult {
+    return this.$i18n.d(value, ...args)
+  }
+
+  Vue.prototype.$n = function (value: number, ...args: any): NumberFormatResult {
+    return this.$i18n.n(value, ...args)
+  }
+}

+ 114 - 0
plugin/vue-i18n/src/format.js

@@ -0,0 +1,114 @@
+/* @flow */
+
+import { warn, isObject } from './util'
+
+export default class BaseFormatter {
+  _caches: { [key: string]: Array<Token> }
+
+  constructor () {
+    this._caches = Object.create(null)
+  }
+
+  interpolate (message: string, values: any): Array<any> {
+    if (!values) {
+      return [message]
+    }
+    let tokens: Array<Token> = this._caches[message]
+    if (!tokens) {
+      tokens = parse(message)
+      this._caches[message] = tokens
+    }
+    return compile(tokens, values)
+  }
+}
+
+type Token = {
+  type: 'text' | 'named' | 'list' | 'unknown',
+  value: string
+}
+
+const RE_TOKEN_LIST_VALUE: RegExp = /^(?:\d)+/
+const RE_TOKEN_NAMED_VALUE: RegExp = /^(?:\w)+/
+
+export function parse (format: string): Array<Token> {
+  const tokens: Array<Token> = []
+  let position: number = 0
+
+  let text: string = ''
+  while (position < format.length) {
+    let char: string = format[position++]
+    if (char === '{') {
+      if (text) {
+        tokens.push({ type: 'text', value: text })
+      }
+
+      text = ''
+      let sub: string = ''
+      char = format[position++]
+      while (char !== undefined && char !== '}') {
+        sub += char
+        char = format[position++]
+      }
+      const isClosed = char === '}'
+
+      const type = RE_TOKEN_LIST_VALUE.test(sub)
+        ? 'list'
+        : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
+          ? 'named'
+          : 'unknown'
+      tokens.push({ value: sub, type })
+    } else if (char === '%') {
+      // when found rails i18n syntax, skip text capture
+      if (format[(position)] !== '{') {
+        text += char
+      }
+    } else {
+      text += char
+    }
+  }
+
+  text && tokens.push({ type: 'text', value: text })
+
+  return tokens
+}
+
+export function compile (tokens: Array<Token>, values: Object | Array<any>): Array<any> {
+  const compiled: Array<any> = []
+  let index: number = 0
+
+  const mode: string = Array.isArray(values)
+    ? 'list'
+    : isObject(values)
+      ? 'named'
+      : 'unknown'
+  if (mode === 'unknown') { return compiled }
+
+  while (index < tokens.length) {
+    const token: Token = tokens[index]
+    switch (token.type) {
+      case 'text':
+        compiled.push(token.value)
+        break
+      case 'list':
+        compiled.push(values[parseInt(token.value, 10)])
+        break
+      case 'named':
+        if (mode === 'named') {
+          compiled.push((values: any)[token.value])
+        } else {
+          if (process.env.NODE_ENV !== 'production') {
+            warn(`Type of token '${token.type}' and format of value '${mode}' don't match!`)
+          }
+        }
+        break
+      case 'unknown':
+        if (process.env.NODE_ENV !== 'production') {
+          warn(`Detect 'unknown' type of token!`)
+        }
+        break
+    }
+    index++
+  }
+
+  return compiled
+}

+ 1065 - 0
plugin/vue-i18n/src/index.js

@@ -0,0 +1,1065 @@
+/* @flow */
+
+import { install, Vue } from './install'
+import {
+  warn,
+  error,
+  isNull,
+  parseArgs,
+  isPlainObject,
+  isObject,
+  isArray,
+  isBoolean,
+  isString,
+  isFunction,
+  looseClone,
+  remove,
+  includes,
+  merge,
+  numberFormatKeys
+} from './util'
+import BaseFormatter from './format'
+import I18nPath from './path'
+
+import type { PathValue } from './path'
+
+const htmlTagMatcher = /<\/?[\w\s="/.':;#-\/]+>/
+const linkKeyMatcher = /(?:@(?:\.[a-z]+)?:(?:[\w\-_|.]+|\([\w\-_|.]+\)))/g
+const linkKeyPrefixMatcher = /^@(?:\.([a-z]+))?:/
+const bracketsMatcher = /[()]/g
+const defaultModifiers = {
+  'upper': str => str.toLocaleUpperCase(),
+  'lower': str => str.toLocaleLowerCase(),
+  'capitalize': str => `${str.charAt(0).toLocaleUpperCase()}${str.substr(1)}`
+}
+
+const defaultFormatter = new BaseFormatter()
+
+export default class VueI18n {
+  static install: () => void
+  static version: string
+  static availabilities: IntlAvailability
+
+  _vm: any
+  _formatter: Formatter
+  _modifiers: Modifiers
+  _root: any
+  _sync: boolean
+  _fallbackRoot: boolean
+  _localeChainCache: { [key: string]: Array<Locale>; }
+  _missing: ?MissingHandler
+  _exist: Function
+  _silentTranslationWarn: boolean | RegExp
+  _silentFallbackWarn: boolean | RegExp
+  _formatFallbackMessages: boolean
+  _dateTimeFormatters: Object
+  _numberFormatters: Object
+  _path: I18nPath
+  _dataListeners: Array<any>
+  _componentInstanceCreatedListener: ?ComponentInstanceCreatedListener
+  _preserveDirectiveContent: boolean
+  _warnHtmlInMessage: WarnHtmlInMessageLevel
+  _postTranslation: ?PostTranslationHandler
+  pluralizationRules: {
+    [lang: string]: (choice: number, choicesLength: number) => number
+  }
+  getChoiceIndex: GetChoiceIndex
+
+  constructor (options: I18nOptions = {}) {
+    // Auto install if it is not done yet and `window` has `Vue`.
+    // To allow users to avoid auto-installation in some cases,
+    // this code should be placed here. See #290
+    /* istanbul ignore if */
+    if (!Vue && typeof window !== 'undefined' && window.Vue) {
+      install(window.Vue)
+    }
+
+    const locale: Locale = options.locale || 'en-US'
+    const fallbackLocale: FallbackLocale = options.fallbackLocale === false
+      ? false
+      : options.fallbackLocale || 'en-US'
+    const messages: LocaleMessages = options.messages || {}
+    const dateTimeFormats = options.dateTimeFormats || {}
+    const numberFormats = options.numberFormats || {}
+
+    this._vm = null
+    this._formatter = options.formatter || defaultFormatter
+    this._modifiers = options.modifiers || {}
+    this._missing = options.missing || null
+    this._root = options.root || null
+    this._sync = options.sync === undefined ? true : !!options.sync
+    this._fallbackRoot = options.fallbackRoot === undefined
+      ? true
+      : !!options.fallbackRoot
+    this._formatFallbackMessages = options.formatFallbackMessages === undefined
+      ? false
+      : !!options.formatFallbackMessages
+    this._silentTranslationWarn = options.silentTranslationWarn === undefined
+      ? false
+      : options.silentTranslationWarn
+    this._silentFallbackWarn = options.silentFallbackWarn === undefined
+      ? false
+      : !!options.silentFallbackWarn
+    this._dateTimeFormatters = {}
+    this._numberFormatters = {}
+    this._path = new I18nPath()
+    this._dataListeners = []
+    this._componentInstanceCreatedListener = options.componentInstanceCreatedListener || null
+    this._preserveDirectiveContent = options.preserveDirectiveContent === undefined
+      ? false
+      : !!options.preserveDirectiveContent
+    this.pluralizationRules = options.pluralizationRules || {}
+    this._warnHtmlInMessage = options.warnHtmlInMessage || 'off'
+    this._postTranslation = options.postTranslation || null
+
+    /**
+     * @param choice {number} a choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)`
+     * @param choicesLength {number} an overall amount of available choices
+     * @returns a final choice index
+    */
+    this.getChoiceIndex = (choice: number, choicesLength: number): number => {
+      const thisPrototype = Object.getPrototypeOf(this)
+      if (thisPrototype && thisPrototype.getChoiceIndex) {
+        const prototypeGetChoiceIndex = (thisPrototype.getChoiceIndex: any)
+        return (prototypeGetChoiceIndex: GetChoiceIndex).call(this, choice, choicesLength)
+      }
+
+      // Default (old) getChoiceIndex implementation - english-compatible
+      const defaultImpl = (_choice: number, _choicesLength: number) => {
+        _choice = Math.abs(_choice)
+
+        if (_choicesLength === 2) {
+          return _choice
+            ? _choice > 1
+              ? 1
+              : 0
+            : 1
+        }
+
+        return _choice ? Math.min(_choice, 2) : 0
+      }
+
+      if (this.locale in this.pluralizationRules) {
+        return this.pluralizationRules[this.locale].apply(this, [choice, choicesLength])
+      } else {
+        return defaultImpl(choice, choicesLength)
+      }
+    }
+
+
+    this._exist = (message: Object, key: Path): boolean => {
+      if (!message || !key) { return false }
+      if (!isNull(this._path.getPathValue(message, key))) { return true }
+      // fallback for flat key
+      if (message[key]) { return true }
+      return false
+    }
+
+    if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+      Object.keys(messages).forEach(locale => {
+        this._checkLocaleMessage(locale, this._warnHtmlInMessage, messages[locale])
+      })
+    }
+
+    this._initVM({
+      locale,
+      fallbackLocale,
+      messages,
+      dateTimeFormats,
+      numberFormats
+    })
+  }
+
+  _checkLocaleMessage (locale: Locale, level: WarnHtmlInMessageLevel, message: LocaleMessageObject): void {
+    const paths: Array<string> = []
+
+    const fn = (level: WarnHtmlInMessageLevel, locale: Locale, message: any, paths: Array<string>) => {
+      if (isPlainObject(message)) {
+        Object.keys(message).forEach(key => {
+          const val = message[key]
+          if (isPlainObject(val)) {
+            paths.push(key)
+            paths.push('.')
+            fn(level, locale, val, paths)
+            paths.pop()
+            paths.pop()
+          } else {
+            paths.push(key)
+            fn(level, locale, val, paths)
+            paths.pop()
+          }
+        })
+      } else if (isArray(message)) {
+        message.forEach((item, index) => {
+          if (isPlainObject(item)) {
+            paths.push(`[${index}]`)
+            paths.push('.')
+            fn(level, locale, item, paths)
+            paths.pop()
+            paths.pop()
+          } else {
+            paths.push(`[${index}]`)
+            fn(level, locale, item, paths)
+            paths.pop()
+          }
+        })
+      } else if (isString(message)) {
+        const ret = htmlTagMatcher.test(message)
+        if (ret) {
+          const msg = `Detected HTML in message '${message}' of keypath '${paths.join('')}' at '${locale}'. Consider component interpolation with '<i18n>' to avoid XSS. See https://bit.ly/2ZqJzkp`
+          if (level === 'warn') {
+            warn(msg)
+          } else if (level === 'error') {
+            error(msg)
+          }
+        }
+      }
+    }
+
+    fn(level, locale, message, paths)
+  }
+
+  _initVM (data: {
+    locale: Locale,
+    fallbackLocale: FallbackLocale,
+    messages: LocaleMessages,
+    dateTimeFormats: DateTimeFormats,
+    numberFormats: NumberFormats
+  }): void {
+    const silent = Vue.config.silent
+    Vue.config.silent = true
+    this._vm = new Vue({ data })
+    Vue.config.silent = silent
+  }
+
+  destroyVM (): void {
+    this._vm.$destroy()
+  }
+
+  subscribeDataChanging (vm: any): void {
+    this._dataListeners.push(vm)
+  }
+
+  unsubscribeDataChanging (vm: any): void {
+    remove(this._dataListeners, vm)
+  }
+
+  watchI18nData (): Function {
+    const self = this
+    return this._vm.$watch('$data', () => {
+      let i = self._dataListeners.length
+      while (i--) {
+        Vue.nextTick(() => {
+          self._dataListeners[i] && self._dataListeners[i].$forceUpdate()
+        })
+      }
+    }, { deep: true })
+  }
+
+  watchLocale (): ?Function {
+    /* istanbul ignore if */
+    if (!this._sync || !this._root) { return null }
+    const target: any = this._vm
+    return this._root.$i18n.vm.$watch('locale', (val) => {
+      target.$set(target, 'locale', val)
+      target.$forceUpdate()
+    }, { immediate: true })
+  }
+
+  onComponentInstanceCreated (newI18n: I18n) {
+    if (this._componentInstanceCreatedListener) {
+      this._componentInstanceCreatedListener(newI18n, this)
+    }
+  }
+
+  get vm (): any { return this._vm }
+
+  get messages (): LocaleMessages { return looseClone(this._getMessages()) }
+  get dateTimeFormats (): DateTimeFormats { return looseClone(this._getDateTimeFormats()) }
+  get numberFormats (): NumberFormats { return looseClone(this._getNumberFormats()) }
+  get availableLocales (): Locale[] { return Object.keys(this.messages).sort() }
+
+  get locale (): Locale { return this._vm.locale }
+  set locale (locale: Locale): void {
+    this._vm.$set(this._vm, 'locale', locale)
+  }
+
+  get fallbackLocale (): FallbackLocale { return this._vm.fallbackLocale }
+  set fallbackLocale (locale: FallbackLocale): void {
+    this._localeChainCache = {}
+    this._vm.$set(this._vm, 'fallbackLocale', locale)
+  }
+
+  get formatFallbackMessages (): boolean { return this._formatFallbackMessages }
+  set formatFallbackMessages (fallback: boolean): void { this._formatFallbackMessages = fallback }
+
+  get missing (): ?MissingHandler { return this._missing }
+  set missing (handler: MissingHandler): void { this._missing = handler }
+
+  get formatter (): Formatter { return this._formatter }
+  set formatter (formatter: Formatter): void { this._formatter = formatter }
+
+  get silentTranslationWarn (): boolean | RegExp { return this._silentTranslationWarn }
+  set silentTranslationWarn (silent: boolean | RegExp): void { this._silentTranslationWarn = silent }
+
+  get silentFallbackWarn (): boolean | RegExp { return this._silentFallbackWarn }
+  set silentFallbackWarn (silent: boolean | RegExp): void { this._silentFallbackWarn = silent }
+
+  get preserveDirectiveContent (): boolean { return this._preserveDirectiveContent }
+  set preserveDirectiveContent (preserve: boolean): void { this._preserveDirectiveContent = preserve }
+
+  get warnHtmlInMessage (): WarnHtmlInMessageLevel { return this._warnHtmlInMessage }
+  set warnHtmlInMessage (level: WarnHtmlInMessageLevel): void {
+    const orgLevel = this._warnHtmlInMessage
+    this._warnHtmlInMessage = level
+    if (orgLevel !== level && (level === 'warn' || level === 'error')) {
+      const messages = this._getMessages()
+      Object.keys(messages).forEach(locale => {
+        this._checkLocaleMessage(locale, this._warnHtmlInMessage, messages[locale])
+      })
+    }
+  }
+
+  get postTranslation (): ?PostTranslationHandler { return this._postTranslation }
+  set postTranslation (handler: PostTranslationHandler): void { this._postTranslation = handler }
+
+  _getMessages (): LocaleMessages { return this._vm.messages }
+  _getDateTimeFormats (): DateTimeFormats { return this._vm.dateTimeFormats }
+  _getNumberFormats (): NumberFormats { return this._vm.numberFormats }
+
+  _warnDefault (locale: Locale, key: Path, result: ?any, vm: ?any, values: any, interpolateMode: string): ?string {
+    if (!isNull(result)) { return result }
+    if (this._missing) {
+      const missingRet = this._missing.apply(null, [locale, key, vm, values])
+      if (isString(missingRet)) {
+        return missingRet
+      }
+    } else {
+      if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key)) {
+        warn(
+          `Cannot translate the value of keypath '${key}'. ` +
+          'Use the value of keypath as default.'
+        )
+      }
+    }
+
+    if (this._formatFallbackMessages) {
+      const parsedArgs = parseArgs(...values)
+      return this._render(key, interpolateMode, parsedArgs.params, key)
+    } else {
+      return key
+    }
+  }
+
+  _isFallbackRoot (val: any): boolean {
+    return !val && !isNull(this._root) && this._fallbackRoot
+  }
+
+  _isSilentFallbackWarn (key: Path): boolean {
+    return this._silentFallbackWarn instanceof RegExp
+      ? this._silentFallbackWarn.test(key)
+      : this._silentFallbackWarn
+  }
+
+  _isSilentFallback (locale: Locale, key: Path): boolean {
+    return this._isSilentFallbackWarn(key) && (this._isFallbackRoot() || locale !== this.fallbackLocale)
+  }
+
+  _isSilentTranslationWarn (key: Path): boolean {
+    return this._silentTranslationWarn instanceof RegExp
+      ? this._silentTranslationWarn.test(key)
+      : this._silentTranslationWarn
+  }
+
+  _interpolate (
+    locale: Locale,
+    message: LocaleMessageObject,
+    key: Path,
+    host: any,
+    interpolateMode: string,
+    values: any,
+    visitedLinkStack: Array<string>
+  ): any {
+    if (!message) { return null }
+
+    const pathRet: PathValue = this._path.getPathValue(message, key)
+    if (isArray(pathRet) || isPlainObject(pathRet)) { return pathRet }
+
+    let ret: mixed
+    if (isNull(pathRet)) {
+      /* istanbul ignore else */
+      if (isPlainObject(message)) {
+        ret = message[key]
+        if (!(isString(ret) || isFunction(ret))) {
+          if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
+            warn(`Value of key '${key}' is not a string or function !`)
+          }
+          return null
+        }
+      } else {
+        return null
+      }
+    } else {
+      /* istanbul ignore else */
+      if (isString(pathRet) || isFunction(pathRet)) {
+        ret = pathRet
+      } else {
+        if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
+          warn(`Value of key '${key}' is not a string or function!`)
+        }
+        return null
+      }
+    }
+
+    // Check for the existence of links within the translated string
+    if (isString(ret) && (ret.indexOf('@:') >= 0 || ret.indexOf('@.') >= 0)) {
+      ret = this._link(locale, message, ret, host, 'raw', values, visitedLinkStack)
+    }
+
+    return this._render(ret, interpolateMode, values, key)
+  }
+
+  _link (
+    locale: Locale,
+    message: LocaleMessageObject,
+    str: string,
+    host: any,
+    interpolateMode: string,
+    values: any,
+    visitedLinkStack: Array<string>
+  ): any {
+    let ret: string = str
+
+    // Match all the links within the local
+    // We are going to replace each of
+    // them with its translation
+    const matches: any = ret.match(linkKeyMatcher)
+    for (let idx in matches) {
+      // ie compatible: filter custom array
+      // prototype method
+      if (!matches.hasOwnProperty(idx)) {
+        continue
+      }
+      const link: string = matches[idx]
+      const linkKeyPrefixMatches: any = link.match(linkKeyPrefixMatcher)
+      const [linkPrefix, formatterName] = linkKeyPrefixMatches
+
+      // Remove the leading @:, @.case: and the brackets
+      const linkPlaceholder: string = link.replace(linkPrefix, '').replace(bracketsMatcher, '')
+
+      if (includes(visitedLinkStack, linkPlaceholder)) {
+        if (process.env.NODE_ENV !== 'production') {
+          warn(`Circular reference found. "${link}" is already visited in the chain of ${visitedLinkStack.reverse().join(' <- ')}`)
+        }
+        return ret
+      }
+      visitedLinkStack.push(linkPlaceholder)
+
+      // Translate the link
+      let translated: any = this._interpolate(
+        locale, message, linkPlaceholder, host,
+        interpolateMode === 'raw' ? 'string' : interpolateMode,
+        interpolateMode === 'raw' ? undefined : values,
+        visitedLinkStack
+      )
+
+      if (this._isFallbackRoot(translated)) {
+        if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(linkPlaceholder)) {
+          warn(`Fall back to translate the link placeholder '${linkPlaceholder}' with root locale.`)
+        }
+        /* istanbul ignore if */
+        if (!this._root) { throw Error('unexpected error') }
+        const root: any = this._root.$i18n
+        translated = root._translate(
+          root._getMessages(), root.locale, root.fallbackLocale,
+          linkPlaceholder, host, interpolateMode, values
+        )
+      }
+      translated = this._warnDefault(
+        locale, linkPlaceholder, translated, host,
+        isArray(values) ? values : [values],
+        interpolateMode
+      )
+
+      if (this._modifiers.hasOwnProperty(formatterName)) {
+        translated = this._modifiers[formatterName](translated)
+      } else if (defaultModifiers.hasOwnProperty(formatterName)) {
+        translated = defaultModifiers[formatterName](translated)
+      }
+
+      visitedLinkStack.pop()
+
+      // Replace the link with the translated
+      ret = !translated ? ret : ret.replace(link, translated)
+    }
+
+    return ret
+  }
+
+  _createMessageContext (values: any): MessageContext {
+    const _list = isArray(values) ? values : []
+    const _named = isObject(values) ? values : {}
+    const list = (index: number): mixed => _list[index]
+    const named = (key: string): mixed => _named[key]
+    return {
+      list,
+      named
+    }
+  }
+
+  _render (message: string | MessageFunction, interpolateMode: string, values: any, path: string): any {
+    if (isFunction(message)) {
+      return message(this._createMessageContext(values))
+    }
+
+    let ret = this._formatter.interpolate(message, values, path)
+
+    // If the custom formatter refuses to work - apply the default one
+    if (!ret) {
+      ret = defaultFormatter.interpolate(message, values, path)
+    }
+
+    // if interpolateMode is **not** 'string' ('row'),
+    // return the compiled data (e.g. ['foo', VNode, 'bar']) with formatter
+    return interpolateMode === 'string' && !isString(ret) ? ret.join('') : ret
+  }
+
+  _appendItemToChain (chain: Array<Locale>, item: Locale, blocks: any): any {
+    let follow = false
+    if (!includes(chain, item)) {
+      follow = true
+      if (item) {
+        follow = item[item.length - 1] !== '!'
+        item = item.replace(/!/g, '')
+        chain.push(item)
+        if (blocks && blocks[item]) {
+          follow = blocks[item]
+        }
+      }
+    }
+    return follow
+  }
+
+  _appendLocaleToChain (chain: Array<Locale>, locale: Locale, blocks: any): any {
+    let follow
+    const tokens = locale.split('-')
+    do {
+      const item = tokens.join('-')
+      follow = this._appendItemToChain(chain, item, blocks)
+      tokens.splice(-1, 1)
+    } while (tokens.length && (follow === true))
+    return follow
+  }
+
+  _appendBlockToChain (chain: Array<Locale>, block: Array<Locale> | Object, blocks: any): any {
+    let follow = true
+    for (let i = 0; (i < block.length) && (isBoolean(follow)); i++) {
+      const locale = block[i]
+      if (isString(locale)) {
+        follow = this._appendLocaleToChain(chain, locale, blocks)
+      }
+    }
+    return follow
+  }
+
+  _getLocaleChain (start: Locale, fallbackLocale: FallbackLocale): Array<Locale> {
+    if (start === '') { return [] }
+
+    if (!this._localeChainCache) {
+      this._localeChainCache = {}
+    }
+
+    let chain = this._localeChainCache[start]
+    if (!chain) {
+      if (!fallbackLocale) {
+        fallbackLocale = this.fallbackLocale
+      }
+      chain = []
+
+      // first block defined by start
+      let block = [start]
+
+      // while any intervening block found
+      while (isArray(block)) {
+        block = this._appendBlockToChain(
+          chain,
+          block,
+          fallbackLocale
+        )
+      }
+
+      // last block defined by default
+      let defaults
+      if (isArray(fallbackLocale)) {
+        defaults = fallbackLocale
+      } else if (isObject(fallbackLocale)) {
+        /* $FlowFixMe */
+        if (fallbackLocale['default']) {
+          defaults = fallbackLocale['default']
+        } else {
+          defaults = null
+        }
+      } else {
+        defaults = fallbackLocale
+      }
+
+      // convert defaults to array
+      if (isString(defaults)) {
+        block = [defaults]
+      } else {
+        block = defaults
+      }
+      if (block) {
+        this._appendBlockToChain(
+          chain,
+          block,
+          null
+        )
+      }
+      this._localeChainCache[start] = chain
+    }
+    return chain
+  }
+
+  _translate (
+    messages: LocaleMessages,
+    locale: Locale,
+    fallback: FallbackLocale,
+    key: Path,
+    host: any,
+    interpolateMode: string,
+    args: any
+  ): any {
+    const chain = this._getLocaleChain(locale, fallback)
+    let res
+    for (let i = 0; i < chain.length; i++) {
+      const step = chain[i]
+      res =
+        this._interpolate(step, messages[step], key, host, interpolateMode, args, [key])
+      if (!isNull(res)) {
+        if (step !== locale && process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+          warn(("Fall back to translate the keypath '" + key + "' with '" + step + "' locale."))
+        }
+        return res
+      }
+    }
+    return null
+  }
+
+  _t (key: Path, _locale: Locale, messages: LocaleMessages, host: any, ...values: any): any {
+    if (!key) { return '' }
+
+    const parsedArgs = parseArgs(...values)
+    const locale: Locale = parsedArgs.locale || _locale
+
+    let ret: any = this._translate(
+      messages, locale, this.fallbackLocale, key,
+      host, 'string', parsedArgs.params
+    )
+    if (this._isFallbackRoot(ret)) {
+      if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(`Fall back to translate the keypath '${key}' with root locale.`)
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$t(key, ...values)
+    } else {
+      ret = this._warnDefault(locale, key, ret, host, values, 'string')
+      if (this._postTranslation && ret !== null && ret !== undefined) {
+        ret = this._postTranslation(ret, key)
+      }
+      return ret
+    }
+  }
+
+  t (key: Path, ...values: any): TranslateResult {
+    return this._t(key, this.locale, this._getMessages(), null, ...values)
+  }
+
+  _i (key: Path, locale: Locale, messages: LocaleMessages, host: any, values: Object): any {
+    const ret: any =
+      this._translate(messages, locale, this.fallbackLocale, key, host, 'raw', values)
+    if (this._isFallbackRoot(ret)) {
+      if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key)) {
+        warn(`Fall back to interpolate the keypath '${key}' with root locale.`)
+      }
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n.i(key, locale, values)
+    } else {
+      return this._warnDefault(locale, key, ret, host, [values], 'raw')
+    }
+  }
+
+  i (key: Path, locale: Locale, values: Object): TranslateResult {
+    /* istanbul ignore if */
+    if (!key) { return '' }
+
+    if (!isString(locale)) {
+      locale = this.locale
+    }
+
+    return this._i(key, locale, this._getMessages(), null, values)
+  }
+
+  _tc (
+    key: Path,
+    _locale: Locale,
+    messages: LocaleMessages,
+    host: any,
+    choice?: number,
+    ...values: any
+  ): any {
+    if (!key) { return '' }
+    if (choice === undefined) {
+      choice = 1
+    }
+
+    const predefined = { 'count': choice, 'n': choice }
+    const parsedArgs = parseArgs(...values)
+    parsedArgs.params = Object.assign(predefined, parsedArgs.params)
+    values = parsedArgs.locale === null ? [parsedArgs.params] : [parsedArgs.locale, parsedArgs.params]
+    return this.fetchChoice(this._t(key, _locale, messages, host, ...values), choice)
+  }
+
+  fetchChoice (message: string, choice: number): ?string {
+    /* istanbul ignore if */
+    if (!message && !isString(message)) { return null }
+    const choices: Array<string> = message.split('|')
+
+    choice = this.getChoiceIndex(choice, choices.length)
+    if (!choices[choice]) { return message }
+    return choices[choice].trim()
+  }
+
+  tc (key: Path, choice?: number, ...values: any): TranslateResult {
+    return this._tc(key, this.locale, this._getMessages(), null, choice, ...values)
+  }
+
+  _te (key: Path, locale: Locale, messages: LocaleMessages, ...args: any): boolean {
+    const _locale: Locale = parseArgs(...args).locale || locale
+    return this._exist(messages[_locale], key)
+  }
+
+  te (key: Path, locale?: Locale): boolean {
+    return this._te(key, this.locale, this._getMessages(), locale)
+  }
+
+  getLocaleMessage (locale: Locale): LocaleMessageObject {
+    return looseClone(this._vm.messages[locale] || {})
+  }
+
+  setLocaleMessage (locale: Locale, message: LocaleMessageObject): void {
+    if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+      this._checkLocaleMessage(locale, this._warnHtmlInMessage, message)
+    }
+    this._vm.$set(this._vm.messages, locale, message)
+  }
+
+  mergeLocaleMessage (locale: Locale, message: LocaleMessageObject): void {
+    if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
+      this._checkLocaleMessage(locale, this._warnHtmlInMessage, message)
+    }
+    this._vm.$set(this._vm.messages, locale, merge({}, this._vm.messages[locale] || {}, message))
+  }
+
+  getDateTimeFormat (locale: Locale): DateTimeFormat {
+    return looseClone(this._vm.dateTimeFormats[locale] || {})
+  }
+
+  setDateTimeFormat (locale: Locale, format: DateTimeFormat): void {
+    this._vm.$set(this._vm.dateTimeFormats, locale, format)
+    this._clearDateTimeFormat(locale, format)
+  }
+
+  mergeDateTimeFormat (locale: Locale, format: DateTimeFormat): void {
+    this._vm.$set(this._vm.dateTimeFormats, locale, merge(this._vm.dateTimeFormats[locale] || {}, format))
+    this._clearDateTimeFormat(locale, format)
+  }
+
+  _clearDateTimeFormat (locale: Locale, format: DateTimeFormat): void {
+    for (let key in format) {
+      const id = `${locale}__${key}`
+
+      if (!this._dateTimeFormatters.hasOwnProperty(id)) {
+        continue
+      }
+
+      delete this._dateTimeFormatters[id]
+    }
+  }
+
+  _localizeDateTime (
+    value: number | Date,
+    locale: Locale,
+    fallback: FallbackLocale,
+    dateTimeFormats: DateTimeFormats,
+    key: string
+  ): ?DateTimeFormatResult {
+    let _locale: Locale = locale
+    let formats: DateTimeFormat = dateTimeFormats[_locale]
+
+    const chain = this._getLocaleChain(locale, fallback)
+    for (let i = 0; i < chain.length; i++) {
+      const current = _locale
+      const step = chain[i]
+      formats = dateTimeFormats[step]
+      _locale = step
+      // fallback locale
+      if (isNull(formats) || isNull(formats[key])) {
+        if (step !== locale && process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+          warn(`Fall back to '${step}' datetime formats from '${current}' datetime formats.`)
+        }
+      } else {
+        break
+      }
+    }
+
+    if (isNull(formats) || isNull(formats[key])) {
+      return null
+    } else {
+      const format: ?DateTimeFormatOptions = formats[key]
+      const id = `${_locale}__${key}`
+      let formatter = this._dateTimeFormatters[id]
+      if (!formatter) {
+        formatter = this._dateTimeFormatters[id] = new Intl.DateTimeFormat(_locale, format)
+      }
+      return formatter.format(value)
+    }
+  }
+
+  _d (value: number | Date, locale: Locale, key: ?string): DateTimeFormatResult {
+    /* istanbul ignore if */
+    if (process.env.NODE_ENV !== 'production' && !VueI18n.availabilities.dateTimeFormat) {
+      warn('Cannot format a Date value due to not supported Intl.DateTimeFormat.')
+      return ''
+    }
+
+    if (!key) {
+      return new Intl.DateTimeFormat(locale).format(value)
+    }
+
+    const ret: ?DateTimeFormatResult =
+      this._localizeDateTime(value, locale, this.fallbackLocale, this._getDateTimeFormats(), key)
+    if (this._isFallbackRoot(ret)) {
+      if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(`Fall back to datetime localization of root: key '${key}'.`)
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n.d(value, key, locale)
+    } else {
+      return ret || ''
+    }
+  }
+
+  d (value: number | Date, ...args: any): DateTimeFormatResult {
+    let locale: Locale = this.locale
+    let key: ?string = null
+
+    if (args.length === 1) {
+      if (isString(args[0])) {
+        key = args[0]
+      } else if (isObject(args[0])) {
+        if (args[0].locale) {
+          locale = args[0].locale
+        }
+        if (args[0].key) {
+          key = args[0].key
+        }
+      }
+    } else if (args.length === 2) {
+      if (isString(args[0])) {
+        key = args[0]
+      }
+      if (isString(args[1])) {
+        locale = args[1]
+      }
+    }
+
+    return this._d(value, locale, key)
+  }
+
+  getNumberFormat (locale: Locale): NumberFormat {
+    return looseClone(this._vm.numberFormats[locale] || {})
+  }
+
+  setNumberFormat (locale: Locale, format: NumberFormat): void {
+    this._vm.$set(this._vm.numberFormats, locale, format)
+    this._clearNumberFormat(locale, format)
+  }
+
+  mergeNumberFormat (locale: Locale, format: NumberFormat): void {
+    this._vm.$set(this._vm.numberFormats, locale, merge(this._vm.numberFormats[locale] || {}, format))
+    this._clearNumberFormat(locale, format)
+  }
+
+  _clearNumberFormat (locale: Locale, format: NumberFormat): void {
+    for (let key in format) {
+      const id = `${locale}__${key}`
+
+      if (!this._numberFormatters.hasOwnProperty(id)) {
+        continue
+      }
+
+      delete this._numberFormatters[id]
+    }
+  }
+
+  _getNumberFormatter (
+    value: number,
+    locale: Locale,
+    fallback: FallbackLocale,
+    numberFormats: NumberFormats,
+    key: string,
+    options: ?NumberFormatOptions
+  ): ?Object {
+    let _locale: Locale = locale
+    let formats: NumberFormat = numberFormats[_locale]
+
+    const chain = this._getLocaleChain(locale, fallback)
+    for (let i = 0; i < chain.length; i++) {
+      const current = _locale
+      const step = chain[i]
+      formats = numberFormats[step]
+      _locale = step
+      // fallback locale
+      if (isNull(formats) || isNull(formats[key])) {
+        if (step !== locale && process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+          warn(`Fall back to '${step}' number formats from '${current}' number formats.`)
+        }
+      } else {
+        break
+      }
+    }
+
+    if (isNull(formats) || isNull(formats[key])) {
+      return null
+    } else {
+      const format: ?NumberFormatOptions = formats[key]
+
+      let formatter
+      if (options) {
+        // If options specified - create one time number formatter
+        formatter = new Intl.NumberFormat(_locale, Object.assign({}, format, options))
+      } else {
+        const id = `${_locale}__${key}`
+        formatter = this._numberFormatters[id]
+        if (!formatter) {
+          formatter = this._numberFormatters[id] = new Intl.NumberFormat(_locale, format)
+        }
+      }
+      return formatter
+    }
+  }
+
+  _n (value: number, locale: Locale, key: ?string, options: ?NumberFormatOptions): NumberFormatResult {
+    /* istanbul ignore if */
+    if (!VueI18n.availabilities.numberFormat) {
+      if (process.env.NODE_ENV !== 'production') {
+        warn('Cannot format a Number value due to not supported Intl.NumberFormat.')
+      }
+      return ''
+    }
+
+    if (!key) {
+      const nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options)
+      return nf.format(value)
+    }
+
+    const formatter: ?Object = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options)
+    const ret: ?NumberFormatResult = formatter && formatter.format(value)
+    if (this._isFallbackRoot(ret)) {
+      if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
+        warn(`Fall back to number localization of root: key '${key}'.`)
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n.n(value, Object.assign({}, { key, locale }, options))
+    } else {
+      return ret || ''
+    }
+  }
+
+  n (value: number, ...args: any): NumberFormatResult {
+    let locale: Locale = this.locale
+    let key: ?string = null
+    let options: ?NumberFormatOptions = null
+
+    if (args.length === 1) {
+      if (isString(args[0])) {
+        key = args[0]
+      } else if (isObject(args[0])) {
+        if (args[0].locale) {
+          locale = args[0].locale
+        }
+        if (args[0].key) {
+          key = args[0].key
+        }
+
+        // Filter out number format options only
+        options = Object.keys(args[0]).reduce((acc, key) => {
+          if (includes(numberFormatKeys, key)) {
+            return Object.assign({}, acc, { [key]: args[0][key] })
+          }
+          return acc
+        }, null)
+      }
+    } else if (args.length === 2) {
+      if (isString(args[0])) {
+        key = args[0]
+      }
+      if (isString(args[1])) {
+        locale = args[1]
+      }
+    }
+
+    return this._n(value, locale, key, options)
+  }
+
+  _ntp (value: number, locale: Locale, key: ?string, options: ?NumberFormatOptions): NumberFormatToPartsResult {
+    /* istanbul ignore if */
+    if (!VueI18n.availabilities.numberFormat) {
+      if (process.env.NODE_ENV !== 'production') {
+        warn('Cannot format to parts a Number value due to not supported Intl.NumberFormat.')
+      }
+      return []
+    }
+
+    if (!key) {
+      const nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options)
+      return nf.formatToParts(value)
+    }
+
+    const formatter: ?Object = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options)
+    const ret: ?NumberFormatToPartsResult = formatter && formatter.formatToParts(value)
+    if (this._isFallbackRoot(ret)) {
+      if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key)) {
+        warn(`Fall back to format number to parts of root: key '${key}' .`)
+      }
+      /* istanbul ignore if */
+      if (!this._root) { throw Error('unexpected error') }
+      return this._root.$i18n._ntp(value, locale, key, options)
+    } else {
+      return ret || []
+    }
+  }
+}
+
+let availabilities: IntlAvailability
+// $FlowFixMe
+Object.defineProperty(VueI18n, 'availabilities', {
+  get () {
+    if (!availabilities) {
+      const intlDefined = typeof Intl !== 'undefined'
+      availabilities = {
+        dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
+        numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
+      }
+    }
+
+    return availabilities
+  }
+})
+
+VueI18n.install = install
+VueI18n.version = '__VERSION__'

+ 40 - 0
plugin/vue-i18n/src/install.js

@@ -0,0 +1,40 @@
+import { warn } from './util'
+import extend from './extend'
+import mixin from './mixin'
+import interpolationComponent from './components/interpolation'
+import numberComponent from './components/number'
+import { bind, update, unbind } from './directive'
+
+export let Vue
+
+export function install (_Vue) {
+  /* istanbul ignore if */
+  if (process.env.NODE_ENV !== 'production' && install.installed && _Vue === Vue) {
+    warn('already installed.')
+    return
+  }
+  install.installed = true
+
+  Vue = _Vue
+
+  const version = (Vue.version && Number(Vue.version.split('.')[0])) || -1
+  /* istanbul ignore if */
+  if (process.env.NODE_ENV !== 'production' && version < 2) {
+    warn(`vue-i18n (${install.version}) need to use Vue 2.0 or later (Vue: ${Vue.version}).`)
+    return
+  }
+
+  extend(Vue)
+  Vue.mixin(mixin)
+  Vue.directive('t', { bind, update, unbind })
+  Vue.component(interpolationComponent.name, interpolationComponent)
+  Vue.component(numberComponent.name, numberComponent)
+
+  // use simple mergeStrategies to prevent i18n instance lose '__proto__'
+  const strats = Vue.config.optionMergeStrategies
+  strats.i18n = function (parentVal, childVal) {
+    return childVal === undefined
+      ? parentVal
+      : childVal
+  }
+}

+ 139 - 0
plugin/vue-i18n/src/mixin.js

@@ -0,0 +1,139 @@
+/* @flow */
+
+import VueI18n from './index'
+import { isPlainObject, warn, error, merge } from './util'
+
+export default {
+  beforeCreate (): void {
+    const options: any = this.$options
+    options.i18n = options.i18n || (options.__i18n ? {} : null)
+
+    if (options.i18n) {
+      if (options.i18n instanceof VueI18n) {
+        // init locale messages via custom blocks
+        if (options.__i18n) {
+          try {
+            let localeMessages = {}
+            options.__i18n.forEach(resource => {
+              localeMessages = merge(localeMessages, JSON.parse(resource))
+            })
+            Object.keys(localeMessages).forEach((locale: Locale) => {
+              options.i18n.mergeLocaleMessage(locale, localeMessages[locale])
+            })
+          } catch (e) {
+            if (process.env.NODE_ENV !== 'production') {
+              error(`Cannot parse locale messages via custom blocks.`, e)
+            }
+          }
+        }
+        this._i18n = options.i18n
+        this._i18nWatcher = this._i18n.watchI18nData()
+      } else if (isPlainObject(options.i18n)) {
+        const rootI18n = this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n
+          ? this.$root.$i18n
+          : null
+        // component local i18n
+        if (rootI18n) {
+          options.i18n.root = this.$root
+          options.i18n.formatter = rootI18n.formatter
+          options.i18n.fallbackLocale = rootI18n.fallbackLocale
+          options.i18n.formatFallbackMessages = rootI18n.formatFallbackMessages
+          options.i18n.silentTranslationWarn = rootI18n.silentTranslationWarn
+          options.i18n.silentFallbackWarn = rootI18n.silentFallbackWarn
+          options.i18n.pluralizationRules = rootI18n.pluralizationRules
+          options.i18n.preserveDirectiveContent = rootI18n.preserveDirectiveContent
+        }
+
+        // init locale messages via custom blocks
+        if (options.__i18n) {
+          try {
+            let localeMessages = {}
+            options.__i18n.forEach(resource => {
+              localeMessages = merge(localeMessages, JSON.parse(resource))
+            })
+            options.i18n.messages = localeMessages
+          } catch (e) {
+            if (process.env.NODE_ENV !== 'production') {
+              warn(`Cannot parse locale messages via custom blocks.`, e)
+            }
+          }
+        }
+
+        const { sharedMessages } = options.i18n
+        if (sharedMessages && isPlainObject(sharedMessages)) {
+          options.i18n.messages = merge(options.i18n.messages, sharedMessages)
+        }
+
+        this._i18n = new VueI18n(options.i18n)
+        this._i18nWatcher = this._i18n.watchI18nData()
+
+        if (options.i18n.sync === undefined || !!options.i18n.sync) {
+          this._localeWatcher = this.$i18n.watchLocale()
+        }
+
+        if (rootI18n) {
+          rootI18n.onComponentInstanceCreated(this._i18n)
+        }
+      } else {
+        if (process.env.NODE_ENV !== 'production') {
+          warn(`Cannot be interpreted 'i18n' option.`)
+        }
+      }
+    } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
+      // root i18n
+      this._i18n = this.$root.$i18n
+    } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
+      // parent i18n
+      this._i18n = options.parent.$i18n
+    }
+  },
+
+  beforeMount (): void {
+    const options: any = this.$options
+    options.i18n = options.i18n || (options.__i18n ? {} : null)
+
+    if (options.i18n) {
+      if (options.i18n instanceof VueI18n) {
+        // init locale messages via custom blocks
+        this._i18n.subscribeDataChanging(this)
+        this._subscribing = true
+      } else if (isPlainObject(options.i18n)) {
+        this._i18n.subscribeDataChanging(this)
+        this._subscribing = true
+      } else {
+        if (process.env.NODE_ENV !== 'production') {
+          warn(`Cannot be interpreted 'i18n' option.`)
+        }
+      }
+    } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
+      this._i18n.subscribeDataChanging(this)
+      this._subscribing = true
+    } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
+      this._i18n.subscribeDataChanging(this)
+      this._subscribing = true
+    }
+  },
+
+  beforeDestroy (): void {
+    if (!this._i18n) { return }
+
+    const self = this
+    this.$nextTick(() => {
+      if (self._subscribing) {
+        self._i18n.unsubscribeDataChanging(self)
+        delete self._subscribing
+      }
+
+      if (self._i18nWatcher) {
+        self._i18nWatcher()
+        self._i18n.destroyVM()
+        delete self._i18nWatcher
+      }
+
+      if (self._localeWatcher) {
+        self._localeWatcher()
+        delete self._localeWatcher
+      }
+    })
+  }
+}

+ 302 - 0
plugin/vue-i18n/src/path.js

@@ -0,0 +1,302 @@
+/* @flow */
+
+import { isObject } from './util'
+
+/**
+ *  Path parser
+ *  - Inspired:
+ *    Vue.js Path parser
+ */
+
+// actions
+const APPEND = 0
+const PUSH = 1
+const INC_SUB_PATH_DEPTH = 2
+const PUSH_SUB_PATH = 3
+
+// states
+const BEFORE_PATH = 0
+const IN_PATH = 1
+const BEFORE_IDENT = 2
+const IN_IDENT = 3
+const IN_SUB_PATH = 4
+const IN_SINGLE_QUOTE = 5
+const IN_DOUBLE_QUOTE = 6
+const AFTER_PATH = 7
+const ERROR = 8
+
+const pathStateMachine: any = []
+
+pathStateMachine[BEFORE_PATH] = {
+  'ws': [BEFORE_PATH],
+  'ident': [IN_IDENT, APPEND],
+  '[': [IN_SUB_PATH],
+  'eof': [AFTER_PATH]
+}
+
+pathStateMachine[IN_PATH] = {
+  'ws': [IN_PATH],
+  '.': [BEFORE_IDENT],
+  '[': [IN_SUB_PATH],
+  'eof': [AFTER_PATH]
+}
+
+pathStateMachine[BEFORE_IDENT] = {
+  'ws': [BEFORE_IDENT],
+  'ident': [IN_IDENT, APPEND],
+  '0': [IN_IDENT, APPEND],
+  'number': [IN_IDENT, APPEND]
+}
+
+pathStateMachine[IN_IDENT] = {
+  'ident': [IN_IDENT, APPEND],
+  '0': [IN_IDENT, APPEND],
+  'number': [IN_IDENT, APPEND],
+  'ws': [IN_PATH, PUSH],
+  '.': [BEFORE_IDENT, PUSH],
+  '[': [IN_SUB_PATH, PUSH],
+  'eof': [AFTER_PATH, PUSH]
+}
+
+pathStateMachine[IN_SUB_PATH] = {
+  "'": [IN_SINGLE_QUOTE, APPEND],
+  '"': [IN_DOUBLE_QUOTE, APPEND],
+  '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH],
+  ']': [IN_PATH, PUSH_SUB_PATH],
+  'eof': ERROR,
+  'else': [IN_SUB_PATH, APPEND]
+}
+
+pathStateMachine[IN_SINGLE_QUOTE] = {
+  "'": [IN_SUB_PATH, APPEND],
+  'eof': ERROR,
+  'else': [IN_SINGLE_QUOTE, APPEND]
+}
+
+pathStateMachine[IN_DOUBLE_QUOTE] = {
+  '"': [IN_SUB_PATH, APPEND],
+  'eof': ERROR,
+  'else': [IN_DOUBLE_QUOTE, APPEND]
+}
+
+/**
+ * Check if an expression is a literal value.
+ */
+
+const literalValueRE: RegExp = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/
+function isLiteral (exp: string): boolean {
+  return literalValueRE.test(exp)
+}
+
+/**
+ * Strip quotes from a string
+ */
+
+function stripQuotes (str: string): string | boolean {
+  const a: number = str.charCodeAt(0)
+  const b: number = str.charCodeAt(str.length - 1)
+  return a === b && (a === 0x22 || a === 0x27)
+    ? str.slice(1, -1)
+    : str
+}
+
+/**
+ * Determine the type of a character in a keypath.
+ */
+
+function getPathCharType (ch: ?string): string {
+  if (ch === undefined || ch === null) { return 'eof' }
+
+  const code: number = ch.charCodeAt(0)
+
+  switch (code) {
+    case 0x5B: // [
+    case 0x5D: // ]
+    case 0x2E: // .
+    case 0x22: // "
+    case 0x27: // '
+      return ch
+
+    case 0x5F: // _
+    case 0x24: // $
+    case 0x2D: // -
+      return 'ident'
+
+    case 0x09: // Tab
+    case 0x0A: // Newline
+    case 0x0D: // Return
+    case 0xA0:  // No-break space
+    case 0xFEFF:  // Byte Order Mark
+    case 0x2028:  // Line Separator
+    case 0x2029:  // Paragraph Separator
+      return 'ws'
+  }
+
+  return 'ident'
+}
+
+/**
+ * Format a subPath, return its plain form if it is
+ * a literal string or number. Otherwise prepend the
+ * dynamic indicator (*).
+ */
+
+function formatSubPath (path: string): boolean | string {
+  const trimmed: string = path.trim()
+  // invalid leading 0
+  if (path.charAt(0) === '0' && isNaN(path)) { return false }
+
+  return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed
+}
+
+/**
+ * Parse a string path into an array of segments
+ */
+
+function parse (path: Path): ?Array<string> {
+  const keys: Array<string> = []
+  let index: number = -1
+  let mode: number = BEFORE_PATH
+  let subPathDepth: number = 0
+  let c: ?string
+  let key: any
+  let newChar: any
+  let type: string
+  let transition: number
+  let action: Function
+  let typeMap: any
+  const actions: Array<Function> = []
+
+  actions[PUSH] = function () {
+    if (key !== undefined) {
+      keys.push(key)
+      key = undefined
+    }
+  }
+
+  actions[APPEND] = function () {
+    if (key === undefined) {
+      key = newChar
+    } else {
+      key += newChar
+    }
+  }
+
+  actions[INC_SUB_PATH_DEPTH] = function () {
+    actions[APPEND]()
+    subPathDepth++
+  }
+
+  actions[PUSH_SUB_PATH] = function () {
+    if (subPathDepth > 0) {
+      subPathDepth--
+      mode = IN_SUB_PATH
+      actions[APPEND]()
+    } else {
+      subPathDepth = 0
+      if (key === undefined) { return false }
+      key = formatSubPath(key)
+      if (key === false) {
+        return false
+      } else {
+        actions[PUSH]()
+      }
+    }
+  }
+
+  function maybeUnescapeQuote (): ?boolean {
+    const nextChar: string = path[index + 1]
+    if ((mode === IN_SINGLE_QUOTE && nextChar === "'") ||
+      (mode === IN_DOUBLE_QUOTE && nextChar === '"')) {
+      index++
+      newChar = '\\' + nextChar
+      actions[APPEND]()
+      return true
+    }
+  }
+
+  while (mode !== null) {
+    index++
+    c = path[index]
+
+    if (c === '\\' && maybeUnescapeQuote()) {
+      continue
+    }
+
+    type = getPathCharType(c)
+    typeMap = pathStateMachine[mode]
+    transition = typeMap[type] || typeMap['else'] || ERROR
+
+    if (transition === ERROR) {
+      return // parse error
+    }
+
+    mode = transition[0]
+    action = actions[transition[1]]
+    if (action) {
+      newChar = transition[2]
+      newChar = newChar === undefined
+        ? c
+        : newChar
+      if (action() === false) {
+        return
+      }
+    }
+
+    if (mode === AFTER_PATH) {
+      return keys
+    }
+  }
+}
+
+export type PathValue = PathValueObject | PathValueArray | Function | string | number | boolean | null
+export type PathValueObject = { [key: string]: PathValue }
+export type PathValueArray = Array<PathValue>
+
+export default class I18nPath {
+  _cache: Object
+
+  constructor () {
+    this._cache = Object.create(null)
+  }
+
+  /**
+   * External parse that check for a cache hit first
+   */
+  parsePath (path: Path): Array<string> {
+    let hit: ?Array<string> = this._cache[path]
+    if (!hit) {
+      hit = parse(path)
+      if (hit) {
+        this._cache[path] = hit
+      }
+    }
+    return hit || []
+  }
+
+  /**
+   * Get path value from path string
+   */
+  getPathValue (obj: mixed, path: Path): PathValue {
+    if (!isObject(obj)) { return null }
+
+    const paths: Array<string> = this.parsePath(path)
+    if (paths.length === 0) {
+      return null
+    } else {
+      const length: number = paths.length
+      let last: any = obj
+      let i: number = 0
+      while (i < length) {
+        const value: any = last[paths[i]]
+        if (value === undefined) {
+          return null
+        }
+        last = value
+        i++
+      }
+
+      return last
+    }
+  }
+}

+ 169 - 0
plugin/vue-i18n/src/util.js

@@ -0,0 +1,169 @@
+/* @flow */
+
+/**
+ * constants
+ */
+
+export const numberFormatKeys = [
+  'style',
+  'currency',
+  'currencyDisplay',
+  'useGrouping',
+  'minimumIntegerDigits',
+  'minimumFractionDigits',
+  'maximumFractionDigits',
+  'minimumSignificantDigits',
+  'maximumSignificantDigits',
+  'localeMatcher',
+  'formatMatcher',
+  'unit'
+]
+
+/**
+ * utilities
+ */
+
+export function warn (msg: string, err: ?Error): void {
+  if (typeof console !== 'undefined') {
+    console.warn('[vue-i18n] ' + msg)
+    /* istanbul ignore if */
+    if (err) {
+      console.warn(err.stack)
+    }
+  }
+}
+
+export function error (msg: string, err: ?Error): void {
+  if (typeof console !== 'undefined') {
+    console.error('[vue-i18n] ' + msg)
+    /* istanbul ignore if */
+    if (err) {
+      console.error(err.stack)
+    }
+  }
+}
+
+export const isArray = Array.isArray
+
+export function isObject (obj: mixed): boolean %checks {
+  return obj !== null && typeof obj === 'object'
+}
+
+export function isBoolean (val: mixed): boolean %checks {
+  return typeof val === 'boolean'
+}
+
+export function isString (val: mixed): boolean %checks {
+  return typeof val === 'string'
+}
+
+const toString: Function = Object.prototype.toString
+const OBJECT_STRING: string = '[object Object]'
+export function isPlainObject (obj: any): boolean {
+  return toString.call(obj) === OBJECT_STRING
+}
+
+export function isNull (val: mixed): boolean {
+  return val === null || val === undefined
+}
+
+export function isFunction (val: mixed): boolean %checks {
+  return typeof val === 'function'
+}
+
+export function parseArgs (...args: Array<mixed>): Object {
+  let locale: ?string = null
+  let params: mixed = null
+  if (args.length === 1) {
+    if (isObject(args[0]) || isArray(args[0])) {
+      params = args[0]
+    } else if (typeof args[0] === 'string') {
+      locale = args[0]
+    }
+  } else if (args.length === 2) {
+    if (typeof args[0] === 'string') {
+      locale = args[0]
+    }
+    /* istanbul ignore if */
+    if (isObject(args[1]) || isArray(args[1])) {
+      params = args[1]
+    }
+  }
+
+  return { locale, params }
+}
+
+export function looseClone (obj: Object): Object {
+  return JSON.parse(JSON.stringify(obj))
+}
+
+export function remove (arr: Array<any>, item: any): Array<any> | void {
+  if (arr.length) {
+    const index = arr.indexOf(item)
+    if (index > -1) {
+      return arr.splice(index, 1)
+    }
+  }
+}
+
+export function includes (arr: Array<any>, item: any): boolean {
+  return !!~arr.indexOf(item)
+}
+
+const hasOwnProperty = Object.prototype.hasOwnProperty
+export function hasOwn (obj: Object | Array<*>, key: string): boolean {
+  return hasOwnProperty.call(obj, key)
+}
+
+export function merge (target: Object): Object {
+  const output = Object(target)
+  for (let i = 1; i < arguments.length; i++) {
+    const source = arguments[i]
+    if (source !== undefined && source !== null) {
+      let key
+      for (key in source) {
+        if (hasOwn(source, key)) {
+          if (isObject(source[key])) {
+            output[key] = merge(output[key], source[key])
+          } else {
+            output[key] = source[key]
+          }
+        }
+      }
+    }
+  }
+  return output
+}
+
+export function looseEqual (a: any, b: any): boolean {
+  if (a === b) { return true }
+  const isObjectA: boolean = isObject(a)
+  const isObjectB: boolean = isObject(b)
+  if (isObjectA && isObjectB) {
+    try {
+      const isArrayA: boolean = isArray(a)
+      const isArrayB: boolean = isArray(b)
+      if (isArrayA && isArrayB) {
+        return a.length === b.length && a.every((e: any, i: number): boolean => {
+          return looseEqual(e, b[i])
+        })
+      } else if (!isArrayA && !isArrayB) {
+        const keysA: Array<string> = Object.keys(a)
+        const keysB: Array<string> = Object.keys(b)
+        return keysA.length === keysB.length && keysA.every((key: string): boolean => {
+          return looseEqual(a[key], b[key])
+        })
+      } else {
+        /* istanbul ignore next */
+        return false
+      }
+    } catch (e) {
+      /* istanbul ignore next */
+      return false
+    }
+  } else if (!isObjectA && !isObjectB) {
+    return String(a) === String(b)
+  } else {
+    return false
+  }
+}

+ 276 - 0
plugin/vue-i18n/types/index.d.ts

@@ -0,0 +1,276 @@
+import Vue, { PluginFunction } from 'vue';
+
+declare namespace VueI18n {
+  type Path = string;
+  type Locale = string;
+  type FallbackLocale = string | string[] | false | { [locale: string]: string[] }
+  type Values = any[] | { [key: string]: any };
+  type Choice = number;
+  interface MessageContext {
+    list(index: number): unknown
+    named(key: string): unknown
+  }
+  type MessageFunction = (ctx: MessageContext) => string;
+  type LocaleMessage = string | MessageFunction | LocaleMessageObject | LocaleMessageArray;
+  interface LocaleMessageObject { [key: string]: LocaleMessage; }
+  interface LocaleMessageArray { [index: number]: LocaleMessage; }
+  interface LocaleMessages { [key: string]: LocaleMessageObject; }
+  type TranslateResult = string | LocaleMessages;
+
+  type LocaleMatcher = 'lookup' | 'best-fit';
+  type FormatMatcher = 'basic' | 'best-fit';
+
+  type DateTimeHumanReadable = 'long' | 'short' | 'narrow';
+  type DateTimeDigital = 'numeric' | '2-digit';
+
+  interface SpecificDateTimeFormatOptions extends Intl.DateTimeFormatOptions {
+    year?: DateTimeDigital;
+    month?: DateTimeDigital | DateTimeHumanReadable;
+    day?: DateTimeDigital;
+    hour?: DateTimeDigital;
+    minute?: DateTimeDigital;
+    second?: DateTimeDigital;
+    weekday?: DateTimeHumanReadable;
+    era?: DateTimeHumanReadable;
+    timeZoneName?: 'long' | 'short';
+    localeMatcher?: LocaleMatcher;
+    formatMatcher?: FormatMatcher;
+  }
+
+  type DateTimeFormatOptions = Intl.DateTimeFormatOptions | SpecificDateTimeFormatOptions;
+
+  interface DateTimeFormat { [key: string]: DateTimeFormatOptions; }
+  interface DateTimeFormats { [locale: string]: DateTimeFormat; }
+  type DateTimeFormatResult = string;
+
+  type CurrencyDisplay = 'symbol' | 'code' | 'name';
+
+  interface SpecificNumberFormatOptions extends Intl.NumberFormatOptions {
+    style?: 'decimal' | 'percent';
+    currency?: string;
+    currencyDisplay?: CurrencyDisplay;
+    localeMatcher?: LocaleMatcher;
+    formatMatcher?: FormatMatcher;
+  }
+
+  interface CurrencyNumberFormatOptions extends Intl.NumberFormatOptions {
+    style: 'currency';
+    currency: string; // Obligatory if style is 'currency'
+    currencyDisplay?: CurrencyDisplay;
+    localeMatcher?: LocaleMatcher;
+    formatMatcher?: FormatMatcher;
+  }
+
+  type NumberFormatOptions = Intl.NumberFormatOptions | SpecificNumberFormatOptions | CurrencyNumberFormatOptions;
+
+  interface NumberFormat { [key: string]: NumberFormatOptions; }
+  interface NumberFormats { [locale: string]: NumberFormat; }
+  type NumberFormatResult = string;
+  type PluralizationRulesMap = {
+    /**
+     * @param choice {number} a choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)`
+     * @param choicesLength {number} an overall amount of available choices
+     * @returns a final choice index
+    */
+    [lang: string]: (choice: number, choicesLength: number) => number;
+  };
+  type Modifiers = { [key: string]: (str : string) => string };
+
+  type FormattedNumberPartType = 'currency' | 'decimal' | 'fraction' | 'group' | 'infinity' | 'integer' | 'literal' | 'minusSign' | 'nan' | 'plusSign' | 'percentSign';
+
+  type WarnHtmlInMessageLevel = 'off' | 'warn' | 'error';
+
+  interface FormattedNumberPart {
+    type: FormattedNumberPartType;
+    value: string;
+  }
+  interface NumberFormatToPartsResult { [index: number]: FormattedNumberPart; }
+
+  interface Formatter {
+    interpolate(message: string, values: Values | undefined, path: string): (any[] | null);
+  }
+
+  type MissingHandler = (locale: Locale, key: Path, vm: Vue | null, values: any) => string | void;
+  type PostTranslationHandler = (str: string, key?: string) => string;
+  type ComponentInstanceCreatedListener = (newVm: VueI18n & IVueI18n, rootVm: VueI18n & IVueI18n) => void;
+
+  interface IntlAvailability {
+    dateTimeFormat: boolean;
+    numberFormat: boolean;
+  }
+
+  // tslint:disable-next-line:interface-name
+  interface I18nOptions {
+    locale?: Locale;
+    fallbackLocale?: FallbackLocale;
+    messages?: LocaleMessages;
+    dateTimeFormats?: DateTimeFormats;
+    numberFormats?: NumberFormats;
+    formatter?: Formatter;
+    modifiers?: Modifiers,
+    missing?: MissingHandler;
+    fallbackRoot?: boolean;
+    formatFallbackMessages?: boolean;
+    sync?: boolean;
+    silentTranslationWarn?: boolean | RegExp;
+    silentFallbackWarn?: boolean | RegExp;
+    preserveDirectiveContent?: boolean;
+    pluralizationRules?: PluralizationRulesMap;
+    warnHtmlInMessage?: WarnHtmlInMessageLevel;
+    sharedMessages?: LocaleMessages;
+    postTranslation?: PostTranslationHandler;
+    componentInstanceCreatedListener?: ComponentInstanceCreatedListener;
+  }
+}
+
+export type Path = VueI18n.Path;
+export type Locale = VueI18n.Locale;
+export type FallbackLocale = VueI18n.FallbackLocale;
+export type Values = VueI18n.Values;
+export type Choice = VueI18n.Choice;
+export type MessageContext = VueI18n.MessageContext;
+export type MessageFunction = VueI18n.MessageFunction;
+export type LocaleMessage = VueI18n.LocaleMessage;
+export type LocaleMessageObject = VueI18n.LocaleMessageObject;
+export type LocaleMessageArray = VueI18n.LocaleMessageArray;
+export type LocaleMessages = VueI18n.LocaleMessages;
+export type TranslateResult = VueI18n.TranslateResult;
+export type DateTimeFormatOptions = VueI18n.DateTimeFormatOptions;
+export type DateTimeFormat = VueI18n.DateTimeFormat;
+export type DateTimeFormats = VueI18n.DateTimeFormats;
+export type DateTimeFormatResult = VueI18n.DateTimeFormatResult;
+export type NumberFormatOptions = VueI18n.NumberFormatOptions;
+export type NumberFormat = VueI18n.NumberFormat;
+export type NumberFormats = VueI18n.NumberFormats;
+export type NumberFormatResult = VueI18n.NumberFormatResult;
+export type NumberFormatToPartsResult = VueI18n.NumberFormatToPartsResult;
+export type WarnHtmlInMessageLevel = VueI18n.WarnHtmlInMessageLevel;
+export type Formatter = VueI18n.Formatter;
+export type MissingHandler = VueI18n.MissingHandler;
+export type PostTranslationHandler = VueI18n.PostTranslationHandler;
+export type IntlAvailability = VueI18n.IntlAvailability;
+export type I18nOptions = VueI18n.I18nOptions;
+
+export declare interface IVueI18n {
+  readonly messages: VueI18n.LocaleMessages;
+  readonly dateTimeFormats: VueI18n.DateTimeFormats;
+  readonly numberFormats: VueI18n.NumberFormats;
+
+  locale: VueI18n.Locale;
+  fallbackLocale: VueI18n.FallbackLocale;
+  missing: VueI18n.MissingHandler;
+  formatter: VueI18n.Formatter;
+  formatFallbackMessages: boolean;
+  silentTranslationWarn: boolean | RegExp;
+  silentFallbackWarn: boolean | RegExp;
+  preserveDirectiveContent: boolean;
+  pluralizationRules: VueI18n.PluralizationRulesMap;
+  warnHtmlInMessage: VueI18n.WarnHtmlInMessageLevel;
+  postTranslation: VueI18n.PostTranslationHandler;
+  t(key: VueI18n.Path, values?: VueI18n.Values): VueI18n.TranslateResult;
+  t(key: VueI18n.Path, locale: VueI18n.Locale, values?: VueI18n.Values): VueI18n.TranslateResult;
+  tc(key: VueI18n.Path, choice?: VueI18n.Choice, values?: VueI18n.Values): string;
+  tc(
+    key: VueI18n.Path,
+    choice: VueI18n.Choice,
+    locale: VueI18n.Locale,
+    values?: VueI18n.Values,
+  ): string;
+  te(key: VueI18n.Path, locale?: VueI18n.Locale): boolean;
+  d(
+    value: number | Date,
+    key?: VueI18n.Path,
+    locale?: VueI18n.Locale,
+  ): VueI18n.DateTimeFormatResult;
+  d(value: number | Date, args?: { [key: string]: string }): VueI18n.DateTimeFormatResult;
+  n(value: number, key?: VueI18n.Path, locale?: VueI18n.Locale): VueI18n.NumberFormatResult;
+  n(value: number, args?: { [key: string]: string }): VueI18n.NumberFormatResult;
+  getLocaleMessage(locale: VueI18n.Locale): VueI18n.LocaleMessageObject;
+  setLocaleMessage(locale: VueI18n.Locale, message: VueI18n.LocaleMessageObject): void;
+  mergeLocaleMessage(locale: VueI18n.Locale, message: VueI18n.LocaleMessageObject): void;
+  getDateTimeFormat(locale: VueI18n.Locale): VueI18n.DateTimeFormat;
+  setDateTimeFormat(locale: VueI18n.Locale, format: VueI18n.DateTimeFormat): void;
+  mergeDateTimeFormat(locale: VueI18n.Locale, format: VueI18n.DateTimeFormat): void;
+  getNumberFormat(locale: VueI18n.Locale): VueI18n.NumberFormat;
+  setNumberFormat(locale: VueI18n.Locale, format: VueI18n.NumberFormat): void;
+  mergeNumberFormat(locale: VueI18n.Locale, format: VueI18n.NumberFormat): void;
+  getChoiceIndex: (choice: number, choicesLength: number) => number;
+}
+
+declare class VueI18n {
+  constructor(options?: VueI18n.I18nOptions)
+
+  readonly messages: VueI18n.LocaleMessages;
+  readonly dateTimeFormats: VueI18n.DateTimeFormats;
+  readonly numberFormats: VueI18n.NumberFormats;
+  readonly availableLocales: VueI18n.Locale[];
+
+  locale: VueI18n.Locale;
+  fallbackLocale: VueI18n.FallbackLocale;
+  missing: VueI18n.MissingHandler;
+  formatter: VueI18n.Formatter;
+  formatFallbackMessages: boolean;
+  silentTranslationWarn: boolean | RegExp;
+  silentFallbackWarn: boolean | RegExp;
+  preserveDirectiveContent: boolean;
+  pluralizationRules: VueI18n.PluralizationRulesMap;
+  warnHtmlInMessage: VueI18n.WarnHtmlInMessageLevel;
+  postTranslation: VueI18n.PostTranslationHandler;
+
+  t(key: VueI18n.Path, values?: VueI18n.Values): VueI18n.TranslateResult;
+  t(key: VueI18n.Path, locale: VueI18n.Locale, values?: VueI18n.Values): VueI18n.TranslateResult;
+  tc(key: VueI18n.Path, choice?: VueI18n.Choice, values?: VueI18n.Values): string;
+  tc(key: VueI18n.Path, choice: VueI18n.Choice, locale: VueI18n.Locale, values?: VueI18n.Values): string;
+  te(key: VueI18n.Path, locale?: VueI18n.Locale): boolean;
+  d(value: number | Date, key?: VueI18n.Path, locale?: VueI18n.Locale): VueI18n.DateTimeFormatResult;
+  d(value: number | Date, args?: { [key: string]: string }): VueI18n.DateTimeFormatResult;
+  n(value: number, key?: VueI18n.Path, locale?: VueI18n.Locale): VueI18n.NumberFormatResult;
+  n(value: number, args?: { [key: string]: string }): VueI18n.NumberFormatResult;
+
+  getLocaleMessage(locale: VueI18n.Locale): VueI18n.LocaleMessageObject;
+  setLocaleMessage(locale: VueI18n.Locale, message: VueI18n.LocaleMessageObject): void;
+  mergeLocaleMessage(locale: VueI18n.Locale, message: VueI18n.LocaleMessageObject): void;
+
+  getDateTimeFormat(locale: VueI18n.Locale): VueI18n.DateTimeFormat;
+  setDateTimeFormat(locale: VueI18n.Locale, format: VueI18n.DateTimeFormat): void;
+  mergeDateTimeFormat(locale: VueI18n.Locale, format: VueI18n.DateTimeFormat): void;
+
+  getNumberFormat(locale: VueI18n.Locale): VueI18n.NumberFormat;
+  setNumberFormat(locale: VueI18n.Locale, format: VueI18n.NumberFormat): void;
+  mergeNumberFormat(locale: VueI18n.Locale, format: VueI18n.NumberFormat): void;
+
+  /**
+   * @param choice {number} a choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)`
+   * @param choicesLength {number} an overall amount of available choices
+   * @returns a final choice index
+  */
+  getChoiceIndex: (choice: number, choicesLength: number) => number;
+
+  static install: PluginFunction<never>;
+  static version: string;
+  static availabilities: VueI18n.IntlAvailability;
+}
+
+declare module 'vue/types/vue' {
+  interface Vue {
+    readonly $i18n: VueI18n & IVueI18n;
+    $t: typeof VueI18n.prototype.t;
+    $tc: typeof VueI18n.prototype.tc;
+    $te: typeof VueI18n.prototype.te;
+    $d: typeof VueI18n.prototype.d;
+    $n: typeof VueI18n.prototype.n;
+  }
+}
+
+declare module 'vue/types/options' {
+  interface ComponentOptions<V extends Vue> {
+    i18n?: {
+      messages?: VueI18n.LocaleMessages;
+      dateTimeFormats?: VueI18n.DateTimeFormats;
+      numberFormats?: VueI18n.NumberFormats;
+      sharedMessages?: VueI18n.LocaleMessages;
+    };
+  }
+}
+
+export default VueI18n;

+ 34 - 0
plugin/vue-i18n/vetur/attributes.json

@@ -0,0 +1,34 @@
+{
+  "i18n/path" : {
+    "description": "[required]\nKeypath of the locale message",
+    "type": "string"
+  },
+  "i18n/locale" : {
+    "description": "[optional]\nLocale to be used in this translation",
+    "type": "string"
+  },
+  "i18n/tag" : {
+    "description": "[optional]\nWhich tag to render, default is \"span\"",
+    "type": "string"
+  },
+  "i18n/places": {
+    "description": "[optional after v8.14]\nWill be removed in the next major version, use the slot syntax instead\n\nhttp://kazupon.github.io/vue-i18n/guide/interpolation.html#slots-syntax-usage",
+    "type": "array|object"
+  },
+  "i18n-n/value" : {
+    "description": "[required]\nNumber to be used in formatting",
+    "type": "number"
+  },
+  "i18n-n/format": {
+    "description": "[optional]\nNumber format name or object with explicit format options",
+    "type": "string|object"
+  },
+  "i18n-n/locale" : {
+    "description": "[optional]\nLocale to be used in this translation",
+    "type": "string"
+  },
+  "i18n-n/tag" : {
+    "description": "[optional]\nWhich tag to render, default is `span`",
+    "type": "string"
+  }
+}

+ 20 - 0
plugin/vue-i18n/vetur/tags.json

@@ -0,0 +1,20 @@
+{
+  "i18n": {
+    "attributes": [
+      "path",
+      "locale",
+      "tag",
+      "places"
+    ],
+    "description": "This is a functional component that can be used when HTML interpolation is needed.\n\nhttp://kazupon.github.io/vue-i18n/guide/interpolation.html#basic-usage"
+  },
+  "i18n-n": {
+    "attributes": [
+      "value",
+      "format",
+      "locale",
+      "tag"
+    ],
+    "description": "This functional component provides a way to use HTML interpolation in pair with number formatting.\n\nhttp://kazupon.github.io/vue-i18n/guide/number.html#custom-formatting"
+  }
+}

+ 30 - 2
store/index.js

@@ -1,6 +1,7 @@
 import Vue from 'vue'
 import Vuex from 'vuex'
 import user from './model/user'
+import i18n from '../libs/i18n/index.js'
 Vue.use(Vuex)
 
 const store = new Vuex.Store({
@@ -13,6 +14,22 @@ const store = new Vuex.Store({
 		weichatInfo: {}, //保存微信注册信息
 		weichatObj: '', //微信对象
 		// #endif
+		langList: [
+			{
+				value: 'en',
+				label: 'English'
+			},
+			// {
+			//      value: 'cn',
+			//      label: '简体中文'
+			//    },
+			{
+				value: 'tw',
+				label: '繁體中文'
+			}
+		],
+		lang:uni.getStorageSync('lang')||'tw',
+
 	},
 	mutations: {
 		//保存微信信息
@@ -22,12 +39,23 @@ const store = new Vuex.Store({
 		//保存微信对象
 		setWeiChatObj(state, provider) {
 			state.weichatObj = provider;
-		}
+		},
+		LANG(state, data) {
+			uni.setStorageSync('lang', data)
+			i18n.locale = data
+			state.lang = data
+		},
 	},
 	modules: {
 		user
 	},
-	actions: {}
+	actions: {
+		// 设置当前语言
+		setLang({ commit }, data) {
+		  commit('LANG', data)
+		  // commit('VANTLANG', data)
+		},
+	}
 })
 
 export default store

+ 1 - 1
uni.scss

@@ -1,7 +1,7 @@
 /* 页面左右间距 */
 $page-row-spacing: 30rpx;
 //页面基础颜色
-$page-color-base: #f8f8f8; //页面背景颜色
+$page-color-base: #000; //页面背景颜色
 $page-color-light: #f8f6fc;
 // 主题颜色
 $base-color: #902020; //项目颜色

Some files were not shown because too many files changed in this diff