Open mv-go opened 2 years ago
Thank you for your reporting!
We cannot use the part
option with n
.
api docs said, n
returns only string type.
if you would like to use Intl.NumberFormatter.prototype.formatToParts
, you need to use the Number format component i18n-n
.
https://vue-i18n.intlify.dev/guide/essentials/number.html#custom-formatting
I would like to know the use case why you would like to use formatToParts
and equivalent in n
.
Maybe, it’s useful for everyone else as well.
Hi, @kazupon !
Thanks for replying!
My use case is the following:
We are working with high-precision numbers in my project. Precision sometimes goes up to 18 fractional digits.
So I can have a value = 0.0123456789012345678
. JS is not capable of working with precision over 15 digits. So even declaring such value const value = ...
and then logging it console.log(value)
will log a rounded number - some precision will be lost. Something similar is actually happening when passing such precise numbers from BE to FE (or vice versa) using JSON.
We have decided that BE will provide to the FE such values as strings. And FE would have to display them to users localised. This is where i18n comes into play.
Obviously I can not pass strings to n
and passing string directly to Intl.NumberFormat
converts them to number
first under the hood. So the precision is lost again.
My idea was to do something along the lines of
const customFormatter = (value: string) => {
const asNumber = Number(value) // so precision is lost, but it's OK
const asParts = n(asNumber, { key: 'myNumberFormat', part: true })
const jsonDecimalSeparator = '.' // decimal separator used by my BE for numbers-as-string
const separatorIndex = value.indexOf(jsonDecimalSeparator) // index of a separator in the original string
const preciseInteger: string = value.slice(0, separatorIndex) // precise integer part as string
const preciseFraction: string = value.slice(separatorIndex + jsonDecimalSeparator.length, value.length) // precise fraction part as string
// here is the "clever" part - replacing parts of formatted number with their respective precise values
const asPrecisePartsFlattened = asParts.map(part => {
if (part.type === 'integer') return preciseInteger
if (part.type === 'fractions') return preciseFraction
return part.value
})
return asPrecisePartsFlattened.join('') // return a formatted string
}
This can obviously be extended to add reactivity, support for whole-integer numbers, different formats, etc.
Actually, while writing this, it got me thinking that folks working with (not-yet) supported currencies - e.g. cryptos of all sorts - could also benefit from this.
const customCurrencies = ['Crypto1, Crypto2']
const customFormat = (value: number, currency: string) => {
if (!customCurrencies.includes(currency)) return n(value, { key: 'currencyFormat', currency })
const asParts = n(value, { key: 'currencyFormat', currency: 'USD' }) // using USD to not cause Intl error
return asParts
.map(part => {
if (part.type !== 'currency') return part
return {
...part
value: currency // replacing USD to our custom currency
}
})
.map(part => part.value) // flatten - collect parts values together
.join('') // return a formatted string
}
Thanks for your detail use-case!
It helps me understand your use case.
I will try to support formatToParts
in n
.
Reporting a bug?
Using
part
option for number formatter throws an error. JSfiddle below.Example usage:
Expected behavior
Reproduction
https://jsfiddle.net/qagtkzxj/39/
System Info
Screenshot
No response
Additional context
No response
Validations