Skip to content
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

[Feature Request] Implement CultureInfo as thin layer on top of built-in Internationalization APIs #2126

Closed
Zaid-Ajaj opened this issue Jul 21, 2020 · 4 comments
Labels

Comments

@Zaid-Ajaj
Copy link
Member

Description

The reason Fable doesn't support CultureInfo is sheer number of locale-specific information that Fable would need to implement. Luckily though, both the browser and nodejs environments provide a built-in internationalization API known as Intl. This API already supports number and date formatting that we can use when using {Int32|Double|Decimal|DateTime|DateTimeOffset}.ToString(CultureInfo) so that Fable can delegate as much work possible to the Intl APIs and remove the existing implementation.

I propose a simple generation output:

let dutch = CultureInfo.GetCultureInfo "nl-NL" // compiles to simply { locale: "nl-NL" }

compiles to

export const dutch = { locale: "nl-NL" }

Retrieving current locale:

let currentCulture =  CultureInfo.CurrentCulture
let invariantCulture = CultireInfo.InvariantCulture

compiles to this cross-platform expression

export const currentCulture = { locale: Intl.DateTimeFormat().resolvedOptions().locale } 
export const invariantCulture = { locale: "en-GB" } // always (at least something stable) 

Formatting APIs

let dutch = CultureInfo.GetCultureInfo "nl-NL"
let price = 120.50
let formatted = price.ToString("C", dutch)

compiles to

export const dutch = { locale: "nl-NL" }
export const price = 120.50
export const formatted = new Intl.NumberFormat(dutch.locale, { style: 'currency', currency: lookupCurrency(dutch.locale) }).format(price)

where lookupCurrency is a fable-core utility function that returns currency code based on the input locale:

const lookupCurrency = locale => {
  const lookup = {
     "nl-NL": "EUR", 
     "ja-JP": "JPY", 
      // ....
  }
  
  return lookup[locale] || someDefaultHere; 
}

You can also extend currency formatting. for example price.ToString("C3", dutch) would add an extra option maximumSignificantDigits to be added as well to the number formatting options.

And so of and so forth for date formatting as well. Unfortunately, there is no culture specific number/date parsing in JS (afaik) so things like Int32.Parse and DateTime.Parse wouldn't support CultureInfo either like they are doing now.

I hope we can get this in #2078

The alternative is of course to write a binding library outside of Fable to map the formatting APIs to Intl calls

@alfonsogarciacaro @ncave @MangelMaxime what do you think?

@alfonsogarciacaro
Copy link
Member

For Nagareyama I'm considering to add ReplacementPlugins. We had something similar in Narumi (Fable 1). The idea is users can more easily add custom replacements to their projects and if they work well they can contribute them back to Fable. Maybe we could use this as an opportunity to experiment with this feature.

@Zaid-Ajaj
Copy link
Member Author

Hi @alfonsogarciacaro I don't think the replacement plugins are suitable for this feature, mainly because:

  • It requires adding small utility functions in fable-core (we can emit a fable-core call but not if it is not there)
  • It replaces the current implementation of date and number formatting into a more idiomatic API
  • Might require caching the instances of NumberFormat/DateFormat instead of instantiating a new one every time a currency or date needs to be formatted

@alfonsogarciacaro
Copy link
Member

It requires adding small utility functions in fable-core (we can emit a fable-core call but not if it is not there)

You should be able to include references to utility functions (either in JS or F#). Anyways, maybe in this case the currency could be included in the CultureInfo translation?

It replaces the current implementation of date and number formatting into a more idiomatic API

It depends on the precedence of the replacements. We should likely make custom replacements go before the built-in ones so you could intercept date and number formatting. If they're not replaced successfully, the built-in replacement takes place.

Might require caching the instances of NumberFormat/DateFormat instead of instantiating a new one every time a currency or date needs to be formatted

A utility function could do the change. Though in this case it may not be necessary. At least all the examples in MDN call the constructor every time: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat

In any case, raising these question is a proof that it would be good to test the Replacement plugins with a real use-case like this, so we can polish the plugins feature before releasing the stable version of Nagareyama 👍

@alfonsogarciacaro
Copy link
Member

Closing as there are no plans to implement this feature at least for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants