vue#ComponentOptions TypeScript Examples

The following examples show how to use vue#ComponentOptions. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.ts    From vue-storefront-1 with MIT License 6 votes vote down vote up
mountMixin = <V extends Vue>(
  component: ComponentOptions<V>,
  mountOptions: ThisTypedShallowMountOptions<V> = {},
  template = '<div />'
): Wrapper<V> => {
  const localVue = createLocalVue();

  localVue.use(Vuex);

  return shallowMount({
    template,
    mixins: [component]
  }, {
    localVue,
    ...mountOptions
  })
}
Example #2
Source File: index.ts    From vue-storefront-1 with MIT License 6 votes vote down vote up
mountMixinWithStore = <V extends Vue>(
  component: ComponentOptions<V>,
  storeOptions: object = {},
  mountOptions: ThisTypedShallowMountOptions<V> = {},
  template = '<div />'
): Wrapper<V> => {
  const localVue = createLocalVue();

  localVue.use(Vuex);

  const store = new Vuex.Store({
    ...storeOptions
  });

  return shallowMount({
    template,
    mixins: [component]
  }, {
    store,
    localVue,
    ...mountOptions
  })
}
Example #3
Source File: wc.test.ts    From vue-i18n-next with MIT License 5 votes vote down vote up
test('custom blocks', async () => {
  const i18n = createI18n<false>({
    legacy: false,
    locale: 'en',
    messages: {
      en: {
        hello: 'hello web components!'
      },
      ja: {
        hello: 'こんにちは Web コンポーネント!'
      }
    }
  })

  const Provider = defineCustomElement({
    setup() {
      provide(I18nInjectionKey, i18n)
      return () => h('my-child-block')
    }
  })
  customElements.define('my-provider-block', Provider)
  const Child = defineCustomElement({
    setup() {
      const instance = getCurrentInstance()
      if (instance == null) {
        throw new Error()
      }
      const options = instance.type as ComponentOptions
      options.__i18n = [
        {
          locale: 'en',
          resource: { foo: 'foo!' }
        },
        {
          locale: 'ja',
          resource: { foo: 'ふー!' }
        }
      ]
      const { t } = useI18n({
        inheritLocale: true,
        useScope: 'local'
      })
      return () => h('div', t('foo'))
    }
  })
  customElements.define('my-child-block', Child)

  container.innerHTML = `<my-provider-block></my-provider-block>`
  await nextTick()
  const provider = container.childNodes[0] as VueElement
  const child = provider.shadowRoot!.childNodes[0] as VueElement
  expect(child.shadowRoot!.innerHTML).toBe(`<div>foo!</div>`)

  i18n.global.locale.value = 'ja'
  await nextTick()
  expect(child.shadowRoot!.innerHTML).toBe(`<div>ふー!</div>`)
})
Example #4
Source File: bridge.ts    From vue-i18n-next with MIT License 4 votes vote down vote up
/**
 * Port from [email protected]
 * This mixin is used when we use vue-i18n-bridge
 */
export function defineMixin(
  i18n: I18n,
  VueI18n: any // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
): ComponentOptions {
  return {
    beforeCreate(): void {
      const options: any = this.$options // eslint-disable-line @typescript-eslint/no-explicit-any
      if (options.__VUE18N__INSTANCE__) {
        return
      }
      options.i18n = options.i18n || (options.__i18nBridge ? {} : null)

      this._i18nBridgeRoot = i18n
      if (i18n.mode === 'composition') {
        this._i18n = i18n
        return
      }

      if (options.i18n) {
        if (options.i18n instanceof VueI18n) {
          // init locale messages via custom blocks
          if (options.__i18nBridge) {
            try {
              const localeMessages =
                options.i18n && options.i18n.messages
                  ? options.i18n.messages
                  : {}
              ;(options.__i18nBridge as string[]).forEach(resource =>
                deepCopy(JSON.parse(resource), localeMessages)
              )
              Object.keys(localeMessages).forEach((locale: Locale) => {
                options.i18n.mergeLocaleMessage(locale, localeMessages[locale])
              })
            } catch (e) {
              if (__DEV__) {
                console.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) {
            try {
              const localeMessages =
                options.i18n && options.i18n.messages
                  ? options.i18n.messages
                  : {}
              ;(options.__i18nBridge as string[]).forEach(resource =>
                deepCopy(JSON.parse(resource), localeMessages)
              )
              options.i18n.messages = localeMessages
            } catch (e) {
              if (__DEV__) {
                warn(`Cannot parse locale messages via custom blocks.`, e)
              }
            }
          }

          const { sharedMessages } = options.i18n
          if (sharedMessages && isPlainObject(sharedMessages)) {
            deepCopy(sharedMessages, options.i18n.messages)
          }

          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 (__DEV__) {
            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 // eslint-disable-line @typescript-eslint/no-explicit-any
      if (options.__VUE18N__INSTANCE__) {
        return
      }

      if (i18n.mode === 'composition') {
        return
      }

      options.i18n = options.i18n || (options.__i18nBridge ? {} : 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 (__DEV__) {
            warn(`Cannot be interpreted 'i18n' option.`)
          }
        }
      } else if (
        this.$root &&
        this.$root.$i18n &&
        this.$root.$i18n instanceof VueI18n
      ) {
        this._i18n.subscribeDataChanging(this)
        this._subscribing = true
      } else if (
        options.parent &&
        options.parent.$i18n &&
        options.parent.$i18n instanceof VueI18n
      ) {
        this._i18n.subscribeDataChanging(this)
        this._subscribing = true
      }
    },

    beforeDestroy(): void {
      const options: any = this.$options // eslint-disable-line @typescript-eslint/no-explicit-any
      if (options.__VUE18N__INSTANCE__) {
        return
      }

      if (this._i18nBridgeRoot) {
        delete this._i18nBridgeRoot
        return
      }

      if (i18n.mode === 'composition') {
        delete this._i18n
        return
      }

      if (!this._i18n) {
        return
      }

      const self = this as any // eslint-disable-line @typescript-eslint/no-explicit-any
      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
        }
      })
    }
  }
}
Example #5
Source File: next.ts    From vue-i18n-next with MIT License 4 votes vote down vote up
/**
 * Supports compatibility for legacy vue-i18n APIs
 * This mixin is used when we use [email protected] or later
 */
export function defineMixin(
  vuei18n: VueI18n,
  composer: Composer,
  i18n: I18nInternal
): ComponentOptions {
  return {
    beforeCreate(): void {
      const instance = getCurrentInstance()
      /* istanbul ignore if */
      if (!instance) {
        throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR)
      }

      const options = this.$options
      if (options.i18n) {
        const optionsI18n = options.i18n as VueI18nOptions &
          ComposerInternalOptions

        if (options.__i18n) {
          optionsI18n.__i18n = options.__i18n
        }
        optionsI18n.__root = composer
        if (this === this.$root) {
          this.$i18n = mergeToRoot(vuei18n, optionsI18n)
        } else {
          optionsI18n.__injectWithOption = true
          this.$i18n = createVueI18n(optionsI18n)
        }
      } else if (options.__i18n) {
        if (this === this.$root) {
          this.$i18n = mergeToRoot(vuei18n, options)
        } else {
          this.$i18n = createVueI18n({
            __i18n: (options as ComposerInternalOptions).__i18n,
            __injectWithOption: true,
            __root: composer
          } as VueI18nOptions)
        }
      } else {
        // set global
        this.$i18n = vuei18n
      }

      if (options.__i18nGlobal) {
        adjustI18nResources(composer, options as ComposerOptions, options)
      }

      ;(vuei18n as unknown as VueI18nInternal).__onComponentInstanceCreated(
        this.$i18n
      )
      i18n.__setInstance(instance, this.$i18n as VueI18n)

      // defines vue-i18n legacy APIs
      this.$t = (...args: unknown[]): TranslateResult => this.$i18n.t(...args)
      this.$rt = (...args: unknown[]): TranslateResult => this.$i18n.rt(...args)
      this.$tc = (...args: unknown[]): TranslateResult => this.$i18n.tc(...args)
      this.$te = (key: Path, locale?: Locale): boolean =>
        this.$i18n.te(key, locale)
      this.$d = (...args: unknown[]): DateTimeFormatResult =>
        this.$i18n.d(...args)
      this.$n = (...args: unknown[]): NumberFormatResult =>
        this.$i18n.n(...args)
      this.$tm = (key: Path): LocaleMessageValue<VueMessageType> | {} =>
        this.$i18n.tm(key)
    },

    mounted(): void {
      /* istanbul ignore if */
      if (
        (__DEV__ || __FEATURE_PROD_VUE_DEVTOOLS__) &&
        !__NODE_JS__ &&
        this.$el &&
        this.$i18n
      ) {
        this.$el.__VUE_I18N__ = this.$i18n.__composer
        const emitter: VueDevToolsEmitter = (this.__v_emitter =
          createEmitter<VueDevToolsEmitterEvents>())
        const _vueI18n = this.$i18n as unknown as VueI18nInternal
        _vueI18n.__enableEmitter && _vueI18n.__enableEmitter(emitter)
        emitter.on('*', addTimelineEvent)
      }
    },

    unmounted(): void {
      const instance = getCurrentInstance()
      /* istanbul ignore if */
      if (!instance) {
        throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR)
      }

      /* istanbul ignore if */
      if (
        (__DEV__ || __FEATURE_PROD_VUE_DEVTOOLS__) &&
        !__NODE_JS__ &&
        this.$el &&
        this.$el.__VUE_I18N__
      ) {
        if (this.__v_emitter) {
          this.__v_emitter.off('*', addTimelineEvent)
          delete this.__v_emitter
        }
        if (this.$i18n) {
          const _vueI18n = this.$i18n as unknown as VueI18nInternal
          _vueI18n.__disableEmitter && _vueI18n.__disableEmitter()
          delete this.$el.__VUE_I18N__
        }
      }

      delete this.$t
      delete this.$rt
      delete this.$tc
      delete this.$te
      delete this.$d
      delete this.$n
      delete this.$tm

      i18n.__deleteInstance(instance)
      delete this.$i18n
    }
  }
}
Example #6
Source File: i18n.test.ts    From vue-i18n-next with MIT License 4 votes vote down vote up
describe('useI18n', () => {
  let org: any // eslint-disable-line @typescript-eslint/no-explicit-any
  let spy: any // eslint-disable-line @typescript-eslint/no-explicit-any
  beforeEach(() => {
    org = console.warn
    spy = jest.fn()
    console.warn = spy
  })
  afterEach(() => {
    console.warn = org
  })

  test('basic', async () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'ja',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    let composer: unknown
    const App = defineComponent({
      setup() {
        composer = useI18n({
          inheritLocale: false,
          locale: 'en',
          messages: {
            en: {
              hello: 'hello!'
            }
          }
        })
        return {}
      },
      template: `<p>foo</p>`
    })
    await mount(App, i18n)

    expect(i18n.global).not.toEqual(composer)
    expect((composer as Composer).locale.value).toEqual('en')
  })

  test('global scope', async () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'ja',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    let composer: unknown
    const App = defineComponent({
      setup() {
        composer = useI18n({ useScope: 'global' })
        return {}
      },
      template: `<p>foo</p>`
    })
    await mount(App, i18n)

    expect(i18n.global).toEqual(composer)
    expect((composer as Composer).locale.value).toEqual('ja')
  })

  test('parent scope', async () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'ja',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    let leaf: unknown
    let parent: unknown
    const App = defineComponent({
      components: {
        Leaf: {
          template: '<p>local</p>',
          setup() {
            leaf = useI18n({ useScope: 'parent' })
            return {}
          }
        }
      },
      setup() {
        parent = useI18n({
          inheritLocale: false,
          locale: 'en',
          messages: {
            en: {
              hello: 'hello!'
            }
          }
        })
        return {}
      },
      template: `<div>parent</div><Leaf />`
    })
    await mount(App, i18n)

    expect(i18n.global).not.toEqual(leaf)
    expect(i18n.global).not.toEqual(parent)
    expect(parent).toEqual(leaf)
    expect((leaf as Composer).locale.value).toEqual('en')
  })

  test('not found parent composer with parent scope', async () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'ja',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    let composer: unknown
    const App = defineComponent({
      components: {
        Leaf: {
          template: '<p>local</p>',
          setup() {
            composer = useI18n({ useScope: 'parent' })
            return {}
          }
        }
      },
      setup() {
        return {}
      },
      template: `<div>parent</div><Leaf />`
    })
    await mount(App, i18n)

    expect(i18n.global).toEqual(composer)
    expect((composer as Composer).locale.value).toEqual('ja')
  })

  test('empty options', async () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'ja',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    let composer: unknown
    const App = defineComponent({
      setup() {
        composer = useI18n()
        return {}
      },
      template: `<p>foo</p>`
    })
    await mount(App, i18n)

    expect(i18n.global).toEqual(composer)
    expect((composer as Composer).locale.value).toEqual('ja')
  })

  test('empty options, when have i18n custom blocks', async () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'ja',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    let composer: unknown
    const App = defineComponent({
      setup() {
        const instance = getCurrentInstance()
        if (instance == null) {
          throw new Error()
        }
        const options = instance.type as ComponentOptions
        options.__i18n = [
          {
            locale: '',
            resource: { en: { hello: 'Hello,world!' } }
          },
          {
            locale: '',
            resource: { ja: { hello: 'こんにちは、世界!' } }
          }
        ] as any // eslint-disable-line @typescript-eslint/no-explicit-any
        composer = useI18n()
        return { t: (composer as Composer).t }
      },
      template: `<p>{{ t('hello', ['foo'], { locale: 'ja' }) }}</p>`
    })
    const { html } = await mount(App, i18n)

    expect(html()).toEqual('<p>こんにちは、世界!</p>')
    expect(i18n.global).not.toEqual(composer)
    expect((composer as Composer).locale.value).toEqual('ja')
  })

  test(errorMessages[I18nErrorCodes.MUST_BE_CALL_SETUP_TOP], async () => {
    let error = ''
    try {
      useI18n({})
    } catch (e) {
      error = e.message
    }
    expect(error).toEqual(errorMessages[I18nErrorCodes.MUST_BE_CALL_SETUP_TOP])
  })

  test(errorMessages[I18nErrorCodes.NOT_INSLALLED], async () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'ja',
      messages: {
        en: {
          hello: 'hello!'
        }
      }
    })

    let error = ''
    const App = defineComponent({
      setup() {
        try {
          useI18n({})
        } catch (e) {
          error = e.message
        }
        return {}
      }
    })
    await mount(App, i18n, { installI18n: false })
    expect(error).toEqual(errorMessages[I18nErrorCodes.NOT_INSLALLED])
  })

  describe('On legacy', () => {
    describe('default', () => {
      test(
        errorMessages[I18nErrorCodes.NOT_AVAILABLE_IN_LEGACY_MODE],
        async () => {
          const i18n = createI18n({
            legacy: true,
            locale: 'ja',
            messages: {
              en: {
                hello: 'hello!'
              }
            }
          })

          let error = ''
          const App = defineComponent({
            setup() {
              try {
                useI18n({
                  locale: 'en',
                  messages: {
                    en: {
                      hello: 'hello!'
                    }
                  }
                })
              } catch (e) {
                error = e.message
              }
              return {}
            },
            template: `<p>foo</p>`
          })
          await mount(App, i18n)
          expect(error).toEqual(
            errorMessages[I18nErrorCodes.NOT_AVAILABLE_IN_LEGACY_MODE]
          )
        }
      )
    })

    describe('enable', () => {
      describe('t', () => {
        test('translation & locale changing', async () => {
          const i18n = createI18n({
            allowComposition: true,
            locale: 'ja',
            messages: {
              en: {
                hello: 'hello!'
              },
              ja: {
                hello: 'こんにちは!'
              }
            }
          })

          const App = defineComponent({
            setup() {
              const { locale, t } = useI18n()
              return { locale, t }
            },
            template: `<p>{{ t('hello') }}</p>`
          })
          const { html } = await mount(App, i18n)
          expect(html()).toEqual('<p>こんにちは!</p>')

          i18n.global.locale = 'en'
          await nextTick()
          expect(html()).toEqual('<p>hello!</p>')
        })

        test('local scope', async () => {
          const i18n = createI18n({
            allowComposition: true,
            locale: 'en',
            messages: {
              en: {
                hello: 'hello!'
              },
              ja: {}
            }
          })

          const App = defineComponent({
            setup() {
              const { locale, t } = useI18n({
                useScope: 'local',
                messages: {
                  en: {
                    world: 'world!'
                  },
                  ja: {
                    world: '世界!'
                  }
                }
              })
              return { locale, t }
            },
            i18n: {},
            template: `<p>{{ locale }}:{{ t('world') }}</p>`
          })
          const { html } = await mount(App, i18n)
          expect(html()).toEqual('<p>en:world!</p>')

          i18n.global.locale = 'ja'
          await nextTick()
          expect(html()).toEqual('<p>ja:世界!</p>')
        })

        test('use i18n option', async () => {
          const i18n = createI18n({
            allowComposition: true,
            locale: 'en',
            messages: {
              en: {
                hello: 'hello!'
              },
              ja: {}
            }
          })

          const App = defineComponent({
            setup() {
              const { locale, t } = useI18n({
                useScope: 'local'
              })
              return { locale, t }
            },
            i18n: {
              messages: {
                en: {
                  world: 'world!'
                },
                ja: {
                  world: '世界!'
                }
              }
            },
            template: `<p>{{ locale }}:{{ t('world') }}</p>`
          })
          const { html } = await mount(App, i18n)
          expect(html()).toEqual('<p>en:world!</p>')
        })

        test('use custom block', async () => {
          const i18n = createI18n({
            allowComposition: true,
            locale: 'ja',
            messages: {
              en: {
                hello: 'hello!'
              },
              ja: {}
            }
          })

          const App = defineComponent({
            setup() {
              const instance = getCurrentInstance()
              if (instance == null) {
                throw new Error()
              }
              const options = instance.type as ComponentOptions
              options.__i18n = [
                {
                  locale: 'ja',
                  resource: {
                    hello: 'こんにちは!'
                  }
                }
              ]
              const { locale, t } = useI18n({
                inheritLocale: true,
                useScope: 'local'
              })
              return { locale, t }
            },
            template: `<p>{{ locale }}:{{ t('hello') }}</p>`
          })
          const { html } = await mount(App, i18n)
          expect(html()).toEqual('<p>ja:こんにちは!</p>')
        })

        test('not defined i18n option in local scope', async () => {
          const i18n = createI18n({
            allowComposition: true,
            locale: 'en',
            messages: {
              en: {
                hello: 'hello!'
              }
            }
          })

          let error = ''
          const App = defineComponent({
            setup() {
              try {
                useI18n({ useScope: 'local' })
              } catch (e) {
                error = e.message
              }
              return {}
            }
          })
          await mount(App, i18n)
          expect(error).toEqual(
            errorMessages[
              I18nErrorCodes.MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION
            ]
          )
        })
      })
    })

    describe('d', () => {
      test('datetime formatting', async () => {
        const i18n = createI18n({
          allowComposition: true,
          locale: 'en-US',
          fallbackLocale: ['ja-JP'],
          datetimeFormats: {
            'en-US': {
              short: {
                year: 'numeric',
                month: '2-digit',
                day: '2-digit',
                hour: '2-digit',
                minute: '2-digit',
                timeZone: 'America/New_York'
              }
            },
            'ja-JP': {
              long: {
                year: 'numeric',
                month: '2-digit',
                day: '2-digit',
                hour: '2-digit',
                minute: '2-digit',
                second: '2-digit',
                timeZone: 'Asia/Tokyo'
              },
              short: {
                year: 'numeric',
                month: '2-digit',
                day: '2-digit',
                hour: '2-digit',
                minute: '2-digit',
                timeZone: 'Asia/Tokyo'
              }
            }
          }
        })

        const App = defineComponent({
          setup() {
            const { d } = useI18n()
            const dt = new Date(Date.UTC(2012, 11, 20, 3, 0, 0))
            return { d, dt }
          },
          template: `<p>{{ d(dt, 'long') }}</p>`
        })
        const { html } = await mount(App, i18n)
        expect(html()).toEqual('<p>2012/12/20 12:00:00</p>')
      })
    })

    describe('n', () => {
      test('number formatting', async () => {
        const i18n = createI18n({
          allowComposition: true,
          locale: 'en-US',
          fallbackLocale: ['ja-JP'],
          numberFormats: {
            'en-US': {
              currency: {
                style: 'currency',
                currency: 'USD',
                currencyDisplay: 'symbol'
              },
              decimal: {
                style: 'decimal',
                useGrouping: false
              }
            },
            'ja-JP': {
              currency: {
                style: 'currency',
                currency: 'JPY' /*, currencyDisplay: 'symbol'*/
              },
              numeric: {
                style: 'decimal',
                useGrouping: false
              },
              percent: {
                style: 'percent',
                useGrouping: false
              }
            }
          }
        })

        const App = defineComponent({
          setup() {
            const { n } = useI18n()
            const value = 0.99
            return { n, value }
          },
          template: `<p>{{ n(value, { key: 'percent' }) }}</p>`
        })
        const { html } = await mount(App, i18n)
        expect(html()).toEqual('<p>99%</p>')
      })
    })
  })

  test(errorMessages[I18nErrorCodes.NOT_INSLALLED_WITH_PROVIDE], async () => {
    const Provider = defineCustomElement({
      setup() {
        createI18n<false>({ legacy: false })
        return () => h('my-consumer')
      }
    })
    customElements.define('my-provider', Provider)

    let error = ''
    const Consumer = defineCustomElement({
      setup() {
        try {
          useI18n()
        } catch (e) {
          error = e.message
        }
        return () => h('div')
      }
    })
    customElements.define('my-consumer', Consumer)

    container.innerHTML = `<my-provider><my-provider>`
    await nextTick()

    expect(error).toEqual(
      errorMessages[I18nErrorCodes.NOT_INSLALLED_WITH_PROVIDE]
    )
  })
})
Example #7
Source File: i18n.test.ts    From vue-i18n-next with MIT License 4 votes vote down vote up
describe('merge i18n custom blocks to global scope', () => {
  test('composition mode', async () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'ja',
      messages: {
        en: {
          hi: { hello: 'hello!' }
        }
      }
    })

    const App = defineComponent({
      setup() {
        const instance = getCurrentInstance()
        if (instance == null) {
          throw new Error()
        }
        const options = instance.type as ComponentOptions
        options.__i18nGlobal = [
          {
            locale: 'en',
            resource: {
              hi: { hi: 'hi!' },
              foo: 'foo!'
            }
          },
          {
            locale: 'ja',
            resource: { foo: 'ふー!' }
          }
        ]
        useI18n({
          useScope: 'global',
          messages: {
            ja: {
              hello: 'こんにちは!'
            }
          }
        })
        return {}
      },
      template: `<p>foo</p>`
    })
    await mount(App, i18n)

    expect(i18n.global.getLocaleMessage('en')).toEqual({
      hi: {
        hi: 'hi!',
        hello: 'hello!'
      },
      foo: 'foo!'
    })
    expect(i18n.global.getLocaleMessage('ja')).toEqual({
      hello: 'こんにちは!',
      foo: 'ふー!'
    })
  })

  test('legacy mode', async () => {
    const i18n = createI18n({
      legacy: true,
      locale: 'ja',
      messages: {
        en: {
          hi: { hello: 'hello!' }
        },
        ja: {
          hello: 'こんにちは!'
        }
      }
    })

    const App = defineComponent({
      __i18nGlobal: [
        {
          locale: 'en',
          resource: {
            hi: { hi: 'hi!' },
            foo: 'foo!'
          }
        },
        {
          locale: 'ja',
          resource: { foo: 'ふー!' }
        }
      ],
      template: `<p>foo</p>`
    })
    await mount(App, i18n)

    expect(i18n.global.getLocaleMessage('en')).toEqual({
      hi: {
        hi: 'hi!',
        hello: 'hello!'
      },
      foo: 'foo!'
    })
    expect(i18n.global.getLocaleMessage('ja')).toEqual({
      hello: 'こんにちは!',
      foo: 'ふー!'
    })
  })
})
Example #8
Source File: i18n.test.ts    From vue-i18n-next with MIT License 4 votes vote down vote up
describe('custom pluralization', () => {
  test('legacy', async () => {
    const i18n = createI18n({
      locale: 'ru',
      pluralizationRules: _pluralRules,
      messages: {
        ru: {
          car: '0 машин | {n} машина | {n} машины | {n} машин'
        }
      }
    })

    const App = defineComponent({
      template: `
        <p>{{ $tc('car', 1) }}</p>
        <p>{{ $tc('car', 2) }}</p>
        <p>{{ $tc('car', 4) }}</p>
        <p>{{ $tc('car', 12) }}</p>
        <p>{{ $tc('car', 21) }}</p>
      `
    })
    const { find } = await mount(App, i18n)
    await nextTick()
    expect(find('p:nth-child(1)')!.innerHTML).toEqual('1 машина')
    expect(find('p:nth-child(2)')!.innerHTML).toEqual('2 машины')
    expect(find('p:nth-child(3)')!.innerHTML).toEqual('4 машины')
    expect(find('p:nth-child(4)')!.innerHTML).toEqual('12 машин')
    expect(find('p:nth-child(5)')!.innerHTML).toEqual('21 машина')
  })

  test('legacy + custom block', async () => {
    const i18n = createI18n({
      locale: 'ru',
      pluralizationRules: _pluralRules
    })

    const App = defineComponent({
      __i18n: [
        {
          locale: 'ru',
          resource: {
            car: '0 машин | {n} машина | {n} машины | {n} машин'
          }
        }
      ],
      template: `
        <p>{{ $tc('car', 1) }}</p>
        <p>{{ $tc('car', 2) }}</p>
        <p>{{ $tc('car', 4) }}</p>
        <p>{{ $tc('car', 12) }}</p>
        <p>{{ $tc('car', 21) }}</p>
      `
    })
    const { find } = await mount(App, i18n)
    await nextTick()
    expect(find('p:nth-child(1)')!.innerHTML).toEqual('1 машина')
    expect(find('p:nth-child(2)')!.innerHTML).toEqual('2 машины')
    expect(find('p:nth-child(3)')!.innerHTML).toEqual('4 машины')
    expect(find('p:nth-child(4)')!.innerHTML).toEqual('12 машин')
    expect(find('p:nth-child(5)')!.innerHTML).toEqual('21 машина')
  })

  test('composition', async () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'ru',
      pluralRules: _pluralRules,
      messages: {
        ru: {
          car: '0 машин | {n} машина | {n} машины | {n} машин'
        }
      }
    })

    const App = defineComponent({
      setup() {
        const { t } = useI18n()
        return { t }
      },
      template: `
        <p>{{ t('car', 1) }}</p>
        <p>{{ t('car', 2) }}</p>
        <p>{{ t('car', 4) }}</p>
        <p>{{ t('car', 12) }}</p>
        <p>{{ t('car', 21) }}</p>
      `
    })
    const { find } = await mount(App, i18n)
    await nextTick()
    expect(find('p:nth-child(1)')!.innerHTML).toEqual('1 машина')
    expect(find('p:nth-child(2)')!.innerHTML).toEqual('2 машины')
    expect(find('p:nth-child(3)')!.innerHTML).toEqual('4 машины')
    expect(find('p:nth-child(4)')!.innerHTML).toEqual('12 машин')
    expect(find('p:nth-child(5)')!.innerHTML).toEqual('21 машина')
  })

  test('composition + custom block', async () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'ru'
    })

    const App = defineComponent({
      setup() {
        const instance = getCurrentInstance()
        if (instance == null) {
          throw new Error()
        }
        const options = instance.type as ComponentOptions
        options.__i18n = [
          {
            locale: 'ru',
            resource: {
              car: '0 машин | {n} машина | {n} машины | {n} машин'
            }
          }
        ]
        const { t } = useI18n({
          inheritLocale: true,
          useScope: 'local',
          pluralRules: _pluralRules
        })
        return { t }
      },
      template: `
        <p>{{ t('car', 1) }}</p>
        <p>{{ t('car', 2) }}</p>
        <p>{{ t('car', 4) }}</p>
        <p>{{ t('car', 12) }}</p>
        <p>{{ t('car', 21) }}</p>
      `
    })
    const { find } = await mount(App, i18n)
    await nextTick()
    expect(find('p:nth-child(1)')!.innerHTML).toEqual('1 машина')
    expect(find('p:nth-child(2)')!.innerHTML).toEqual('2 машины')
    expect(find('p:nth-child(3)')!.innerHTML).toEqual('4 машины')
    expect(find('p:nth-child(4)')!.innerHTML).toEqual('12 машин')
    expect(find('p:nth-child(5)')!.innerHTML).toEqual('21 машина')
  })
})