mixin.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* @flow */
  2. import VueI18n from './index'
  3. import { isPlainObject, warn, error, merge } from './util'
  4. /**
  5. * Mixin
  6. *
  7. * If `bridge` mode, empty mixin is returned,
  8. * else regulary mixin implementation is returned.
  9. */
  10. export default function defineMixin (bridge: boolean = false) {
  11. function mounted (): void {
  12. if (this !== this.$root && this.$options.__INTLIFY_META__ && this.$el) {
  13. this.$el.setAttribute('data-intlify', this.$options.__INTLIFY_META__)
  14. }
  15. }
  16. return bridge
  17. ? { mounted } // delegate `vue-i18n-bridge` mixin implementation
  18. : { // regulary
  19. beforeCreate (): void {
  20. const options: any = this.$options
  21. options.i18n = options.i18n || ((options.__i18nBridge || options.__i18n) ? {} : null)
  22. if (options.i18n) {
  23. if (options.i18n instanceof VueI18n) {
  24. // init locale messages via custom blocks
  25. if ((options.__i18nBridge || options.__i18n)) {
  26. try {
  27. let localeMessages = options.i18n && options.i18n.messages ? options.i18n.messages : {}
  28. const __i18n = options.__i18nBridge || options.__i18n
  29. __i18n.forEach(resource => {
  30. localeMessages = merge(localeMessages, JSON.parse(resource))
  31. })
  32. Object.keys(localeMessages).forEach((locale: Locale) => {
  33. options.i18n.mergeLocaleMessage(locale, localeMessages[locale])
  34. })
  35. } catch (e) {
  36. if (process.env.NODE_ENV !== 'production') {
  37. error(`Cannot parse locale messages via custom blocks.`, e)
  38. }
  39. }
  40. }
  41. this._i18n = options.i18n
  42. this._i18nWatcher = this._i18n.watchI18nData()
  43. } else if (isPlainObject(options.i18n)) {
  44. const rootI18n = this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n
  45. ? this.$root.$i18n
  46. : null
  47. // component local i18n
  48. if (rootI18n) {
  49. options.i18n.root = this.$root
  50. options.i18n.formatter = rootI18n.formatter
  51. options.i18n.fallbackLocale = rootI18n.fallbackLocale
  52. options.i18n.formatFallbackMessages = rootI18n.formatFallbackMessages
  53. options.i18n.silentTranslationWarn = rootI18n.silentTranslationWarn
  54. options.i18n.silentFallbackWarn = rootI18n.silentFallbackWarn
  55. options.i18n.pluralizationRules = rootI18n.pluralizationRules
  56. options.i18n.preserveDirectiveContent = rootI18n.preserveDirectiveContent
  57. }
  58. // init locale messages via custom blocks
  59. if ((options.__i18nBridge || options.__i18n)) {
  60. try {
  61. let localeMessages = options.i18n && options.i18n.messages ? options.i18n.messages : {}
  62. const __i18n = options.__i18nBridge || options.__i18n
  63. __i18n.forEach(resource => {
  64. localeMessages = merge(localeMessages, JSON.parse(resource))
  65. })
  66. options.i18n.messages = localeMessages
  67. } catch (e) {
  68. if (process.env.NODE_ENV !== 'production') {
  69. warn(`Cannot parse locale messages via custom blocks.`, e)
  70. }
  71. }
  72. }
  73. const { sharedMessages } = options.i18n
  74. if (sharedMessages && isPlainObject(sharedMessages)) {
  75. options.i18n.messages = merge(options.i18n.messages, sharedMessages)
  76. }
  77. this._i18n = new VueI18n(options.i18n)
  78. this._i18nWatcher = this._i18n.watchI18nData()
  79. if (options.i18n.sync === undefined || !!options.i18n.sync) {
  80. this._localeWatcher = this.$i18n.watchLocale()
  81. }
  82. if (rootI18n) {
  83. rootI18n.onComponentInstanceCreated(this._i18n)
  84. }
  85. } else {
  86. if (process.env.NODE_ENV !== 'production') {
  87. warn(`Cannot be interpreted 'i18n' option.`)
  88. }
  89. }
  90. } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
  91. // root i18n
  92. this._i18n = this.$root.$i18n
  93. } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
  94. // parent i18n
  95. this._i18n = options.parent.$i18n
  96. }
  97. },
  98. beforeMount (): void {
  99. const options: any = this.$options
  100. options.i18n = options.i18n || ((options.__i18nBridge || options.__i18n) ? {} : null)
  101. if (options.i18n) {
  102. if (options.i18n instanceof VueI18n) {
  103. // init locale messages via custom blocks
  104. this._i18n.subscribeDataChanging(this)
  105. this._subscribing = true
  106. } else if (isPlainObject(options.i18n)) {
  107. this._i18n.subscribeDataChanging(this)
  108. this._subscribing = true
  109. } else {
  110. if (process.env.NODE_ENV !== 'production') {
  111. warn(`Cannot be interpreted 'i18n' option.`)
  112. }
  113. }
  114. } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
  115. this._i18n.subscribeDataChanging(this)
  116. this._subscribing = true
  117. } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
  118. this._i18n.subscribeDataChanging(this)
  119. this._subscribing = true
  120. }
  121. },
  122. mounted,
  123. beforeDestroy (): void {
  124. if (!this._i18n) { return }
  125. const self = this
  126. this.$nextTick(() => {
  127. if (self._subscribing) {
  128. self._i18n.unsubscribeDataChanging(self)
  129. delete self._subscribing
  130. }
  131. if (self._i18nWatcher) {
  132. self._i18nWatcher()
  133. self._i18n.destroyVM()
  134. delete self._i18nWatcher
  135. }
  136. if (self._localeWatcher) {
  137. self._localeWatcher()
  138. delete self._localeWatcher
  139. }
  140. })
  141. }
  142. }
  143. }