Commit c52002e4 authored by dragondean@qq.com's avatar dragondean@qq.com

国际化

parent 40eb52de
Stack trace:
Frame Function Args
00800000010 0018006401E (001802839A0, 0018026EFD1, 00000000059, 000FFFFB700)
00800000010 0018004973A (00800000010, 00100000000, 00000000000, 00000000001)
00800000010 00180049772 (00000000000, 00000000000, 00000000059, 00180354100)
00800000010 00180070FE9 (00000000000, 000FFFFC7D0, 0000000000B, 00000000000)
00800000010 001800712A0 (00000000003, 000FFFFC8F0, 00180045BCF, 000FFFFC8F0)
00800000010 00180072AB9 (000FFFFC8F0, 00180271795, 001801004A7, 0000000000D)
00800000010 0018005B2A3 (7FF8018B1490, 00000000000, 00000000000, 000FFFFFFFF)
00800000010 0018005C655 (00800029390, 1D400000000, 00000000000, 00000000008)
00800000010 0018005CB3F (000FFFFCCE0, 000FFFFCC45, 00000000000, 205C745C615C635C)
000FFFFCBBC 0018005CF2F (635C655C205C265C, 3E5C205C6F5C685C, 765C655C645C2F5C, 795C745C745C2F5C)
000FFFFCCE0 00180049EE8 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0 00180048846 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0 001800488F4 (00000000000, 00000000000, 00000000000, 00000000000)
End of stack trace
Stack trace:
Frame Function Args
00800000010 0018006401E (001802839A0, 0018026EFD1, 00000000059, 000FFFFB710)
00800000010 0018004973A (00800000010, 00100000000, 00000000000, 00000000001)
00800000010 00180049772 (00000000000, 00000000000, 00000000059, 00180353FD0)
00800000010 00180070FE9 (00000000002, 000FFFFC7E0, 0000000000B, 00000000000)
00800000010 001800712A0 (000FFFFCBC0, 00800000010, 00180045B55, 000FFFFC900)
00800000010 00180072AB9 (000FFFFC900, 00180271795, 001801004A7, 0000000000D)
00800000010 0018005B2A3 (7FF8018B1490, 00000000000, 00000000000, 040FFFFFFFF)
00800000010 0018005C655 (00000000002, 00180350D08, 00000000002, 00000000008)
00800000010 0018005CB3F (000FFFFCC9C, 000FFFFCCE0, 000FFFFCC9D, 000FFFFCC00)
000FFFFCBCC 0018005CF2F (6D5C2D5C6C5C615C, 675C615C6E5C615C, 635C2D5C725C655C, 205C655C725C6F5C)
000FFFFCCE0 00180049EE8 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0 00180048846 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0 001800488F4 (00000000000, 00000000000, 00000000000, 00000000000)
End of stack trace
import Vue from 'vue'
import VueI18n from './vue-i18n/dist/vue-i18n.common'
import {getLocale} from '@/utils/db'
Vue.use(VueI18n)
const i18n = new VueI18n({
locale: getLocale() || 'zh_CN',
formatFallbackMessages: true,
messages: {
'en_US': require('./languages/en_US.json'),
'zh_CN': require('./languages/zh_CN.json')
}
})
console.log({i18n})
/* Vue.filter('$t', Vue.$i18n)
*/
// 重新console.warn来捕获未翻译的内容
/* console.wareOrig = console.warn
console.warn = (...data) => {
console.log('warn', typeof data)
console.wareOrig(data)
} */
export default i18n
\ No newline at end of file
{
"登录": "Login",
"个人中心": "User Center",
"布局设置": "Layout"
}
\ No newline at end of file
{
"登录": "登录"
}
\ No newline at end of file
## v8.27.2 (2022-06-20)
#### :bug: Bug Fixes
* [#1512](https://github.com/kazupon/vue-i18n/pull/1512) Allow modifiers names in pascalCase ([@nofacez](https://github.com/nofacez))
#### :pencil: Documentation
* [#1505](https://github.com/kazupon/vue-i18n/pull/1505) Update interpolation.md ([@victor1014](https://github.com/victor1014))
#### Committers: 2
- Mikhail ([@nofacez](https://github.com/nofacez))
- Victor ([@victor1014](https://github.com/victor1014))
## v8.27.1 (2022-03-29)
#### :zap: Improved Features
* [#1488](https://github.com/kazupon/vue-i18n/pull/1488) Allow colon in locale message keys used in linked locale messages ([@ax-jmckenzie](https://github.com/ax-jmckenzie))
#### :pencil: Documentation
* [#1462](https://github.com/kazupon/vue-i18n/pull/1462) Restrict version to 8 for installing npm package ([@arpi17](https://github.com/arpi17))
#### Committers: 2
- James McKenzie ([@ax-jmckenzie](https://github.com/ax-jmckenzie))
- Árpád Illyés ([@arpi17](https://github.com/arpi17))
## v8.27.0 (2022-01-21)
#### :star: New Features
* [#1441](https://github.com/kazupon/vue-i18n/pull/1441) feat: add a new option fallbackRootWithEmptyString ([@PeterAlfredLee](https://github.com/PeterAlfredLee))
#### Committers: 1
- Lee ([@PeterAlfredLee](https://github.com/PeterAlfredLee))
## v8.26.8 (2021-12-28)
#### :zap: Improved Features
* [#1429](https://github.com/kazupon/vue-i18n/pull/1429) improvement: type definition order for vue-i18n-bridge integration ([@kazupon](https://github.com/kazupon))
#### :pencil: Documentation
* [#1416](https://github.com/kazupon/vue-i18n/pull/1416) Update links to i18n Ally in tooling docs ([@FloEdelmann](https://github.com/FloEdelmann))
#### Committers: 2
- Flo Edelmann ([@FloEdelmann](https://github.com/FloEdelmann))
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.26.7 (2021-11-02)
#### :bug: Bug Fixes
* [#1411](https://github.com/kazupon/vue-i18n/pull/1411) fix: cannot work watchLocale on vue-i18n-bridge ([@kazupon](https://github.com/kazupon))
#### Committers: 1
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.26.6 (2021-11-02)
#### :zap: Improved Features
* [#1409](https://github.com/kazupon/vue-i18n/pull/1409) improvement: notify locale changing to composer ([@kazupon](https://github.com/kazupon))
#### Committers: 1
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.26.5 (2021-10-01)
#### :zap: Improved Features
* [#1396](https://github.com/kazupon/vue-i18n/pull/1396) Revert "improvement: $i18n property deinition for vue-i18n-bridge" ([@kazupon](https://github.com/kazupon))
#### Committers: 1
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.26.4 (2021-10-01)
#### :zap: Improved Features
* [#1394](https://github.com/kazupon/vue-i18n/pull/1394) improvement: $i18n property deinition for vue-i18n-bridge ([@kazupon](https://github.com/kazupon))
#### Committers: 1
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.26.3 (2021-09-30)
#### :zap: Improved Features
* [#1392](https://github.com/kazupon/vue-i18n/pull/1392) improvement: vue-i18n-loader bridge mode ([@kazupon](https://github.com/kazupon))
#### Committers: 1
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.26.2 (2021-09-28)
#### :zap: Improved Features
* [#1390](https://github.com/kazupon/vue-i18n/pull/1390) improvement: add flags for vue-i18n-bridge ([@kazupon](https://github.com/kazupon))
#### Committers: 1
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.26.1 (2021-09-23)
#### :zap: Improved Features
* [#1388](https://github.com/kazupon/vue-i18n/pull/1388) feat: add sync property ([@kazupon](https://github.com/kazupon))
#### Committers: 1
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.26.0 (2021-09-22)
#### :star: New Features
* [#1385](https://github.com/kazupon/vue-i18n/pull/1385) feat: support for vue-i18n-bridge ([@kazupon](https://github.com/kazupon))
#### Committers: 1
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.25.1 (2021-09-13)
#### :bug: Bug Fixes
* [#1381](https://github.com/kazupon/vue-i18n/pull/1381) fix: linked messages containing slash symbol ([@Lamberthassel](https://github.com/Lamberthassel))
#### :lock: Security Fixes
* [#1353](https://github.com/kazupon/vue-i18n/pull/1353) build(deps): [security] bump tar from 6.0.2 to 6.1.3 ([@dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
#### :pencil: Documentation
* [#1323](https://github.com/kazupon/vue-i18n/pull/1323) Added version notice for custom pluralizations ([@ingria](https://github.com/ingria))
#### Committers: 3
- Igor Nabebin ([@Lamberthassel](https://github.com/Lamberthassel))
- Ingria ([@ingria](https://github.com/ingria))
- [@dependabot-preview[bot]](https://github.com/apps/dependabot-preview)
## v8.25.0 (2021-07-16)
#### :star: New Features
* [#1271](https://github.com/kazupon/vue-i18n/pull/1271) feat: Added linked, locale, formatter, values, path to MessageContext ([@fabis94](https://github.com/fabis94))
#### :bug: Bug Fixes
* [#1321](https://github.com/kazupon/vue-i18n/pull/1321) fix broken mergeLocaleMessage ([@phonezawphyo](https://github.com/phonezawphyo))
#### Committers: 3
- [@dependabot-preview[bot]](https://github.com/apps/dependabot-preview)
- [@fabis94](https://github.com/fabis94)
- [@phonezawphyo](https://github.com/phonezawphyo)
## v8.24.5 (2021-06-19)
#### :bug: Bug Fixes
* [#1278](https://github.com/kazupon/vue-i18n/pull/1278) fix: Ensure that the order at desroy is the same as before change to `Set` from `Array` ([@kazupon](https://github.com/kazupon))
#### :zap: Improved Features
* [#1194](https://github.com/kazupon/vue-i18n/pull/1194) fix: add locale arg type i18n.n method type signature ([@alireza4050](https://github.com/alireza4050))
#### :pencil: Documentation
* [#1273](https://github.com/kazupon/vue-i18n/pull/1273) docs(api:zh): update the Chinese docs of "API" ([@baboon-king](https://github.com/baboon-king))
* [#1267](https://github.com/kazupon/vue-i18n/pull/1267) Documentation - Update @kazupon/vue-i18n-loader to @intlify/vue-i18n-loader ([@fbigand](https://github.com/fbigand))
* [#1258](https://github.com/kazupon/vue-i18n/pull/1258) Grammar fix for Installing vue-i18n-loader ([@TerabyteTiger](https://github.com/TerabyteTiger))
#### Committers: 5
- Alireza Asgharizadeh ([@alireza4050](https://github.com/alireza4050))
- BaboonKing ([@baboon-king](https://github.com/baboon-king))
- Tyler V ([@TerabyteTiger](https://github.com/TerabyteTiger))
- [@fbigand](https://github.com/fbigand)
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.24.4 (2021-04-28)
#### :bug: Bug Fixes
* [#1192](https://github.com/kazupon/vue-i18n/pull/1192) Revert "fix: i18n reference to root causes memory leak (#1044)" ([@kazupon](https://github.com/kazupon))
#### Committers: 2
- Alexander Sokolov ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.24.3 (2021-04-09)
#### :bug: Bug Fixes
* [#1175](https://github.com/kazupon/vue-i18n/pull/1175) [perf] Use Set so lookup of _dataListeners can be O(1) ([@exoego](https://github.com/exoego))
#### :chart_with_upwards_trend: Performance Fixes
* [#1175](https://github.com/kazupon/vue-i18n/pull/1175) [perf] Use Set so lookup of _dataListeners can be O(1) ([@exoego](https://github.com/exoego))
#### Committers: 1
- TATSUNO Yasuhiro ([@exoego](https://github.com/exoego))
## v8.24.2 (2021-03-23)
#### :bug: Bug Fixes
* [#1151](https://github.com/kazupon/vue-i18n/pull/1151) fix: i18n reference to root causes memory leak (#1044) ([@lzxb](https://github.com/lzxb))
#### :pencil: Documentation
* [#1152](https://github.com/kazupon/vue-i18n/pull/1152) $tc return type ([@Glandos](https://github.com/Glandos))
#### Committers: 2
- Glandos ([@Glandos](https://github.com/Glandos))
- 狼族小狈 ([@lzxb](https://github.com/lzxb))
## v8.24.1 (2021-03-11)
#### :bug: Bug Fixes
* [#1145](https://github.com/kazupon/vue-i18n/pull/1145) Allowing paths to be null for lookups. ([@martinheidegger](https://github.com/martinheidegger))
#### Committers: 1
- Martin Heidegger ([@martinheidegger](https://github.com/martinheidegger))
## v8.24.0 (2021-03-08)
#### :star: New Features
* [#1139](https://github.com/kazupon/vue-i18n/pull/1139) experimental: add meta info for intlify tools ([@kazupon](https://github.com/kazupon))
#### Committers: 1
- kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
## v8.23.0 (2021-02-24)
#### :zap: Improved Features
* [#1118](https://github.com/kazupon/vue-i18n/pull/1118) Fix wrong LocaleMatcher type for TS 4.2 ('best-fit' to 'best fit'). ([@mpawelski](https://github.com/mpawelski))
#### :pencil: Documentation
* [#1124](https://github.com/kazupon/vue-i18n/pull/1124) Add documentation for directive `choice` argument ([@Gameghostify](https://github.com/Gameghostify))
* [#1114](https://github.com/kazupon/vue-i18n/pull/1114) Update tooling.md ([@fanlinqiang](https://github.com/fanlinqiang))
* [#1104](https://github.com/kazupon/vue-i18n/pull/1104) Documentation improvemation ([@lucasferreiralimax](https://github.com/lucasferreiralimax))
#### Committers: 4
- Lucas ([@lucasferreiralimax](https://github.com/lucasferreiralimax))
- Mariusz Pawelski ([@mpawelski](https://github.com/mpawelski))
- [@Gameghostify](https://github.com/Gameghostify)
- [@fanlinqiang](https://github.com/fanlinqiang)
## v8.22.4 (2021-01-16)
#### :chart_with_upwards_trend: Performance Fixes
* [#1101](https://github.com/kazupon/vue-i18n/pull/1101) Improve performance of mergeLocaleMessage (#1099) ([@cslee](https://github.com/cslee))
#### Committers: 2
- Eric Lee ([@cslee](https://github.com/cslee))
- Lucas ([@lucasferreiralimax](https://github.com/lucasferreiralimax))
## v8.22.3 (2021-01-08)
#### :zap: Improved Features
* [#1096](https://github.com/kazupon/vue-i18n/pull/1096) @types: Fixed too narrow option types in n() and d() methods ([@gehlert](https://github.com/gehlert))
#### Committers: 3
- MASONGZHI ([@masongzhi](https://github.com/masongzhi))
- TATSUNO Yasuhiro ([@exoego](https://github.com/exoego))
- [@gehlert](https://github.com/gehlert)
## v8.22.2 (2020-11-18)
#### :bug: Bug Fixes
* [#1048](https://github.com/kazupon/vue-i18n/pull/1048) fix: number format keys missing compared the Intl.Number object ([@jevillard](https://github.com/jevillard))
#### Committers: 2
- Alexander Sokolov ([@Alex-Sokolov](https://github.com/Alex-Sokolov))
- Jérémy Villard ([@jevillard](https://github.com/jevillard))
## v8.22.1 (2020-10-19)
#### :boom: Breaking Change
* [#1020](https://github.com/kazupon/vue-i18n/pull/1020) escapeParameterHtml flag: Don't escape ampersand #1019 ([@gardarh](https://github.com/gardarh))
#### Committers: 1
- Gardar Hauksson ([@gardarh](https://github.com/gardarh))
## v8.22.0 (2020-10-06)
#### :star: New Features
* [#1009](https://github.com/kazupon/vue-i18n/pull/1009) Add escapeParameterHtml parameter. #1002 ([@gardarh](https://github.com/gardarh))
#### :bug: Bug Fixes
* [#1003](https://github.com/kazupon/vue-i18n/pull/1003) Bugfix in index.js: wrong if condition in fetchChoice ([@cimchd](https://github.com/cimchd))
#### Committers: 4
- Andreas ([@devmount](https://github.com/devmount))
- Gardar Hauksson ([@gardarh](https://github.com/gardarh))
- Raffaele Pizzari ([@pixari](https://github.com/pixari))
- [@cimchd](https://github.com/cimchd)
## v8.21.1 (2020-09-11)
#### :bug: Bug Fixes
* [#995](https://github.com/kazupon/vue-i18n/pull/995) Update mixin.js ([@ferencbeutel4711](https://github.com/ferencbeutel4711))
#### Committers: 1
- Ferenc Beutel ([@ferencbeutel4711](https://github.com/ferencbeutel4711))
## 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
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.
<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="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>
</p>
<p align="center">Internationalization plugin for Vue.js</p>
<br/>
<h3 align="center">🏅 Platinum 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"
width="400px"
/>
</a>
</p>
<h3 align="center">✨ Special Sponsors</h3>
<p align="center">
<a
href="https://plaid.co.jp/"
target="_blank">
<img
src="https://raw.githubusercontent.com/kazupon/vue-i18n/v8.x/vuepress/.vuepress/public/patrons/plaid.svg"
width="240px"
/>
</a>
</p>
<h3 align="center">🥇 Gold Sponsors</h3>
<p align="center">
<a
href="https://nuxtjs.org/"
target="_blank">
<img
src="https://raw.githubusercontent.com/kazupon/vue-i18n/v8.x/vuepress/.vuepress/public/patrons/nuxt.png"
width="240px"
/>
</a>
</p>
<p align="center">
<a
href="https://rapidapi.com/"
target="_blank">
<img
src="https://raw.githubusercontent.com/kazupon/vue-i18n/v8.x/vuepress/.vuepress/public/patrons/RapidAPI.svg"
width="240px"
/>
</a>
</p>
<p align="center">
<a
href="https://localazy.com/blog/how-to-localize-vuejs-app-with-vue-i18n-and-localazy?utm_source=kazupon&utm_medium=banner&utm_campaign=sponsorships_kazupon&utm_content=logo"
target="_blank">
<img
src="https://raw.githubusercontent.com/kazupon/vue-i18n/v8.x/vuepress/.vuepress/public/patrons/localazy.svg"
width="240px"
/>
</a>
</p>
<p align="center">
<a
href="https://crowdin.com/teams/engineering?utm_source=vue-i18n.intlify.dev&utm_medium=referral"
target="_blank">
<img
src="https://raw.githubusercontent.com/kazupon/vue-i18n/v8.x/vuepress/.vuepress/public/patrons/crowdin.svg"
width="240px"
/>
</a>
</p>
<h3 align="center">🥈 Silver Sponsors</h3>
<h3 align="center">🥉 Bronze Sponsors</h3>
<p align="center">
<a href="https://www.sendcloud.com/" target="_blank">
<img
src="https://raw.githubusercontent.com/kazupon/vue-i18n/v8.x/vuepress/.vuepress/public/patrons/sendcloud.png"
width="144px"
/>
</a>
</p>
<p align="center">
<a href="https://www.vuemastery.com/" target="_blank">
<img
src="https://raw.githubusercontent.com/kazupon/vue-i18n/v8.x/vuepress/.vuepress/public/patrons/vuemastery.png"
width="144px"
/>
</a>
</p>
<p align="center">
<a href="https://www.deci-bel.com/" target="_blank">
<img
src="https://raw.githubusercontent.com/kazupon/vue-i18n/v8.x/vuepress/.vuepress/public/patrons/decibel.png"
width="144px"
/>
</a>
</p>
<br/>
## ⚠️ NOTICE
**This repository is for Vue I18n v8.x and Vue 2**
**If you want to know about how to usage for Vue I18n v9 on Vue 3, See the [this repository](https://github.com/intlify/vue-i18n-next))**
## 🙋‍♂️ About support for v8
We will follow Vue v2 maintenance lifespan
## 📔 Documentation
About Vue I18n v8.x, See [here](http://kazupon.github.io/vue-i18n/)
If you want to read Vue I18n v9 docs, See [here](https://vue-i18n.intlify.dev/)
## 📜 Changelog
Detailed changes for each release are documented in the [CHANGELOG.md](https://github.com/kazupon/vue-i18n/blob/dev/CHANGELOG.md).
## ❗ 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.
## 💪 Contribution
Please make sure to read the [Contributing Guide](https://github.com/kazupon/vue-i18n/blob/dev/CONTRIBUTING.md) before making a pull request.
## ©️ License
[MIT](http://opensource.org/licenses/MIT)
declare var Intl: any;
declare type Path = string;
declare type Locale = string;
declare type MessageContext = {
list: (index: number) => mixed,
named: (key: string) => mixed,
linked: (key: string) => TranslateResult,
values: any,
path: string,
formatter: Formatter,
messages: LocaleMessages,
locale: Locale
}
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,
datetimeFormats?: DateTimeFormats,
numberFormats?: NumberFormats,
formatter?: Formatter,
missing?: MissingHandler,
modifiers?: Modifiers,
root?: I18n, // for internal
fallbackRoot?: boolean,
fallbackRootWithEmptyString?: boolean,
formatFallbackMessages?: boolean,
sync?: boolean,
silentTranslationWarn?: boolean | RegExp,
silentFallbackWarn?: boolean | RegExp,
pluralizationRules?: PluralizationRules,
preserveDirectiveContent?: boolean,
warnHtmlInMessage?: WarnHtmlInMessageLevel,
sharedMessages?: LocaleMessage,
postTranslation?: PostTranslationHandler,
componentInstanceCreatedListener?: ComponentInstanceCreatedListener,
escapeParameterHtml?: boolean,
__VUE_I18N_BRIDGE__?: string,
};
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)
};
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,
}
{
"_from": "vue-i18n@^8.27.2",
"_id": "vue-i18n@8.27.2",
"_inBundle": false,
"_integrity": "sha512-QVzn7u2WVH8F7eSKIM00lujC7x1mnuGPaTnDTmB01Hd709jDtB9kYtBqM+MWmp5AJRx3gnqAdZbee9MelqwFBg==",
"_location": "/vue-i18n",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "vue-i18n@^8.27.2",
"name": "vue-i18n",
"escapedName": "vue-i18n",
"rawSpec": "^8.27.2",
"saveSpec": null,
"fetchSpec": "^8.27.2"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.27.2.tgz",
"_shasum": "b649a65ff42b7d1a482679b732902f889965a068",
"_spec": "vue-i18n@^8.27.2",
"_where": "D:\\projects\\jiedao-admin",
"author": {
"name": "kazuya kawaguchi",
"email": "kawakazu80@gmail.com"
},
"bugs": {
"url": "https://github.com/kazupon/vue-i18n/issues"
},
"bundleDependencies": false,
"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"
}
},
"deprecated": false,
"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",
"@vuepress/theme-vue": "^1.9.7",
"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": "^102.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": "^7.14.0",
"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": "^2.1.1",
"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.23.3",
"sinon": "^11.1.1",
"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.8.2",
"webpack": "^4.43.0",
"webpack-cli": "^4.7.2",
"webpack-dev-middleware": "^5.0.0",
"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.27.2",
"vetur": {
"tags": "vetur/tags.json",
"attributes": "vetur/attributes.json"
}
}
/* @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)
}
/* @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
}
}
/* @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
}
/* @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)
}
}
/* @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
}
/* @flow */
import { install, Vue } from './install'
import {
warn,
error,
isNull,
parseArgs,
isPlainObject,
isObject,
isArray,
isBoolean,
isString,
isFunction,
looseClone,
remove,
arrayFrom,
includes,
merge,
numberFormatKeys,
escapeParams
} from './util'
import BaseFormatter from './format'
import I18nPath from './path'
import type { PathValue } from './path'
const htmlTagMatcher = /<\/?[\w\s="/.':;#-\/]+>/
const linkKeyMatcher = /(?:@(?:\.[a-zA-Z]+)?:(?:[\w\-_|./]+|\([\w\-_:|./]+\)))/g
const linkKeyPrefixMatcher = /^@(?:\.([a-zA-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
_fallbackRootWithEmptyString: 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: Set<any>
_componentInstanceCreatedListener: ?ComponentInstanceCreatedListener
_preserveDirectiveContent: boolean
_warnHtmlInMessage: WarnHtmlInMessageLevel
_escapeParameterHtml: boolean
_postTranslation: ?PostTranslationHandler
__VUE_I18N_BRIDGE__: ?string
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 || 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._fallbackRootWithEmptyString = options.fallbackRootWithEmptyString === undefined
? true
: !!options.fallbackRootWithEmptyString
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 = new Set()
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
this._escapeParameterHtml = options.escapeParameterHtml || false
if ('__VUE_I18N_BRIDGE__' in options) {
this.__VUE_I18N_BRIDGE__ = options.__VUE_I18N_BRIDGE__
}
/**
* @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, __VUE18N__INSTANCE__: true })
Vue.config.silent = silent
}
destroyVM (): void {
this._vm.$destroy()
}
subscribeDataChanging (vm: any): void {
this._dataListeners.add(vm)
}
unsubscribeDataChanging (vm: any): void {
remove(this._dataListeners, vm)
}
watchI18nData (): Function {
const self = this
return this._vm.$watch('$data', () => {
const listeners = arrayFrom(this._dataListeners)
let i = listeners.length
while(i--) {
Vue.nextTick(() => {
listeners[i] && listeners[i].$forceUpdate()
})
}
}, { deep: true })
}
watchLocale (composer?: any): ?Function {
if (!composer) {
/* 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 })
} else {
// deal with vue-i18n-bridge
if (!this.__VUE_I18N_BRIDGE__) { return null }
const self = this
const target: any = this._vm
return this.vm.$watch('locale', (val) => {
target.$set(target, 'locale', val)
if (self.__VUE_I18N_BRIDGE__ && composer) {
composer.locale.value = 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 }
get sync (): boolean { return this._sync }
set sync (val: boolean): void { this._sync = val }
_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 (this._fallbackRootWithEmptyString? !val : isNull(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)
// eslint-disable-next-line no-autofix/prefer-const
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, formatter: Formatter, path: string, interpolateMode: string): 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]
const messages = this._getMessages()
const locale = this.locale
return {
list,
named,
values,
formatter,
path,
messages,
locale,
linked: (linkedKey: string) => this._interpolate(locale, messages[locale] || {}, linkedKey, null, interpolateMode, undefined, [linkedKey])
}
}
_render (message: string | MessageFunction, interpolateMode: string, values: any, path: string): any {
if (isFunction(message)) {
return message(
this._createMessageContext(values, this._formatter || defaultFormatter, path, interpolateMode)
)
}
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)
if(this._escapeParameterHtml) {
parsedArgs.params = escapeParams(parsedArgs.params)
}
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(
typeof this._vm.messages[locale] !== 'undefined' && Object.keys(this._vm.messages[locale]).length
? Object.assign({}, 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 {
// eslint-disable-next-line no-autofix/prefer-const
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 {
// eslint-disable-next-line no-autofix/prefer-const
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__'
import { warn } from './util'
import extend from './extend'
import defineMixin 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, options = { bridge: false }) {
/* 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(defineMixin(options.bridge))
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
}
}
/* @flow */
import VueI18n from './index'
import { isPlainObject, warn, error, merge } from './util'
/**
* Mixin
*
* If `bridge` mode, empty mixin is returned,
* else regulary mixin implementation is returned.
*/
export default function defineMixin (bridge: boolean = false) {
function mounted (): void {
if (this !== this.$root && this.$options.__INTLIFY_META__ && this.$el) {
this.$el.setAttribute('data-intlify', this.$options.__INTLIFY_META__)
}
}
return bridge
? { mounted } // delegate `vue-i18n-bridge` mixin implementation
: { // regulary
beforeCreate (): void {
const options: any = this.$options
options.i18n = options.i18n || ((options.__i18nBridge || options.__i18n) ? {} : null)
if (options.i18n) {
if (options.i18n instanceof VueI18n) {
// init locale messages via custom blocks
if ((options.__i18nBridge || options.__i18n)) {
try {
let localeMessages = options.i18n && options.i18n.messages ? options.i18n.messages : {}
const __i18n = options.__i18nBridge || options.__i18n
__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.__i18nBridge || options.__i18n)) {
try {
let localeMessages = options.i18n && options.i18n.messages ? options.i18n.messages : {}
const __i18n = options.__i18nBridge || options.__i18n
__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.__i18nBridge || 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
}
},
mounted,
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
}
})
}
}
}
/* @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 || value === null) {
return null
}
last = value
i++
}
return last
}
}
}
/* @flow */
/**
* constants
*/
export const numberFormatKeys = [
'compactDisplay',
'currency',
'currencyDisplay',
'currencySign',
'localeMatcher',
'notation',
'numberingSystem',
'signDisplay',
'style',
'unit',
'unitDisplay',
'useGrouping',
'minimumIntegerDigits',
'minimumFractionDigits',
'maximumFractionDigits',
'minimumSignificantDigits',
'maximumSignificantDigits'
]
/**
* 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: Set<any>, item: any): Set<any> | void {
if (arr.delete(item)) {
return arr
}
}
export function arrayFrom (arr: Set<any>): Array<any> {
const ret = []
arr.forEach(a => ret.push(a))
return ret
}
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
}
}
/**
* Sanitizes html special characters from input strings. For mitigating risk of XSS attacks.
* @param rawText The raw input from the user that should be escaped.
*/
function escapeHtml(rawText: string): string {
return rawText
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;')
}
/**
* Escapes html tags and special symbols from all provided params which were returned from parseArgs().params.
* This method performs an in-place operation on the params object.
*
* @param {any} params Parameters as provided from `parseArgs().params`.
* May be either an array of strings or a string->any map.
*
* @returns The manipulated `params` object.
*/
export function escapeParams(params: any): any {
if(params != null) {
Object.keys(params).forEach(key => {
if(typeof(params[key]) == 'string') {
params[key] = escapeHtml(params[key])
}
})
}
return params
}
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 type PluignOptions = VueI18n.PluignOptions
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
linked(key: string): VueI18n.TranslateResult
values: any
path: string
formatter: Formatter
messages: LocaleMessages
locale: Locale
}
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;
fallbackRootWithEmptyString?: boolean,
formatFallbackMessages?: boolean;
sync?: boolean;
silentTranslationWarn?: boolean | RegExp;
silentFallbackWarn?: boolean | RegExp;
preserveDirectiveContent?: boolean;
pluralizationRules?: PluralizationRulesMap;
warnHtmlInMessage?: WarnHtmlInMessageLevel;
sharedMessages?: LocaleMessages;
postTranslation?: PostTranslationHandler;
componentInstanceCreatedListener?: ComponentInstanceCreatedListener;
escapeParameterHtml?: boolean;
}
type PluignOptions = {
bridge?: boolean
}
}
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;
sync: 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;
d(value: number | Date, options?: VueI18n.DateTimeFormatOptions): VueI18n.DateTimeFormatResult;
n(value: number, key?: VueI18n.Path, locale?: VueI18n.Locale): VueI18n.NumberFormatResult;
n(value: number, args?: { [key: string]: string }): VueI18n.NumberFormatResult;
n(value: number, options?: VueI18n.NumberFormatOptions, locale?: VueI18n.Locale): 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;
sync: boolean;
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;
d(value: number | Date, options?: VueI18n.DateTimeFormatOptions): VueI18n.DateTimeFormatResult;
n(value: number, key?: VueI18n.Path, locale?: VueI18n.Locale): VueI18n.NumberFormatResult;
n(value: number, args?: { [key: string]: string }): VueI18n.NumberFormatResult;
n(value: number, options?: VueI18n.NumberFormatOptions, locale?: VueI18n.Locale): 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<VueI18n.PluignOptions>;
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;
{
"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"
}
}
{
"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"
}
}
......@@ -27,15 +27,17 @@
<screenfull id="screenfull" class="right-menu-item hover-effect" />
<el-tooltip content="布局大小" effect="dark" placement="bottom">
<el-tooltip :content="$t('布局大小')" effect="dark" placement="bottom">
<size-select id="size-select" class="right-menu-item hover-effect" />
</el-tooltip>
</template>
<el-select v-model="locale" placeholder="语言" class="right-menu-item select-nav" @change="localeChange">
<!-- <el-select v-model="locale" placeholder="语言" class="right-menu-item select-nav" @change="localeChange">
<el-option v-for="dict in langDatas" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-select> -->
<dict-selector :type="DICT_TYPE.SYSTEM_LOCALE" v-model="lang" defaultable class="right-menu-item select-nav" />
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper">
......@@ -44,7 +46,7 @@
</div>
<el-dropdown-menu slot="dropdown">
<router-link to="/user/profile">
<el-dropdown-item>个人中心</el-dropdown-item>
<el-dropdown-item>{{$t('个人中心')}}</el-dropdown-item>
</router-link>
<el-dropdown-item @click.native="setting = true">
<span>布局设置</span>
......@@ -69,23 +71,23 @@ import Search from '@/components/HeaderSearch'
import RuoYiGit from '@/components/RuoYi/Git'
import RuoYiDoc from '@/components/RuoYi/Doc'
import {getLocale, saveLocale} from "@/utils/db";
import {LangEnum} from "@/utils/constants";
import unreadMessage from "@/assets/images/unread-message.png"
import i18n from '@/i18n'
export default {
data() {
return {
unreadMessage,
locale: getLocale(),
// 枚举
langDatas: LangEnum.LANG,
// langDatas: LangEnum.LANG,
notReadTotal:0,//要去取VUEX里面的未读数据总数,我不会,登录之后要调得到当前人未读记录总数接口放到VUEX中
lang: i18n.locale, // 当前语言
}
},
created() {
this.$store.dispatch('getNotMessage');
this.$store.dispatch('getToDoList');
},
},
components: {
Breadcrumb,
TopNav,
......@@ -126,14 +128,22 @@ export default {
}
},
watch:{
lang(val){
console.log('切换了语言', val)
this.$i18n.locale = val
saveLocale(val)
}
},
methods: {
toggleSideBar() {
this.$store.dispatch('app/toggleSideBar')
},
localeChange(value) {
/* localeChange(value) {
console.log(value)
saveLocale(value)
},
}, */
async logout() {
this.$modal.confirm('确定注销并退出系统吗?', '提示').then(() => {
this.$store.dispatch('LogOut').then(() => {
......
import Vue from 'vue'
import Cookies from 'js-cookie'
import Element from 'element-ui'
import './assets/styles/element-variables.scss'
import '@/assets/styles/index.scss' // global css
import '@/assets/styles/ruoyi.scss' // ruoyi css
import App from './App'
......@@ -22,13 +19,13 @@ import { parseTime, resetForm, addDateRange, addBeginAndEndTime, handleTree} fro
import Pagination from "@/components/Pagination";
// 自定义表格工具扩展
import RightToolbar from "@/components/RightToolbar"
import TableForm from '@/components/TableForm'
import DictSelector from '@/components/DictSelector'
// 代码高亮插件
// import hljs from 'highlight.js'
// import 'highlight.js/styles/github-gist.css'
import {DICT_TYPE, getDictDataLabel, getDictDatas, getDictDatas2} from "@/utils/dict";
import i18n from './i18n'
console.log({i18n})
// 全局方法挂载
Vue.prototype.getDicts = getDicts
Vue.prototype.getConfigKey = getConfigKey
......@@ -69,7 +66,7 @@ Vue.component('DictTag', DictTag)
Vue.component('DocAlert', DocAlert)
Vue.component('Pagination', Pagination)
Vue.component('RightToolbar', RightToolbar)
Vue.component('TableForm', TableForm)
// Vue.component('TableForm', TableForm)
Vue.component('DictSelector', DictSelector)
// 字典标签组件
import DictTag from '@/components/DictTag'
......@@ -119,5 +116,6 @@ new Vue({
el: '#app',
router,
store,
i18n,
render: h => h(App)
})
......@@ -29,6 +29,7 @@ export const DICT_TYPE = {
SYSTEM_ERROR_CODE_TYPE: 'system_error_code_type',
INTERNAL_MESSAGE_TYPE: 'internal_message_type',
INTERNAL_MESSAGE_READ_STATUS: 'internal_message_read_status',
SYSTEM_LOCALE: 'system_locale', // 语言列表
HELP_DOC_STATUS: 'help_doc_status',
......
......@@ -3,26 +3,24 @@
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="编号" prop="orderNo">
<el-input v-model="queryParams.numberKey" placeholder="请输入订单号、唛头、提单号" clearable @keyup.enter.native="handleQuery" />
<el-form-item :label="$t('编号')" prop="orderNo">
<el-input v-model="queryParams.numberKey" :placeholder="$t('请输入订单号、唛头、提单号')" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<!-- <el-form-item label="唛头" prop="marks">
<el-input v-model="queryParams.marks" placeholder="唛头" clearable @keyup.enter.native="handleQuery" />
</el-form-item> -->
<el-form-item label="发货人" prop="consignorId">
<el-input v-model="queryParams.consignorId" placeholder="发货人" clearable @keyup.enter.native="handleQuery" />
<el-form-item :label="$t('发货人')" prop="consignorId">
<el-input v-model="queryParams.consignorId" :placeholder="$t('发货人')" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="收货人" prop="consigneeId">
<el-input v-model="queryParams.consigneeId" placeholder="收货人" clearable @keyup.enter.native="handleQuery" />
<el-form-item :label="$t('收货人')" prop="consigneeId">
<el-input v-model="queryParams.consigneeId" :placeholder="$t('收货人')" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="">
<dict-selector :type="DICT_TYPE.ECW_BEGINTIME_TYPE_ENDTIME" v-model="dateFilterType" defaultable style="width: 150px; margin-right: 5px" />
<el-date-picker v-model="dateFilter" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item label="始发地" prop="startWarehouseId">
<el-form-item :label="$t('始发地')" prop="startWarehouseId">
<el-select v-model="queryParams.startWarehouseId" placeholder="请选择始发地">
<el-option v-for="item in expoerCityList" :label="item.titleZh" :value="item.id" :key="item.id"></el-option>
</el-select>
......
......@@ -14,7 +14,7 @@
<el-input v-model="formData.tell" placeholder="请输入公司电话" clearable :style="{width: '100%'}"></el-input>
</el-form-item>
<el-form-item label="公司地址" prop="address">
<el-select v-model="formData.country">
<!-- <el-select v-model="formData.country">
<el-option v-for="(item, index) in treeList" :value="item.id" :label="item.titleZh" :key="item.id" />
</el-select>
<el-select v-model="formData.province">
......@@ -22,8 +22,16 @@
</el-select>
<el-select v-model="formData.city">
<el-option v-for="(item, index) in cityList" :value="item.id" :label="item.titleZh" :key="item.id" />
</el-select>
<el-input v-model="formData.address" placeholder="请输入详细地址"></el-input>
</el-select> -->
<area-selector
:country="formData.country"
:province="formData.province"
:city="formData.city"
@countryChange="onAreaChange('country', $event)"
@provinceChange="onAreaChange('province', $event)"
@cityChange="onAreaChange('city', $event)"
/>
<el-input v-model="formData.address" placeholder="请输入详细地址" class="mt-10"></el-input>
<!-- <el-select v-model="selectedRegionIndex">
<el-option v-for="(item, index) in regionList" :value="index" :label="item.titleZh" :key="item.id" />
</el-select> -->
......@@ -94,8 +102,10 @@
import { createSupplier, updateSupplier, getSupplier} from "@/api/ecw/supplier";
import upload from '@/components/ImageUpload'
import { getListTree } from "@/api/ecw/region";
import TableForm from '@/components/TableForm'
import AreaSelector from '@/components/AreaSelector'
export default {
components: {upload},
components: {upload, TableForm, AreaSelector},
props: [],
data() {
return {
......@@ -176,9 +186,9 @@ export default {
},
mounted() {},
methods: {
onProvinceSelected(e){
console.log(e, e)
},
onAreaChange(type, val){
this.$set(this.formData, type, val)
},
submitForm() {
this.$refs["elForm"].validate(valid => {
if (!valid) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment