Skip to content

Commit

Permalink
⭐ new: add pluralization (#44) by @mmochetti
Browse files Browse the repository at this point in the history
  • Loading branch information
mochetts authored and kazupon committed Aug 25, 2016
1 parent 3e1bf8d commit b5b84d8
Show file tree
Hide file tree
Showing 3 changed files with 262 additions and 1 deletion.
36 changes: 36 additions & 0 deletions src/extend.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ export default function (Vue) {
return this.$options.locales[lang]
}

function fetchChoice (locale, choice) {
if (!locale && typeof locale !== 'string') return null
const choices = locale.split('|')
choice = choice - 1
if (!choices[choice]) return locale
return choices[choice].trim()
}

/**
* Vue.t
*
Expand All @@ -94,6 +102,19 @@ export default function (Vue) {
|| warnDefault(key)
}

/**
* Vue.tc
*
* @param {String} key
* @param {number|undefined} choice
* @param {Array} ...args
* @return {String}
*/

Vue.tc = (key, choice, ...args) => {
if (!choice) { choice = 1 }
return fetchChoice(Vue.t(key, ...args), choice)
}

/**
* $t
Expand All @@ -115,5 +136,20 @@ export default function (Vue) {
|| warnDefault(key)
}

/**
* $tc
*
* @param {String} key
* @param {number|undefined} choice
* @param {Array} ...args
* @return {String}
*/

Vue.prototype.$tc = function (key, choice, ...args) {
if (typeof choice !== 'number' && typeof choice !== 'undefined') return key
if (!choice) { choice = 1 }
return fetchChoice(this.$t(key, ...args), choice)
}

return Vue
}
18 changes: 17 additions & 1 deletion test/specs/fixture/locales.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ export default {
'hello world': 'Hello World',
'Hello {0}': 'Hello {0}',
'continue-with-new-account': 'continue with new account',
underscore: '{hello_msg} world'
underscore: '{hello_msg} world',
plurals: {
car: 'car | cars',
format: {
named: 'Hello {name}, how are you? | Hi {name}, you look fine',
list: 'Hello {0}, how are you? | Hi {0}, you look fine'
},
fallback: 'this is fallback | this is a plural fallback'
}
},
ja: {
message: {
Expand All @@ -23,6 +31,14 @@ export default {
list: 'こんにちは {0}, ごきげんいかが?'
},
fallback1: 'これはフォールバック'
},
plurals: {
car: 'ザ・ワールド | これはフォールバック',
format: {
named: 'こんにちは {name}, ごきげんいかが? | こんにちは {name}, ごきげんいかが?',
list: 'こんにちは {0}, ごきげんいかが?| こんにちは {0}, ごきげんいかが?'
},
fallback: 'これはフォールバック | ザ・ワールド'
}
}
}
209 changes: 209 additions & 0 deletions test/specs/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,106 @@ describe('i18n', () => {
})
})

describe('Vue.tc', () => {
describe('en language locale', () => {
it('should translate an english', () => {
assert.equal(Vue.tc('plurals.car', 1), 'car')
})
})

describe('multi plural check', () => {
it('should fetch pluralized string', () => {
assert.equal(Vue.tc('plurals.car', 2), 'cars')
})
})

describe('ja language locale', () => {
it('should translate a japanese', () => {
assert.equal(Vue.tc('plurals.car', 1, 'ja'), 'ザ・ワールド')
})
})

describe('key argument', () => {
describe('not specify', () => {
it('should return empty string', () => {
assert.equal(Vue.tc(), '')
})
})

describe('empty string', () => {
it('should return empty string', () => {
assert.equal(Vue.tc(''), '')
})
})

describe('not regist key', () => {
it('should return key string', () => {
assert.equal(Vue.tc('foo.bar'), 'foo.bar')
})
})

describe('sentence fragment', () => {
it('should translate fragment', () => {
assert.equal(Vue.tc('hello world'), 'Hello World')
})

it('should return replaced string if available', () => {
assert.equal(
Vue.tc('Hello {0}', 1, ['kazupon']),
'Hello kazupon'
)
})

it('should return key if unavailable', () => {
assert.equal(Vue.tc('Hello'), 'Hello')
})
})
})

describe('format arguments', () => {
context('named', () => {
it('should return replaced string', () => {
assert.equal(
Vue.tc('plurals.format.named', 1, { name: 'kazupon' }),
'Hello kazupon, how are you?'
)
})
})

context('list', () => {
it('should return replaced string', () => {
assert.equal(
Vue.tc('plurals.format.list', 1, ['kazupon']),
'Hello kazupon, how are you?'
)
})
})
})

describe('language argument', () => {
it('should return empty string', () => {
assert.equal(Vue.tc('plurals.car', 1, 'ja'), 'ザ・ワールド')
})
})

describe('format & language arguments', () => {
it('should return replaced string', () => {
assert.equal(
Vue.tc('plurals.format.list', 1, 'ja', ['kazupon']),
'こんにちは kazupon, ごきげんいかが?'
)
})
})

describe('fallback', () => {
it('should return fallback string', () => {
assert.equal(
Vue.tc('plurals.fallback', 1, 'ja'),
'これはフォールバック'
)
})
})
})

describe('$t', () => {
describe('en language locale', () => {
Expand Down Expand Up @@ -219,6 +319,115 @@ describe('i18n', () => {
})


describe('$tc', () => {
describe('en language locale', () => {
it('should translate plural english', () => {
const vm = new Vue()
assert.equal(vm.$tc('plurals.car', 1), 'car')
})
})

describe('multi plural check', () => {
it('should fetch pluralized string', () => {
const vm = new Vue()
assert.equal(vm.$tc('plurals.car', 2), 'cars')
})
})

describe('key argument', () => {
describe('not specify', () => {
it('should return empty string', () => {
const vm = new Vue()
assert.equal(vm.$tc(), '')
})
})

describe('empty string', () => {
it('should return empty string', () => {
const vm = new Vue()
assert.equal(vm.$tc(''), '')
})
})

describe('not regist key', () => {
it('should return key string', () => {
const vm = new Vue()
assert.equal(vm.$tc('foo.bar'), 'foo.bar')
})
})

describe('sentence fragment', () => {
it('should translate fragment', () => {
const vm = new Vue()
assert.equal(vm.$tc('hello world'), 'Hello World')
})

it('should return replaced string if available', () => {
const vm = new Vue()
assert.equal(
vm.$tc('Hello {0}', 1, ['kazupon']),
'Hello kazupon'
)
})

it('should return key if unavailable', () => {
const vm = new Vue()
assert.equal(vm.$tc('Hello'), 'Hello')
})
})
})

describe('format arguments', () => {
context('named', () => {
it('should return replaced string', () => {
const vm = new Vue()
assert.equal(
vm.$tc('plurals.format.named', 1, { name: 'kazupon' }),
'Hello kazupon, how are you?'
)
})
})

context('list', () => {
it('should return replaced string', () => {
const vm = new Vue()
assert.equal(
vm.$tc('plurals.format.list', 1, ['kazupon']),
'Hello kazupon, how are you?'
)
})
})
})

describe('language argument', () => {
it('should return empty string', () => {
const vm = new Vue()
assert.equal(vm.$tc('plurals.car', 1, 'ja'), 'ザ・ワールド')
})
})

describe('format & language arguments', () => {
it('should return replaced string', () => {
const vm = new Vue()
assert.equal(
vm.$tc('plurals.format.list', 1, 'ja', ['kazupon']),
'こんにちは kazupon, ごきげんいかが?'
)
})
})

describe('fallback', () => {
it('should return fallback string', () => {
const vm = new Vue()
assert.equal(
vm.$tc('plurals.fallback', 2, 'ja'),
'ザ・ワールド'
)
})
})
})


describe('reactive translation', () => {
let el
beforeEach(() => {
Expand Down

0 comments on commit b5b84d8

Please sign in to comment.