vue-i18n如何缩写货币显示?

时间:2018-06-11 10:21:16

标签: javascript vue.js vue-i18n

有没有办法在vue-i18n生态系统中实现d3与precisionPrefix的关系?

有一个未解决的问题here

我发现了Intl对象here的旧问题。

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

一种 hacky 方式将使用您自己的处理程序替换VueI18n.n

  1. 将custom property = abbreviate添加到VueI18n.numberFormats以确定是否应用特殊样式。

  2. 将原始VueI18n.n保存到VueI18n.n1(我们仍然会将VueI18n.n1用于其他样式)

  3. 使用您自己的处理程序替换VueI18n.n,然后在处理程序中检查numberFormatter.abbreviate是否为真,如果是,请应用您的特殊样式(在下面demo,只需使用正则表达式来实现它。)

  4. 如以下简单演示:

    PS:下面我使用一个简单正则表达式表达式来应用样式,对于某些特殊数字格式,它可能不起作用,您需要自己改进它。

    
    
    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+)?/, '$1 $2M')
      }
      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>
    &#13;
    &#13;
    &#13;

    修改:另一种方法:使用D3-format

    &#13;
    &#13;
    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
        }
      }
    })
    &#13;
    <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>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:0)

经过一段时间的探索,我决定编写自己的帮助方法,因为在我的网站上显示的价格非常高,因此必须使用缩写。 @Sphinx解决方案似乎只是为了使数字更短而付出了很多努力。

我创建了一个utils文件并将i18n导入到其中。这个想法来自how to convert numbers to million in javascript

//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>