Skip to content

part option for n fails with an error #1165

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
5 tasks done
mv-go opened this issue Sep 9, 2022 · 4 comments · May be fixed by #2170
Open
5 tasks done

part option for n fails with an error #1165

mv-go opened this issue Sep 9, 2022 · 4 comments · May be fixed by #2170
Labels
🍰 p2-nice-to-have Priority 2: nothing is broken but it's worth addressing Status: In Progress Work in Progress Status: PR Welcome Welcome to Pull Request Type: Feature Includes new features

Comments

@mv-go
Copy link

mv-go commented Sep 9, 2022

Reporting a bug?

Using part option for number formatter throws an error. JSfiddle below.

Example usage:

const i18n = createI18n({
  locale: 'en',
  legacy: false,
  numberFormats: {
    en: {
      currency: {
        style: 'currency',
        currencyDisplay: 'narrowSymbol',
      },
    }
})

const { n } = useI18n()

const parts = n(100, { key: 'currency', part: true, currency: 'USD' })

Expected behavior

  • not to throw error
  • return an array of parts, so have the same return signature as Intl.NumberFormatter.prototype.formatToParts

Reproduction

https://jsfiddle.net/qagtkzxj/39/

System Info

System:
    OS: macOS 12.5.1
    CPU: (8) arm64 Apple M1
    Memory: 80.39 MB / 8.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.16.0 - ~/.nvm/versions/node/v16.16.0/bin/node
    Yarn: 1.22.18 - /opt/homebrew/bin/yarn
    npm: 8.11.0 - ~/.nvm/versions/node/v16.16.0/bin/npm
  Browsers:
    Chrome: 104.0.5112.101
    Firefox: 94.0.2
    Firefox Developer Edition: 105.0
    Safari: 15.6.1
  npmPackages:
    vue: ^3.2.36 => 3.2.37 
    vue-chartjs: ^4.1.1 => 4.1.1 
    vue-i18n: ^9.2.2 => 9.2.2 
    vue-router: ^4.1.5 => 4.1.5

Screenshot

No response

Additional context

No response

Validations

@mv-go mv-go added the Status: Review Needed Request for review comments label Sep 9, 2022
@kazupon
Copy link
Member

kazupon commented Sep 12, 2022

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.

@kazupon kazupon added Status: Proposal Request for comments and removed Status: Review Needed Request for review comments labels Sep 12, 2022
@mv-go
Copy link
Author

mv-go commented Sep 12, 2022

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
}

Copy link
Member

kazupon commented Sep 13, 2022

Thanks for your detail use-case!
It helps me understand your use case.
I will try to support formatToParts in n.

@kazupon kazupon added Status: In Progress Work in Progress Type: Feature Includes new features Status: PR Welcome Welcome to Pull Request and removed Status: Proposal Request for comments labels Sep 13, 2022 — with Volta.net
@kazupon kazupon added the 🍰 p2-nice-to-have Priority 2: nothing is broken but it's worth addressing label Nov 15, 2022 — with Volta.net
@mauryapari
Copy link

I have implemented the support for part option in the $n() function.
The initial changes are included in the below PR.

#2170

If these changes look good, I will proceed with updating the documentation.
@kazupon Please let me know if this aligns with your expectations — happy to make any adjustments based on your feedback!

@mauryapari mauryapari linked a pull request Apr 26, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🍰 p2-nice-to-have Priority 2: nothing is broken but it's worth addressing Status: In Progress Work in Progress Status: PR Welcome Welcome to Pull Request Type: Feature Includes new features
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants