vue-i18n 如何缩写货币显示?
vue-i18n how to abbreviate currency display?
在 vue-i18n 生态系统中,有没有办法实现 d3 可以用 precisionPrefix 做的事情?
有一个未解决的问题 here。
我发现 Intl
对象 here 的旧问题。
感谢您的帮助。
一个 hacky 方法将用您自己的处理程序替换 VueI18n.n
。
添加自定义 属性=abbreviate to VueI18n.numberFormats
以确定是否应用特殊样式。
将原始的VueI18n.n
保存为VueI18n.n1
(其他样式我们仍将使用VueI18n.n1
)
用自己的handler替换VueI18n.n
,然后在handler里面,检查numberFormatter.abbreviate
是否为真,如果是,应用你的特殊风格(在下面的演示中,只需使用正则表达式来实现它)。
就像下面的简单演示:
PS: 下面我使用一个 simple 正则表达式来应用样式,对于一些特殊的数字格式,它可能不行,需要自己改进。
Vue.use(VueI18n)
const numberFormats = {
'en-US': {
currency: {
style: 'currency', currency: 'USD', currencyDisplay: 'symbol', useGrouping: false
}
},
'ja-JP': {
currency: {
style: 'currency', currency: 'JPY', currencyDisplay: 'name',
abbreviate: true, // custom property to determinate whether apply special styles
maximumSignificantDigits: 4, useGrouping: true
}
}
}
const i18n = new VueI18n({
numberFormats
})
i18n.n1 = i18n.n // save default i18n.n to i18n.n1
i18n.n= function (nValue, nStyle) {
let numberFormatter = this.getNumberFormat(this.locale) // get NumberFormat Based on locale
if (numberFormatter[nStyle].abbreviate) { // if custom property is true
let newValue = Math.round(nValue/1000000) // divide 10^6 for millions, divide 10^3 for K .etc
return this.n1(newValue, nStyle).replace(/(\d[\d|,]*)(\.\d+)?/, ' M')
}
return this.n1(nValue, nStyle) // for others , use default i18n.n to process.
}
Vue.config.productionTip = false
app = new Vue({
el: "#app",
i18n,
data: {
test: 1234567890,
language: 'en-US'
},
computed: {
computedTest: function () {
return this.$n(this.test, 'currency')
}
},
methods: {
toggleLanguage: function () {
this.language = this.language === 'en-US' ? 'ja-JP' : 'en-US'
this.$i18n.locale = this.language
}
}
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-i18n/7.8.0/vue-i18n.js"></script>
<div id="app">
<button @click="toggleLanguage()">Language </button>
<p>Language: [{{language}}]</p>
<p>Org: {{test}}</p>
<p>localed: {{computedTest}}</p>
</div>
编辑:另一种方法:使用D3-format
Vue.use(VueI18n)
const numberFormats = {
'en-US': {
currency: {
style: 'currency', currency: 'USD', currencyDisplay: 'symbol', useGrouping: false
}
},
'ja-JP': {
currency: {
style: 'currency', currency: 'JPY', currencyDisplay: 'name',
abbreviate: true, // custom property to determinate whether apply special styles
maximumSignificantDigits: 4, useGrouping: true
}
}
}
const i18n = new VueI18n({
numberFormats
})
let d3Locales = {}
axios.get('https://unpkg.com/d3-format@1/locale/ja-JP.json')
.then(function (response) {
d3Locales['ja-JP'] = response.data
})
.catch(function (error) {
console.log(error);
});
axios.get('https://unpkg.com/d3-format@1/locale/en-US.json')
.then(function (response) {
d3Locales['en-US'] = response.data
})
.catch(function (error) {
console.log(error);
});
i18n.n1 = i18n.n // save default i18n.n to i18n.n1
i18n.n= function (nValue, nStyle) {
let numberFormatter = this.getNumberFormat(this.locale) // get NumberFormat Based on locale
if (numberFormatter[nStyle].abbreviate) { // if custom property is true
d3.formatDefaultLocale(d3Locales[this.locale])
let p = d3.precisionPrefix(1e4, 1e6),
f = d3.formatPrefix("$." + p, 1e6)
return f(nValue);
}
return this.n1(nValue, nStyle) // for others , use default i18n.n to process.
}
Vue.config.productionTip = false
app = new Vue({
el: "#app",
i18n,
data: {
test: 1234567890,
language: 'en-US'
},
computed: {
computedTest: function () {
return this.$n(this.test, 'currency')
}
},
methods: {
toggleLanguage: function () {
this.language = this.language === 'en-US' ? 'ja-JP' : 'en-US'
this.$i18n.locale = this.language
}
}
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-i18n/7.8.0/vue-i18n.js"></script>
<script src="https://d3js.org/d3-format.v1.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div id="app">
<button @click="toggleLanguage()">Language </button>
<p>Language: [{{language}}]</p>
<p>Org: {{test}}</p>
<p>localed: {{computedTest}}</p>
</div>
经过一段时间的研究后,我决定编写自己的辅助方法,因为我网站上显示的价格相当大,所以缩写是必须的。 @Sphinx 解决方案似乎只是为了缩短数字而付出太多努力。
我创建了一个 utils 文件并将 i18n 导入其中。创意来自
//Utils.js
import { i18n } from 'boot/i18n.ts'
export const CURRENCY_CALCULATOR = (price) => {
let abbreviatedPrice = price
if (i18n.locale === 'en-us') {
abbreviatedPrice = Math.abs(Number(price)) >= 1.0e+6
? Math.abs(Number(price)) / 1.0e+6 + "M"
: Math.abs(Number(price)) >= 1.0e+3
? Math.abs(Number(price)) / 1.0e+3 + "K"
: Math.abs(Number(price));
} else {
// Other languages uses different units
abbreviatedPrice = Math.abs(Number(price)) >= 1.0e+4
? Math.abs(Number(price)) / 1.0e+4 + i18n.t('sorting.tenThousands')
: Math.abs(Number(price));
}
// setup currency symbol by yourself, because I use the same symbol for both
return `$ ${abbreviatedPrice}`
}
在你的组件中
<template>
<div class="col-auto">
{{ calculateCurrency(item.price) }}
</div>
</template>
<script>
import { CURRENCY_CALCULATOR } from '../constants/Utils'
export default {
name: '<<component name here>>',
props: ['<<your props here>>']
methods: {
calculateCurrency (price) {
return CURRENCY_CALCULATOR(price)
}
}
}
</script>
在 vue-i18n 生态系统中,有没有办法实现 d3 可以用 precisionPrefix 做的事情?
有一个未解决的问题 here。
我发现 Intl
对象 here 的旧问题。
感谢您的帮助。
一个 hacky 方法将用您自己的处理程序替换 VueI18n.n
。
添加自定义 属性=abbreviate to
VueI18n.numberFormats
以确定是否应用特殊样式。将原始的
VueI18n.n
保存为VueI18n.n1
(其他样式我们仍将使用VueI18n.n1
)用自己的handler替换
VueI18n.n
,然后在handler里面,检查numberFormatter.abbreviate
是否为真,如果是,应用你的特殊风格(在下面的演示中,只需使用正则表达式来实现它)。
就像下面的简单演示:
PS: 下面我使用一个 simple 正则表达式来应用样式,对于一些特殊的数字格式,它可能不行,需要自己改进。
Vue.use(VueI18n)
const numberFormats = {
'en-US': {
currency: {
style: 'currency', currency: 'USD', currencyDisplay: 'symbol', useGrouping: false
}
},
'ja-JP': {
currency: {
style: 'currency', currency: 'JPY', currencyDisplay: 'name',
abbreviate: true, // custom property to determinate whether apply special styles
maximumSignificantDigits: 4, useGrouping: true
}
}
}
const i18n = new VueI18n({
numberFormats
})
i18n.n1 = i18n.n // save default i18n.n to i18n.n1
i18n.n= function (nValue, nStyle) {
let numberFormatter = this.getNumberFormat(this.locale) // get NumberFormat Based on locale
if (numberFormatter[nStyle].abbreviate) { // if custom property is true
let newValue = Math.round(nValue/1000000) // divide 10^6 for millions, divide 10^3 for K .etc
return this.n1(newValue, nStyle).replace(/(\d[\d|,]*)(\.\d+)?/, ' M')
}
return this.n1(nValue, nStyle) // for others , use default i18n.n to process.
}
Vue.config.productionTip = false
app = new Vue({
el: "#app",
i18n,
data: {
test: 1234567890,
language: 'en-US'
},
computed: {
computedTest: function () {
return this.$n(this.test, 'currency')
}
},
methods: {
toggleLanguage: function () {
this.language = this.language === 'en-US' ? 'ja-JP' : 'en-US'
this.$i18n.locale = this.language
}
}
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-i18n/7.8.0/vue-i18n.js"></script>
<div id="app">
<button @click="toggleLanguage()">Language </button>
<p>Language: [{{language}}]</p>
<p>Org: {{test}}</p>
<p>localed: {{computedTest}}</p>
</div>
编辑:另一种方法:使用D3-format
Vue.use(VueI18n)
const numberFormats = {
'en-US': {
currency: {
style: 'currency', currency: 'USD', currencyDisplay: 'symbol', useGrouping: false
}
},
'ja-JP': {
currency: {
style: 'currency', currency: 'JPY', currencyDisplay: 'name',
abbreviate: true, // custom property to determinate whether apply special styles
maximumSignificantDigits: 4, useGrouping: true
}
}
}
const i18n = new VueI18n({
numberFormats
})
let d3Locales = {}
axios.get('https://unpkg.com/d3-format@1/locale/ja-JP.json')
.then(function (response) {
d3Locales['ja-JP'] = response.data
})
.catch(function (error) {
console.log(error);
});
axios.get('https://unpkg.com/d3-format@1/locale/en-US.json')
.then(function (response) {
d3Locales['en-US'] = response.data
})
.catch(function (error) {
console.log(error);
});
i18n.n1 = i18n.n // save default i18n.n to i18n.n1
i18n.n= function (nValue, nStyle) {
let numberFormatter = this.getNumberFormat(this.locale) // get NumberFormat Based on locale
if (numberFormatter[nStyle].abbreviate) { // if custom property is true
d3.formatDefaultLocale(d3Locales[this.locale])
let p = d3.precisionPrefix(1e4, 1e6),
f = d3.formatPrefix("$." + p, 1e6)
return f(nValue);
}
return this.n1(nValue, nStyle) // for others , use default i18n.n to process.
}
Vue.config.productionTip = false
app = new Vue({
el: "#app",
i18n,
data: {
test: 1234567890,
language: 'en-US'
},
computed: {
computedTest: function () {
return this.$n(this.test, 'currency')
}
},
methods: {
toggleLanguage: function () {
this.language = this.language === 'en-US' ? 'ja-JP' : 'en-US'
this.$i18n.locale = this.language
}
}
})
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-i18n/7.8.0/vue-i18n.js"></script>
<script src="https://d3js.org/d3-format.v1.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div id="app">
<button @click="toggleLanguage()">Language </button>
<p>Language: [{{language}}]</p>
<p>Org: {{test}}</p>
<p>localed: {{computedTest}}</p>
</div>
经过一段时间的研究后,我决定编写自己的辅助方法,因为我网站上显示的价格相当大,所以缩写是必须的。 @Sphinx 解决方案似乎只是为了缩短数字而付出太多努力。
我创建了一个 utils 文件并将 i18n 导入其中。创意来自
//Utils.js
import { i18n } from 'boot/i18n.ts'
export const CURRENCY_CALCULATOR = (price) => {
let abbreviatedPrice = price
if (i18n.locale === 'en-us') {
abbreviatedPrice = Math.abs(Number(price)) >= 1.0e+6
? Math.abs(Number(price)) / 1.0e+6 + "M"
: Math.abs(Number(price)) >= 1.0e+3
? Math.abs(Number(price)) / 1.0e+3 + "K"
: Math.abs(Number(price));
} else {
// Other languages uses different units
abbreviatedPrice = Math.abs(Number(price)) >= 1.0e+4
? Math.abs(Number(price)) / 1.0e+4 + i18n.t('sorting.tenThousands')
: Math.abs(Number(price));
}
// setup currency symbol by yourself, because I use the same symbol for both
return `$ ${abbreviatedPrice}`
}
在你的组件中
<template>
<div class="col-auto">
{{ calculateCurrency(item.price) }}
</div>
</template>
<script>
import { CURRENCY_CALCULATOR } from '../constants/Utils'
export default {
name: '<<component name here>>',
props: ['<<your props here>>']
methods: {
calculateCurrency (price) {
return CURRENCY_CALCULATOR(price)
}
}
}
</script>