Skip to content

Commit

Permalink
fix: bring bug fixes from v9.2.0-beta.11 (#720)
Browse files Browse the repository at this point in the history
* fix: Maximum call stack size (#713)

* fix: vue-i18n components scope resolving in Legacy API mode (#715)

Co-authored-by: Fabian Kranewitter <fabiankranewitter@gmail.com>
  • Loading branch information
kazupon and fabiankranewitter committed Oct 4, 2021
1 parent 77de669 commit b258c48
Show file tree
Hide file tree
Showing 11 changed files with 753 additions and 21 deletions.
19 changes: 7 additions & 12 deletions packages/message-compiler/src/tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,45 +438,40 @@ export function createTokenizer(
}

function readText(scnr: Scanner): string {
const fn = (buf: string): string => {
let buf = ''
while (true) {
const ch = scnr.currentChar()
if (
ch === TokenChars.BraceLeft ||
ch === TokenChars.BraceRight ||
ch === TokenChars.LinkedAlias ||
ch === TokenChars.Pipe ||
!ch
) {
return buf
break
} else if (ch === TokenChars.Modulo) {
if (isTextStart(scnr)) {
buf += ch
scnr.next()
return fn(buf)
} else {
return buf
break
}
} else if (ch === TokenChars.Pipe) {
return buf
} else if (ch === SPACE || ch === NEW_LINE) {
if (isTextStart(scnr)) {
buf += ch
scnr.next()
return fn(buf)
} else if (isPluralStart(scnr)) {
return buf
break
} else {
buf += ch
scnr.next()
return fn(buf)
}
} else {
buf += ch
scnr.next()
return fn(buf)
}
}

return fn('')
return buf
}

function readNamedIdentifier(scnr: Scanner): string {
Expand Down

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions packages/message-compiler/test/tokenizer.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { parse } from '../src/tokenizer'
import { TokenizeOptions } from '../src/options'
import { CompileError } from '../src/errors'
import path from 'path'
import { promises as fs } from 'fs'

test('token analysis', () => {
const cases = [
Expand Down Expand Up @@ -98,3 +100,20 @@ test('token analysis', () => {
}
}
})

describe('edge cases', () => {
test('long text', async () => {
const data = await fs.readFile(
path.join(__dirname, './fixtures/20_newsgroups_alt_atheism_51060.txt'),
'utf8'
)
let err = null
try {
parse(data)
} catch (e) {
console.error(e)
err = e
}
expect(err).toEqual(null)
})
})
3 changes: 2 additions & 1 deletion packages/vue-i18n/src/components/DatetimeFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ export const DatetimeFormat = {
setup(props: DatetimeFormatProps, context: SetupContext): RenderFunction {
const i18n =
props.i18n ||
(useI18n({ useScope: 'parent' }) as Composer & ComposerInternal)
(useI18n({ useScope: 'parent', __useComponent: true }) as Composer &
ComposerInternal)

return renderFormatter<
FormattableProps<number | Date, Intl.DateTimeFormatOptions>,
Expand Down
3 changes: 2 additions & 1 deletion packages/vue-i18n/src/components/NumberFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ export const NumberFormat = {
setup(props: NumberFormatProps, context: SetupContext): RenderFunction {
const i18n =
props.i18n ||
(useI18n({ useScope: 'parent' }) as Composer & ComposerInternal)
(useI18n({ useScope: 'parent', __useComponent: true }) as Composer &
ComposerInternal)

return renderFormatter<
FormattableProps<number, Intl.NumberFormatOptions>,
Expand Down
5 changes: 4 additions & 1 deletion packages/vue-i18n/src/components/Translation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ export const Translation = {
const { slots, attrs } = context
const i18n =
props.i18n ||
(useI18n({ useScope: props.scope }) as Composer & ComposerInternal)
(useI18n({
useScope: props.scope as 'global' | 'parent',
__useComponent: true
}) as Composer & ComposerInternal)
const keys = Object.keys(slots).filter(key => key !== '_')

return (): VNodeChild => {
Expand Down
5 changes: 4 additions & 1 deletion packages/vue-i18n/src/composer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export const EnableEmitter = makeSymbol('__enableEmitter')
export const DisableEmitter = makeSymbol('__disableEmitter')
export const SetPluralRulesSymbol = makeSymbol('__setPluralRules')
export const DevToolsMetaSymbol = makeSymbol('__intlifyMeta')
export const InejctWithOption = makeSymbol('__injectWithOption')

/** @VueI18nComposition */
export type VueMessageType = string | VNode
Expand Down Expand Up @@ -326,6 +327,7 @@ export interface ComposerInternalOptions<
__i18n?: CustomBlocks<Message>
__i18nGlobal?: CustomBlocks<Message>
__root?: Composer<Messages, DateTimeFormats, NumberFormats, Message>
__injectWithOption?: boolean
}

/**
Expand Down Expand Up @@ -1862,7 +1864,8 @@ export function createComposer<
[TransrateVNodeSymbol]: transrateVNode,
[NumberPartsSymbol]: numberParts,
[DatetimePartsSymbol]: datetimeParts,
[SetPluralRulesSymbol]: setPluralRules
[SetPluralRulesSymbol]: setPluralRules,
[InejctWithOption]: (options as any).__injectWithOption // eslint-disable-line @typescript-eslint/no-explicit-any
}

// for vue-devtools timeline event
Expand Down
13 changes: 10 additions & 3 deletions packages/vue-i18n/src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
getLocaleMessages,
createComposer,
EnableEmitter,
DisableEmitter
DisableEmitter,
InejctWithOption
} from './composer'
import { createVueI18n } from './legacy'
import { I18nWarnCodes, getWarnMessage } from './warnings'
Expand Down Expand Up @@ -598,7 +599,8 @@ export function useI18n<
}

if (scope === 'parent') {
let composer = getComposer(i18n, instance)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let composer = getComposer(i18n, instance, (options as any).__useComponent)
if (composer == null) {
if (__DEV__) {
warn(getWarnMessage(I18nWarnCodes.NOT_FOUND_PARENT_SCOPE))
Expand Down Expand Up @@ -666,7 +668,8 @@ function getComposer<
Legacy extends boolean
>(
i18n: I18n<Messages, DateTimeFormats, NumberFormats, Legacy>,
target: ComponentInternalInstance
target: ComponentInternalInstance,
useComponent = false
): Composer<Messages, DateTimeFormats, NumberFormats> | null {
let composer: Composer<Messages, DateTimeFormats, NumberFormats> | null = null
const root = target.root
Expand Down Expand Up @@ -696,6 +699,10 @@ function getComposer<
VueI18nInternal<Messages, DateTimeFormats, NumberFormats>)
.__composer as Composer<Messages, DateTimeFormats, NumberFormats>
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (useComponent && !(composer as any)[InejctWithOption]) {
composer = null
}
}
if (composer != null) {
break
Expand Down
5 changes: 3 additions & 2 deletions packages/vue-i18n/src/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@ function convertComposerOptions<
return messages
}, (messages || {}) as LocaleMessages<VueMessageType>) as typeof options.messages
}
const { __i18n, __root } = options
const { __i18n, __root, __injectWithOption } = options

const datetimeFormats = options.datetimeFormats
const numberFormats = options.numberFormats
Expand All @@ -1138,7 +1138,8 @@ function convertComposerOptions<
escapeParameter,
inheritLocale,
__i18n,
__root
__root,
__injectWithOption
}
}

Expand Down
2 changes: 2 additions & 0 deletions packages/vue-i18n/src/mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export function defineMixin<Messages, DateTimeFormats, NumberFormats>(
if (this === this.$root) {
this.$i18n = mergeToRoot(vuei18n, optionsI18n)
} else {
optionsI18n.__injectWithOption = true
this.$i18n = createVueI18n(optionsI18n)
}
} else if (options.__i18n) {
Expand All @@ -60,6 +61,7 @@ export function defineMixin<Messages, DateTimeFormats, NumberFormats>(
} else {
this.$i18n = createVueI18n({
__i18n: (options as ComposerInternalOptions<Messages>).__i18n,
__injectWithOption: true,
__root: composer
} as VueI18nOptions)
}
Expand Down
77 changes: 77 additions & 0 deletions packages/vue-i18n/test/i18n.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -883,3 +883,80 @@ test('Intlify devtools hooking', () => {
expect(fnI18nInit).toHaveBeenCalled()
expect(fnTranslate).toHaveBeenCalled()
})

test('issue #708', async () => {
const messages = {
en: {
message: {
language: 'English',
quantity: 'Quantity',
list: 'hello, {0}!',
named: 'hello, {name}!',
linked: '@:message.named How are you?',
plural: 'no bananas | {n} banana | {n} bananas'
}
},
ja: {
message: {
language: '日本語',
list: 'こんにちは、{0}!',
named: 'こんにちは、{name}!',
linked: '@:message.named ごきげんいかが?'
}
}
}

const i18n = createI18n({
legacy: true,
locale: 'en',
messages
})

const C2 = defineComponent({
template: `<div>C2 slot: <slot></slot></div>`
})

const C1 = defineComponent({
components: {
C2
},
template: `<div>
C1:
<div>{{ $t("hello", { world: $t("world") }) }}</div>
<i18n-t keypath="hello" tag="div">
<template #world>
<strong>{{ $t("world") }}</strong>
</template>
</i18n-t>
<br />
<C2>
<div>{{ $t("hello", { world: $t("world") }) }}</div>
<i18n-t keypath="hello" tag="div">
<template #world>
<strong>{{ $t("world") }}</strong>
</template>
</i18n-t>
</C2>
</div>`,
i18n: {
messages: {
en: {
hello: 'Hello {world}',
world: 'world!'
}
}
}
})

const App = defineComponent({
components: {
C1
},
template: `<C1 />`
})
const wrapper = await mount(App, i18n)

expect(wrapper.html()).toEqual(
`<div> C1: <div>Hello world!</div><div>Hello <strong>world!</strong></div><br><div>C2 slot: <div>Hello world!</div><div>Hello <strong>world!</strong></div></div></div>`
)
})

0 comments on commit b258c48

Please sign in to comment.