Skip to content

Commit

Permalink
fix: not string method access error (#869)
Browse files Browse the repository at this point in the history
* fix: not string method access error

* refactoring
  • Loading branch information
kazupon committed May 10, 2020
1 parent 078d774 commit e0e69e3
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 23 deletions.
4 changes: 2 additions & 2 deletions src/components/number.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* @flow */

import { warn, isObject, includes, numberFormatKeys } from '../util'
import { warn, isString, isObject, includes, numberFormatKeys } from '../util'

export default {
name: 'i18n-n',
Expand Down Expand Up @@ -34,7 +34,7 @@ export default {
let key: ?string = null
let options: ?NumberFormatOptions = null

if (typeof props.format === 'string') {
if (isString(props.format)) {
key = props.format
} else if (isObject(props.format)) {
if (props.format.key) {
Expand Down
4 changes: 2 additions & 2 deletions src/directive.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* @flow */

import { warn, isPlainObject, looseEqual } from './util'
import { warn, isString, isPlainObject, looseEqual } from './util'

export function bind (el: any, binding: Object, vnode: any): void {
if (!assert(el, vnode)) { return }
Expand Down Expand Up @@ -88,7 +88,7 @@ function parseValue (value: any): Object {
let args: any
let choice: ?number

if (typeof value === 'string') {
if (isString(value)) {
path = value
} else if (isPlainObject(value)) {
path = value.path
Expand Down
43 changes: 24 additions & 19 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
parseArgs,
isPlainObject,
isObject,
isArray,
isBoolean,
isString,
looseClone,
remove,
includes,
Expand Down Expand Up @@ -161,7 +164,7 @@ export default class VueI18n {
paths.pop()
}
})
} else if (typeof message === 'string') {
} 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`
Expand Down Expand Up @@ -283,7 +286,7 @@ export default class VueI18n {
if (!isNull(result)) { return result }
if (this._missing) {
const missingRet = this._missing.apply(null, [locale, key, vm, values])
if (typeof missingRet === 'string') {
if (isString(missingRet)) {
return missingRet
}
} else {
Expand Down Expand Up @@ -342,7 +345,7 @@ export default class VueI18n {
/* istanbul ignore else */
if (isPlainObject(message)) {
ret = message[key]
if (typeof ret !== 'string') {
if (!isString(ret)) {
if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
warn(`Value of key '${key}' is not a string!`)
}
Expand All @@ -353,7 +356,7 @@ export default class VueI18n {
}
} else {
/* istanbul ignore else */
if (typeof pathRet === 'string') {
if (isString(pathRet)) {
ret = pathRet
} else {
if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
Expand Down Expand Up @@ -458,7 +461,7 @@ export default class VueI18n {

// if interpolateMode is **not** 'string' ('row'),
// return the compiled data (e.g. ['foo', VNode, 'bar']) with formatter
return interpolateMode === 'string' && typeof ret !== 'string' ? ret.join('') : ret
return interpolateMode === 'string' && !isString(ret) ? ret.join('') : ret
}

_appendItemToChain (chain: Array<Locale>, item: Locale, blocks: any): any {
Expand Down Expand Up @@ -490,9 +493,11 @@ export default class VueI18n {

_appendBlockToChain (chain: Array<Locale>, block: Array<Locale>, blocks: any): any {
let follow = true
for (let i = 0; (i < block.length) && (typeof follow === 'boolean'); i++) {
for (let i = 0; (i < block.length) && (isBoolean(follow)); i++) {
const locale = block[i]
follow = this._appendLocaleToChain(chain, locale, blocks)
if (isString(locale)) {
follow = this._appendLocaleToChain(chain, locale, blocks)
}
}
return follow
}
Expand All @@ -515,7 +520,7 @@ export default class VueI18n {
let block = [start]

// while any intervening block found
while (Array.isArray(block)) {
while (isArray(block)) {
block = this._appendBlockToChain(
chain,
block,
Expand All @@ -525,9 +530,9 @@ export default class VueI18n {

// last block defined by default
let defaults
if (Array.isArray(fallbackLocale)) {
if (isArray(fallbackLocale)) {
defaults = fallbackLocale
} else if (fallbackLocale instanceof Object) {
} else if (isObject(fallbackLocale)) {
if (fallbackLocale['default']) {
defaults = fallbackLocale['default']
} else {
Expand All @@ -538,7 +543,7 @@ export default class VueI18n {
}

// convert defaults to array
if (typeof defaults === 'string') {
if (isString(defaults)) {
block = [defaults]
} else {
block = defaults
Expand Down Expand Up @@ -628,7 +633,7 @@ export default class VueI18n {
/* istanbul ignore if */
if (!key) { return '' }
if (typeof locale !== 'string') {
if (!isString(locale)) {
locale = this.locale
}
Expand Down Expand Up @@ -657,7 +662,7 @@ export default class VueI18n {
fetchChoice (message: string, choice: number): ?string {
/* istanbul ignore if */
if (!message && typeof message !== 'string') { return null }
if (!message && !isString(message)) { return null }
const choices: Array<string> = message.split('|')
choice = this.getChoiceIndex(choice, choices.length)
Expand Down Expand Up @@ -819,7 +824,7 @@ export default class VueI18n {
let key: ?string = null

if (args.length === 1) {
if (typeof args[0] === 'string') {
if (isString(args[0])) {
key = args[0]
} else if (isObject(args[0])) {
if (args[0].locale) {
Expand All @@ -830,10 +835,10 @@ export default class VueI18n {
}
}
} else if (args.length === 2) {
if (typeof args[0] === 'string') {
if (isString(args[0])) {
key = args[0]
}
if (typeof args[1] === 'string') {
if (isString(args[1])) {
locale = args[1]
}
}
Expand Down Expand Up @@ -948,7 +953,7 @@ export default class VueI18n {
let options: ?NumberFormatOptions = null

if (args.length === 1) {
if (typeof args[0] === 'string') {
if (isString(args[0])) {
key = args[0]
} else if (isObject(args[0])) {
if (args[0].locale) {
Expand All @@ -967,10 +972,10 @@ export default class VueI18n {
}, null)
}
} else if (args.length === 2) {
if (typeof args[0] === 'string') {
if (isString(args[0])) {
key = args[0]
}
if (typeof args[1] === 'string') {
if (isString(args[1])) {
locale = args[1]
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,20 @@ export function error (msg: string, err: ?Error): void {
}
}

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 {
Expand Down
18 changes: 18 additions & 0 deletions test/unit/fallback.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,21 @@ describe('kazupon#138 mmokross#2 - Fallback Locale as array for cascading fallba
})
})
})

describe('issue #868', () => {
it('should be fallbacked', () => {
const i18n = new VueI18n({
locale: 'de-CH',
fallbackLocale: {
'de-CH': ['fr', 'it'],
'zh-Hant': ['zh-Hans'],
'es-CL': ['es-AR'],
'es': ['en-GB'],
'pt': ['es-AR'],
default: ['en-US', 1, {}, null, false, undefined, 'en']
},
messages
})
assert.deepEqual(i18n.t('message.hello'), 'the world')
})
})

0 comments on commit e0e69e3

Please sign in to comment.