GithubHelp home page GithubHelp logo

Intl Support about hermes HOT 182 CLOSED

facebook avatar facebook commented on April 26, 2024 181
Intl Support

from hermes.

Comments (182)

wyzzy avatar wyzzy commented on April 26, 2024 93

Strong +1 for including Intl support out-of-the-box in Hermes, having just encountered this limitation ourselves!

At the moment the lack of Intl support on Android RN is a major source of inconsistency in behaviour between iOS and Android. On iOS Intl 'just works' as expected, but not so on Android, where you're stuck trying to find some workable solution to restore parity in behaviour on the two platforms. On iOS, Number.prototype.toLocaleString() for formatting numbers and currency values all work as expected, as does Date.prototype.toLocaleString() for dates, and all the Intl API...

The lack of Intl support on Android's out-of-the-box JSC was one significant hurdle we encountered in enabling our iOS-first RN app for Android. As many folks have said, the pollyfills just don't work well enough and feel like an unsatisfactory hack.

For our investment app, date/time and currency formatting are the primary drivers, though relative time rules, plural rules, and list formats would all undeniably help offer a more polished user experience.

Needing to include a custom JSC build on Android is non-trivial and really shouldn't be necessary for such a fundamental piece of functionality!

If Hermes is worried about size, some RN config to optionally exclude Intl support for those (rare?) apps that don't need it might be a way forward. Surely these days most commercial quality apps need to reliably present localised time & date or numeric/currency values?

If Hermes did fully support Intl, switching from the existing JSC would be a no-brainer for us. On the other hand, no support means we would perhaps be better off with a JSC build that does support it?? Feels like a problem that Hermes needs an answer to, one way or the other.

I18n certainly is darn complicated, which is precisely why it's so important that the platform itself offers first-class support for Intl out of the box! Even on Android.

from hermes.

danilobuerger avatar danilobuerger commented on April 26, 2024 63

Its main use cases (most popular function it has) to the RN community

Enabling I18n for apps regarding:

  • Date / Time Formats
  • Relative Time Formats
  • List Formats
  • Number (also Currency) Formats
  • Plural Rules

Any important libraries that depend on it

https://github.com/formatjs/react-intl (> 10K Stars)
https://github.com/moment/luxon (> 8K Stars)

What alternatives exist (is there a JS-only way to implement it?)

As pointed out by @fbartho, polyfilling doesn't work properly. Every other solution is incomplete at least regarding locale rules around the world.

but I think it was related to ICU's binary size

If it is just about binary size, it could be done like JSC: a variant with Intl.
See https://github.com/react-native-community/jsc-android-buildscripts/#international-variant

and that it is not part of the normal EcmaScript JS spec

However, lots of functions that are part of the ECMAScript 2015, are dependent on Intl to function "properly", or at least need a locale aware implementation anyway. For example:

20.3.4.39 Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )
An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Date.prototype.toLocaleString method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of the toLocaleString method is used.

This function returns a String value. The contents of the String are implementation-dependent, but are intended to represent the Date in the current time zone in a convenient, human-readable form that corresponds to the conventions of the host environment’s current locale.

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024 44

An update on plans for Intl support. Our primary motivation for building Intl support is to make Hermes usable as a replacement for JSC for the most apps on Android.

Currently, the android community build of JSC doesn't support all of ECMA 402. In particular, the only properties of Intl which it supports are getCanonicalLocales, Collator, NumberFormat, DateTimeFormat, and PluralNames. The latter was only relatively recently implemented in JSC. In addition, DateTimeFormat.formatRange/formatRangeToParts are not implemented by JSC.

Given the history of Intl JSC, we will plan initially to implement getCanonicalLocales, Collator, NumberFormat, and DateTimeFormat, excluding the range methods. Later, we can add more functionality as needed.

If anybody knows of RN app which uses any other Intl APIs, please comment and tag me. Thanks!

from hermes.

fbartho avatar fbartho commented on April 26, 2024 42

Intl is super important for us, and unfortunately, it's a blocker for my team. The Polyfills we tried before switching to jsc-intl weren't complete (they allowed compilation/basic testing, but didn't work in actual localized environments).

Is there a plan for when Intl might be discussed again for the Hermes Engine?

from hermes.

jcurtis avatar jcurtis commented on April 26, 2024 31

Intl is a major concern for all the apps I have ever worked on. Today we're using react-intl which is one of the most popular React libraries for handling intl. As stated before, there are no polyfills that work properly on Android right now.

I'd be curious if someone could tell us what Facebook uses to handle intl in their React Native apps? Specifically for number and date formatting.

from hermes.

tmikov avatar tmikov commented on April 26, 2024 26

Sorry about the delayed response here. Internally at Facebook we use fbt, with its own specific translation assets handling, and translation dictionary shipped with the app binary. fbt was open sourced a while back, and fortunately we have RN android variant in OSS now.

See:
https://github.com/facebookincubator/fbt
https://github.com/facebookincubator/fbt/tree/master/packages/fbt-rn-android-native
https://github.com/facebookincubator/fbt/tree/rn-demo-app

The published version currently builds for Android but AFAIK there is nothing preventing porting to iOS.

On the subject of Intl support: we would like to have it in Hermes, but it isn't our top priority, since, as described above, we don't use it internally. We welcome help from the community in implementing it.

from hermes.

TheSavior avatar TheSavior commented on April 26, 2024 25

EDIT: I found that Chrome Status shares data publicly on the usage of these APIs. I have gathered and ordered that data for the Intl APIs in this comment.

Additional anecdotal data is probably not as helpful now.


We are revisiting Intl support on Hermes and need your help figuring out which functions to prioritize. There are a ton of Intl APIs and I'd bet that only a handful of them are the most critical functions blocking Hermes adoption.

Please help us understand the particular function calls that are blocking your ability to use Hermes. For example, I've seen Number.prototype.toLocaleString() mentioned twice in this thread. That's the kind of specific example I'm looking for. "Relative Time Formats" is too vague. I'm sure there are many more functions that would be really nice to have but aren't as critical. Please mention them, but separately so I can track that.

Intl functions blocking usage of Hermes:

  • Number.prototype.toLocaleString()
  • Date.prototype.toLocaleString
  • Date.prototype.toLocaleTimeString
  • Intl.DateTimeFormat().resolvedOptions
  • Intl.DateTimeFormat().format() (specific options)
  • Intl.NumberFormat().format() (specific options)
  • Intl.RelativeTimeFormat().format()
  • String.prototype.localeCompare

Also, I saw a mention of the react-intl project. Can someone go through that and identify what Intl functions it uses and share those here?

Thanks!

from hermes.

feruzm avatar feruzm commented on April 26, 2024 22

Big thanks to this thread, Hermes is great but we need support for Intl which most fundamental part of any app.

from hermes.

TheTimeWalker avatar TheTimeWalker commented on April 26, 2024 18

One thing to add: Intl works perfectly out of box on iOS as it has to use its V8 (oops!) JavaScriptCore engine which already integrates this. So I find it strange why we're trying to back off from Intl support as this would just confuse RN developers with the iOS and Android feature gap.

from hermes.

longlho avatar longlho commented on April 26, 2024 14

Hello, I'm the maintainer of react-intl & formatjs & also a delegate on TC39/ECMA-402. We got quite a few requests to support non-traditional JS engines that don't have Intl, and sounds like hermes is 1 of those. There're no hierarchy of which Intl APIs are more important/popular from my perspective because most implementations either use libicu or has native bindings that wraps around icu4j/icu4c.

On top of that the standards are evolving. formatjs has polyfills for stage-3 APIs like Unified NumberFormat which allows you to format units like 5 feet or compact notation like 1 thousand. What you'd gain from native implementation in hermes vs polyfill would basically means hermes would have to package w/ CLDR data (& follow its upgrade cadence as well). That's a non-trivial amount of bytes.

Performance-wise I don't see a huge advantage unless you're handling subsecond re-rendering.

The other reason why it's hard to pick and choose 2, 3 or 4 APIs to support is because if you look at the spec, they share a lot of abstract operations & CLDR data. For example, you typically always have to start with locale negotiation, which is the process to match what the user asks for, and what data you have. None of the browsers package ALL of CLDR so this is especially important. From there you start figuring out CLDR dataset(s) based on the API and then join them together to produce the best-effort output (that's right, ECMA-402 is best effort & not correct).

If I were to rank, the sequence you basically need would be something like:

  1. Intl.Locale because you need locale negotiation, whether public or abstract
  2. Intl.DateTimeFormat because you need 2 datasets: CLDR for pattern & IANA for timezone so it might help a lot of people to not have to polyfill those giant datasets.
  3. Intl.PluralRules because it's very foundational, even to NumberFormat (to determine things like 1 dollar vs 2 dollars)
  4. Intl.NumberFormat because it's an important primitive
  5. Intl.RelativeTimeFormat is cherry-on-top.

The class of problem involving string like Collation algorithm is fairly separate and not necessarily required.

Happy to chat more :)

from hermes.

patrickkempff avatar patrickkempff commented on April 26, 2024 10

How does facebook handle Intl in their apps when using Hermes?

from hermes.

janicduplessis avatar janicduplessis commented on April 26, 2024 10

I'm currently using the following polyfills for Hermes:

I'm using https://lingui.js.org/ as a higher level abstraction over intl apis.

I don't have anything blocking usage of hermes since it works fine with these polyfills. First thing would be to try and remove usage of the intl polyfill, this one actually implements a lot of apis, the list is available here https://github.com/andyearnshaw/Intl.js#implemented.

Here are some Intl apis I use either directly or through lingui-js:

  • Intl.NumberFormat for currency formatting.
  • Intl.DateTimeFormat for date formatting.
  • Intl.RelativeTimeFormat for relative date formatting (x days ago).

from hermes.

TheSavior avatar TheSavior commented on April 26, 2024 10

Microsoft is staffing up people to work on the Intl implementations that @mhorowitz mentioned live in https://github.com/facebook/hermes/tree/master/lib/Platform/Intl

from hermes.

longlho avatar longlho commented on April 26, 2024 9

FWIW we just released Intl.DateTimeFormat ES2021 polyfill so basically all the Intl APIs are polyfills except Intl.Collator
https://formatjs.io/docs/polyfills

from hermes.

chrisbobbe avatar chrisbobbe commented on April 26, 2024 9

if you look over in the Pull Requests tab, you can see that this work is progressing. I'm excited to see it happening!

Great! I see that several of these were recently resolved. πŸŽ‰

#319 #320 #321 #322

from hermes.

gmaclennan avatar gmaclennan commented on April 26, 2024 8

As @danilobuerger clearly states, there is no complete and reliable JS-only solution to this. For I18n apps Intl is needed. It adds to binary size, but as I understand it that's because I18n is so darn complicated with so many edge-cases.

from hermes.

mars-lan avatar mars-lan commented on April 26, 2024 8

We ended up using react-native-v8 which provides similar performance benefit like Hermes but has full intl support.

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024 8

@gpawlik A couple weeks ago I landed the framework to bridge between JS to C++ to Java for the APIs I mentioned above. Most of the code lives under https://github.com/facebook/hermes/tree/master/lib/Platform/Intl. This isn't yet very usable, as the changes to build using CMake have not yet landed. We'll be working on that soon.

Once that happens, we need real implementations of the Java API there in terms of the Android ICU library. We have had a community member express intent to work on this, but I cannot speak for their plans directly. Of course, PRs are always welcome!

from hermes.

fbartho avatar fbartho commented on April 26, 2024 6

That's a great point @TheTimeWalker -- this is a "platform compatibility issue" where iOS & Android's JavaScript engines differ. (Nit: iOS uses the JavaScriptCore engine rather than the V8 engine, but your point is the same).

I guess the key question is: What is this project's driving mandate with regards to differences between iOS & Android? -- Presumably the expectation is that there shouldn't be significant framework-level differences? Especially not in things that can't be polyfilled-well.

Unfortunately, the existing Polyfills in this case are insufficient. React-Native developers targeting more than one language will be stuck on jsc-intl unless this feature is provided by Hermes!

from hermes.

jozan avatar jozan commented on April 26, 2024 6

I use Luxon and it uses Intl apis quite a bit. I assume lots of other people also use Luxon for handling dates and timezones and other things.

Luxon uses or supports at least these Intl methods:

  • Intl.RelativeTimeFormat (constructor)
  • Intl.RelativeTimeFormat.prototype.format
  • Intl.RelativeTimeFormat.prototype.formatToParts
  • Intl.DateTimeFormat (constructor)
  • Intl.DateTimeFormat.prototype.formatToParts
  • Intl.DateTimeFormat.prototype.format
  • Intl.DateTimeFormat.prototype.resolvedOptions
  • Date.prototype.toLocaleString

from hermes.

dlebedynskyi avatar dlebedynskyi commented on April 26, 2024 5

@TheSavior
I believe we are specifically interested in DateTime and TimeZone related ones such as

  • Date.prototype.toLocaleString
  • Date.prototype.toLocaleTimeString
  • Intl.DateTimeFormat().resolvedOptions
  • rest of timezone related things

For react-intl it is probably better to start with intl-messageformat as it is most used one.

@fbartho
I believe moment is not actually using Intl.

from hermes.

TheSavior avatar TheSavior commented on April 26, 2024 5

It looks like the ChromeStatus page has usage numbers for these APIs:

  • String.prototype.toLocaleLowerCase() 18.143881%
  • Number.prototype.toLocaleString() 15.742356%
  • DateTimeFormat 8.755547%
  • String.prototype.localeCompare() 8.739834%
  • Collator 5.05094%
  • NumberFormat 3.182229%
  • String.prototype.toLocaleUpperCase() 1.832129%
  • Date.prototype.toLocaleString() 1.7049%
  • Date.prototype.toLocaleDateString() 1.19445%
  • Date.prototype.toLocaleTimeString() 0.796161%
  • RelativeTimeFormat 0.165491%
  • PluralRules 0.136803%
  • ListFormat 0.00172%
  • Locale <=0.000001%

This is probably better than any anecdotal data we are going to get here, although I'm still open to anecdotal data. πŸ˜„

from hermes.

RichardLindhout avatar RichardLindhout commented on April 26, 2024 5

I recommend my library users to use the following code (for my date picker library). (Thanks a lot @longlho!)

// in your index.js file
if (!!global.HermesInternal) {
  require('@formatjs/intl-getcanonicallocales/polyfill')

  require('@formatjs/intl-pluralrules/polyfill')
  require('@formatjs/intl-pluralrules/locale-data/nl') // use your language files

  require('@formatjs/intl-relativetimeformat/polyfill')
  require('@formatjs/intl-relativetimeformat/locale-data/nl') // use your language files

  require('@formatjs/intl-listformat/polyfill')
  require('@formatjs/intl-listformat/locale-data/nl') // use your language files

  require('@formatjs/intl-displaynames/polyfill')
  require('@formatjs/intl-displaynames/locale-data/nl') // use your language files

  require('@formatjs/intl-numberformat/polyfill')
  require('@formatjs/intl-numberformat/locale-data/nl') // use your language files

  require('@formatjs/intl-datetimeformat/polyfill')
  require('@formatjs/intl-datetimeformat/locale-data/nl') // use your language files

  require('@formatjs/intl-datetimeformat/add-all-tz')

  require('@formatjs/intl-locale/polyfill')

  // https://formatjs.io/docs/polyfills/intl-datetimeformat/#default-timezone
  let RNLocalize = require('react-native-localize')
  if ('__setDefaultTimeZone' in Intl.DateTimeFormat) {
    Intl.DateTimeFormat.__setDefaultTimeZone(RNLocalize.getTimeZone())
  }
}

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024 5

@RichardLindhout if you look over in the Pull Requests tab, you can see that this work is progressing. I'm excited to see it happening!

from hermes.

fbartho avatar fbartho commented on April 26, 2024 4

Our codebase also directly uses

from hermes.

janicduplessis avatar janicduplessis commented on April 26, 2024 4

@TheSavior Intl.XFormat apis actually don't really have many functions. AFAIK the usage is pretty much always:

new Intl.XFormat('locale').format(thing)

For example Intl.NumberFormat:

new Intl.NumberFormat('de-DE').format(number)

Actually I think what you are looking for is which options on the format constructor we want to support first. Here's a list of options that should be supported / I'm using

NumberFormat (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat/NumberFormat)

  • style: I think all 4 options would be important to have
  • currency: needed for currency support
  • currencyDisplay
  • minimumFractionDigits
  • maximumFractionDigits

DateTimeFormat (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/DateTimeFormat)

  • dateStyle
  • timeStyle
  • hour12
  • weekday, year, month, day, hour, minute, second

RelativeTimeFormat (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RelativeTimeFormat/RelativeTimeFormat)

This one doesn't have much options so I guess everything.

from hermes.

longlho avatar longlho commented on April 26, 2024 4

If you gotta do it, I'd personally recommend stage-4 of ES2020 because right now there's no way to monkey-patch Intl APIs from ES2015 to, say ES2019, so having old support is kinda worse than no support you'd always lag behind MDN docs. Right now stage-3 polyfills are basically the full implementation.

from hermes.

LouisKraemer avatar LouisKraemer commented on April 26, 2024 4

FWIW we just released Intl.DateTimeFormat ES2021 polyfill so basically all the Intl APIs are polyfills except Intl.Collator
formatjs.io/docs/polyfills

Hi, I tried using your polyfill to use hermes on my RN app but I cannot get it working
I keep getting Property 'Intl' doesn't exist, js engine : hermes
I don't think I missed a step though

Could you help me on the matter ? Hermes would be a huge boost on my app

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024 4

@RichardLindhout Thanks, it's good to know there are workarounds while we work on Intl.

I'm curious, what's the size impact of the JS polyfills on the app? What if someone wants multiple languages?

from hermes.

longlho avatar longlho commented on April 26, 2024 3

So to clarify I'm talking about this: https://formatjs.io/docs/polyfills/intl-relativetimeformat#dynamic-import--capability-detection

I'm not super familiar with how RN does bundling. What I meant is you can still ship w/ ALL locales, just don't load them ALL at once or it'll definitely OOM.

The core polyfill are typically small (~20 - 40KB unminified). Locale data for ALL locales are quite large

API Size (unminified)
Intl.getCanonicalLocales 0
Intl.Locale 0
Intl.PluralRules 848K
Intl.NumberFormat 22M
Intl.DateTimeFormat 22M CLDR + 420K IANA TZ
Intl.RelativeTimeFormat 3.4M
Intl.ListFormat 2.2M
Intl.DisplayNames 15M

So total unminified unzipped is around 85M. Now I did a quick gzip on ru which is typically the largest & most complex locale and compression shaves it down by ~83% so ballpark 14M gzipped? There are 543 locales so you can do the math πŸ˜„

Now this is not apple to apple bc JSC (WebKit) is notorious for being behind on Intl APIs, so tbh I don't what's included in JSC with Intl variant. There's a high chance if u use JSC w/ Intl u'd still need polyfills (e.g https://caniuse.com/#search=relativetimeformat or Intl.NumberFormat ES2020)

from hermes.

longlho avatar longlho commented on April 26, 2024 3

That's if you package 543 locales, which, I don't think you should or need to, 6MB worth of CLDR data would be 250 locales, which, I still don't think you should or need to support πŸ˜„

Supporting another locale (aside from the framework & data to do so) requires operation & QA as they don't always appear the same way (think of bidi, truncation, different calendar like buddhist, different numbering system like tibet...). I haven't seen any app that supports more than a handful.

The polyfill approach has worked well for the web from what I've seen and that has a much stricter size & runtime constraint than native (e.g ECMA402 spent a lot of time discussing which unit are sanctioned to be part of spec bc of size).

That said, I'm not familiar with the RN ecosystem so just my 2c.

from hermes.

learnyst avatar learnyst commented on April 26, 2024 2

Hi,
We also need the support of Intl in hermes.

from hermes.

OtacilioN avatar OtacilioN commented on April 26, 2024 2

Hey folks,

Is that any workaround suggested for Number.prototype.toLocaleString() while they don't implement Intl ?

We broke our minds for some weeks with this bug because when we were using the debug mode in React Native, the Number.prototype.toLocaleString() works, I think because it uses my browser engine to run JavaScript, but as soon we assemble the app or turnOff the debug mode, Number.prototype.toLocaleString() starts to no work.

from hermes.

fbartho avatar fbartho commented on April 26, 2024 2

@OtacilioN -- On my team we're still using org.webkit:android-jsc-intl:r245459 until Hermes supports Intl (we would love to use Hermes for Android Performance reasons!!) Not to give you useless advice, but that's what I recommend.

And I ran into exactly the same debug-time issues with some other features including Proxy (also missing in Hermes, #33), before that was updated to be available on android-jsc. I feel your pain!

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024 2

@longlho I started looking into this, and I have a generic question. ECMA 402 is written in terms of CLDR data, but icu and icu4j are written in terms of higher-level abstractions, which in turn use CLDR data underneath. So, the APIs have strong parallels, but spec compliance is not clear. For example, if implemented new Intl.NumberFormat(...).format(number)); by using com.ibm.icu.number.NumberFormatter and it's associated classes, would this be a proper implementation? Or am I going to run into gaps and inconsistencies? Is test262/test/intl402 detailed enough to provide confidence?

from hermes.

likern avatar likern commented on April 26, 2024 2

Is there any progress this? Is it possible to prioritize on this critical feature?

Recently highly popular react-native-reanimated library introduced new version 2 based on Turbomodules.

Now it supports on Android only Hermes engine (no JSC support yet, no recent plans). At the same time Hermes doesn't support Intl, which is highly popular in i18n (react-intl).

This leads to blocking on Intl support feature. Developers can't update their apps to Reanimated V2.

from hermes.

longlho avatar longlho commented on April 26, 2024 2

I typically recommend dynamically polyfill locale on demand. For intl-numberformat you'll likely OOM if you load everything. Note that Chrome doesn't even ship with all locales.

from hermes.

janicduplessis avatar janicduplessis commented on April 26, 2024 2

I think the main issue with the polyfill approach and supporting a large number of locales is that currently RN doesn't have good support for code splitting and loading bundles at runtime, which I'm pretty sure is how you can scale intl polyfills on the web.

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024 2

Hermes is mainly a C++ library. It doesn't control how JS is packaged or loaded.

It sounds like your suggestions are potentially relevant for React Native, if someone wanted to contribute it.

For now, our strategy for Hermes is to have the Intl APIs call into the Java android.icu APIs, so we can ship only the necessary glue between them. I think this is more sustainable in the long run, although it might not get the functionality into the VM as quickly.

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024 2

@SrBrahma

Is DateTimeFormat already supported?

None of Intl is supported yet, but it's being worked on.

from hermes.

dulinriley avatar dulinriley commented on April 26, 2024 1

It will help us prioritize work on Intl if we know the following things:

  • Its main use cases (most popular function it has) to the RN community
  • Any important libraries that depend on it
  • What alternatives exist (is there a JS-only way to implement it?)

I don't remember the exact conversation we had about Intl, but I think it was related to ICU's binary size, and that it is not part of the normal EcmaScript JS spec.

@avp or @ridiculousfish have more context on this

from hermes.

gpawlik avatar gpawlik commented on April 26, 2024 1

@dulinriley is there any more information that you need in order to prioritise this issue?

from hermes.

fbartho avatar fbartho commented on April 26, 2024 1

I'm not entirely sure how to search react-intl for "particular function calls" that need to be supported. I'm trying to join their slack to figure that out.

In addition to react-intl, a super popular library is MomentJS -- https://momentjs.com & its sub library moment-timezone https://momentjs.com/timezone/

Moment has a CI testing various browsers/environments, so maybe you can add hermes to that list, and then get an enumeration of the methods that are missing / fail tests?

from hermes.

TheSavior avatar TheSavior commented on April 26, 2024 1

Hey @longlho, thanks for the response. We are definitely worried and want to do everything we can to avoid increasing the size of the binary substantially. Our current thinking is that the implementations of these APIs in Hermes would internally use the native Android APIs so that we wouldn't have to include that CLDR data. Does that seem feasible with your understanding?

from hermes.

longlho avatar longlho commented on April 26, 2024 1

The other thing to note is that NumberFormat/DateTimeFormat in ES2015 is different from ES2017 & ES2020 πŸ˜„. The tendency of ECMA-402 right now is to add more things to options instead of new APIs.

from hermes.

longlho avatar longlho commented on April 26, 2024 1

yeah test262 should be enough. Browsers all use icu4c under the hood so I think it should be fine for you guys (e.g V8 https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/objects/js-number-format.h)

from hermes.

gpawlik avatar gpawlik commented on April 26, 2024 1

@mhorowitz would you be able to give us an update on the progress please?

from hermes.

longlho avatar longlho commented on April 26, 2024 1

@likern https://github.com/longlho/hermes-intl-demo

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024 1

@RichardLindhout The gradle files says JSC with Intl support is 6mb larger, per architecture. There is no such thing as an international version of JSI.

I was asking about the size of formatjs polyfills exactly because I was interested in the size impact. Based on what @longlho says, it sounds like adding all languages will blow out your memory, so that's not a good option. But this doesn't tell me even what a single language plus the base polyfills costs in app size.

@longlho when you say "polyfill locale on demand" do you mean add it to your application when people ask for different locales? Since an RN app ships with its JS bundle, I'm not sure what else this might mean.

from hermes.

longlho avatar longlho commented on April 26, 2024 1

Yup that's right, but as i said you don't need to support 200, or even 100 locales

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024 1

As I mentioned, Hermes doesn't implement import yet, so it's doing none of what's in the spec :-) I said we're outside of my domain because I don't personally know anything about our implementation plans or strategy for import. Someone else is working on that.

My message above is attempting to describe the status quo of the current behavior of Hermes as the engine for React Native, where whatever import does, it's entirely out of Hermes's control. Startup performance is one of our primary metrics, so I imagine we're doing things as lazily as possible.

from hermes.

OtacilioN avatar OtacilioN commented on April 26, 2024

@marlonchalegre

from hermes.

OtacilioN avatar OtacilioN commented on April 26, 2024

Yeah, we had some bugs related to proxy too, fortunately, checked the code of the lib that we were using, and made a pull request to not use proxy when is not supported, actually, the usage of proxy was not really necessary in the lib.

Unfortunately, we made the decision of migrating to Hermes a couple of months ago and getting back to JSC could be really painful now. I could not imagine that an engine created by facebook would not support localization. 😒

from hermes.

thinklinux avatar thinklinux commented on April 26, 2024

@patrickkempff I don't think they use it in their apps.

from hermes.

TheSavior avatar TheSavior commented on April 26, 2024

@dlebedynskyi thanks, from my quick searching it looks like IntlMessageFormat isn't part of a finalized spec. Am I looking in the wrong place?

from hermes.

TheSavior avatar TheSavior commented on April 26, 2024

@janicduplessis, it looks like the Intl APIs you list are a collection of multiple functions. Do you know which functions in those APIs you use? The more specific the better here :)

from hermes.

TheSavior avatar TheSavior commented on April 26, 2024

Thanks @janicduplessis @jozan, updated

from hermes.

cdsanchez avatar cdsanchez commented on April 26, 2024

@TheSavior Would it be feasible for this Intl support to be built on top of JSI interfaces such that other JS engines with JSI implementations (beyond Hermes) can take advantage of this?

from hermes.

janicduplessis avatar janicduplessis commented on April 26, 2024

@TheSavior I think another thing to consider is the binary size impact of each Intl api.

from hermes.

longlho avatar longlho commented on April 26, 2024

Not to mention CLDR data compression in and of itself is a whole problem set, because of how locale fallback works (e.g en-GB -> en-001 -> en) so yeah, the increase in size won't be trivial.

We're having debate in ECMA-402 during Unified NumberFormat on what unit data to package, which is why the spec only has 6 sanctioned units. It's definitely a point of contention.

from hermes.

longlho avatar longlho commented on April 26, 2024

Hey @longlho, thanks for the response. We are definitely worried and want to do everything we can to avoid increasing the size of the binary substantially. Our current thinking is that the implementations of these APIs in Hermes would internally use the native Android APIs so that we wouldn't have to include that CLDR data. Does that seem feasible with your understanding?

Yes that's definitely feasible. Android does package icu4j AFAIK.

from hermes.

TheSavior avatar TheSavior commented on April 26, 2024

Cool, phew. πŸ˜…

This is why we are trying to figure out which APIs are the most critical to support. The Hermes implementations will require finagling the Android APIs to match the JS spec. We'd like to unblock the majority of people by prioritizing the common APIs first

from hermes.

janicduplessis avatar janicduplessis commented on April 26, 2024

I was thinking we could strip unused locales but this is even better, I like this approach.

from hermes.

longlho avatar longlho commented on April 26, 2024

If that's your approach I think you'd basically need DateTimeFormat & NumberFormat as the bare minimums (to be on par w/ IE11 πŸ˜„). Intl.PluralRules & Intl.RelativeTimeFormat are fairly small & new. PluralRules are mostly useful in the context of MessageFormat and rarely used raw.

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024

Even passing through to icu, there's still a lot of APIs. Even if we have to do it all, it is useful to know what to prioritize and do first.

from hermes.

janicduplessis avatar janicduplessis commented on April 26, 2024

Yea when talking about XFormat apis it would be useful to know which options are used the most (see #23 (comment)). Or just focus on ES2015 options first.

from hermes.

longlho avatar longlho commented on April 26, 2024

Forgot another thing: have you guys run hermes through test262 yet? Intl API abstract ops rely on several building blocks within the core JS spec (ECMA262) to produce a spec-compliant output (e.g things like digit truncation, rounding & BigDecimal...). Therefore it's pretty important for a JS engine to pass test262 πŸ˜„

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024

We run hermes through test262 on a continuous basis, but we skip parts we know we don't implement, like Intl.

from hermes.

longlho avatar longlho commented on April 26, 2024

Ok cool that's good to hear πŸ‘

from hermes.

longlho avatar longlho commented on April 26, 2024

You're looking for https://formatjs.io/docs/polyfills/intl-datetimeformat/#requirements
For Hermes it's likely you need everything in the dep chain https://formatjs.io/docs/polyfills so Intl.getCanonicalLocales, Intl.PluralRules, Intl.NumberFormat & Intl.DateTimeFormat

from hermes.

likern avatar likern commented on April 26, 2024

@longlho I've installed all polyfills, didn't work for me. I see this error:

[Tue Jun 23 2020 23:42:49.868]  ERROR    ReferenceError: Property 'Intl' doesn't exist, js engine: hermes

from hermes.

longlho avatar longlho commented on April 26, 2024

from hermes.

longlho avatar longlho commented on April 26, 2024

Seems working for me:
simulator
hello-world

from hermes.

likern avatar likern commented on April 26, 2024

Seems working for me:
simulator
hello-world
Could you provide repo?

from hermes.

likern avatar likern commented on April 26, 2024

@likern https://github.com/longlho/hermes-intl-demo

I recreated my i18n code based on your repo https://github.com/likern/hermes-intl-demo. Looks like on expo and ejected expo it's working fine.

If I find the source of this error I let you know.

from hermes.

RichardLindhout avatar RichardLindhout commented on April 26, 2024

@likern It's working fine because you don't have Hermes enabled: https://github.com/likern/hermes-intl-demo/blob/master/android/app/build.gradle#L80.

from hermes.

RichardLindhout avatar RichardLindhout commented on April 26, 2024

In my case I needed at least the following polyfills to make the DateFormatting working

import '@formatjs/intl-getcanonicallocales/polyfill'

import '@formatjs/intl-pluralrules/polyfill'
import '@formatjs/intl-pluralrules/locale-data/nl'

import '@formatjs/intl-numberformat/polyfill'
import '@formatjs/intl-numberformat/locale-data/nl'

import '@formatjs/intl-datetimeformat/polyfill'
import '@formatjs/intl-datetimeformat/locale-data/nl'

from hermes.

RichardLindhout avatar RichardLindhout commented on April 26, 2024

For the multilanguage version of JSI it's 6 MB stated in the build.gradle for all locales.

I don't know what's the impact of of formatjs but I think it's a lot less since we can pick the languages needed and even if you added all languages I don't think it would be 6MB.

Maybe ask @longlho on this since he is a maintainer of formatjs.

It would be nice if we could specify which languages to bundle with Hermes to keep the selling point of small binaries (if it comes as close to the 6mb of the international JSI πŸ™„)

from hermes.

longlho avatar longlho commented on April 26, 2024

For reference this is likely the list of locales Chrome supports: https://src.chromium.org/viewvc/chrome/trunk/src/third_party/cld/languages/internal/languages.cc

from hermes.

RichardLindhout avatar RichardLindhout commented on April 26, 2024

@RichardLindhout The gradle files says JSC with Intl support is 6mb larger, per architecture. There is no such thing as an international version of JSI.

I was asking about the size of formatjs polyfills exactly because I was interested in the size impact. Based on what @longlho says, it sounds like adding all languages will blow out your memory, so that's not a good option. But this doesn't tell me even what a single language plus the base polyfills costs in app size.

@longlho when you say "polyfill locale on demand" do you mean add it to your application when people ask for different locales? Since an RN app ships with its JS bundle, I'm not sure what else this might mean.

I think we can't lazy load yet in RN but it would improve startup time and prevent OOM when you have a lot of locales e.g. something like this (https://github.com/microsoft/react-native-lazy-index)

There is no such thing as an international version of JSI.

I did mean JSC :-D ->

/**
 * The preferred build flavor of JavaScriptCore.
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US.  Note that
 * this variant is about 6MiB larger per architecture than default.
 */

from hermes.

Kudo avatar Kudo commented on April 26, 2024

FWIW, current RN's jsc-android used ICU from Chromium.
Chromium maintains their locale list for android at https://chromium.googlesource.com/chromium/deps/icu.git/+/master/filters/android.json.
Different jsc-android version may use different ICU version,
here I am posting the latest Chromium list.

from hermes.

longlho avatar longlho commented on April 26, 2024

That doesn't look right. That's a language list, not locale list and they are different (e.g en vs en-GB)

from hermes.

Kudo avatar Kudo commented on April 26, 2024

Oops, it was locale list before but changed to filter by language after this CL

from hermes.

longlho avatar longlho commented on April 26, 2024

hmm I don't know enough about chromium lang filter to understand what the change entails.

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024

how RN does bundling

RN apps include all the JS in the app which comes from the store. So even if you loaded stuff as needed, your android store app with hermes + all languages would include 14mb of Intl data. This is a significant fraction of the size of most single-ABI apps. This is why we've been trying to avoid a polyfill approach.

from hermes.

RichardLindhout avatar RichardLindhout commented on April 26, 2024

It would be really nice if we could force the locales which are needed in the app/build.gradle file.

It would also be nice if it would load the provided locales dynamically based on the Intl usage so it would not be in RAM.

E.g English user would never have the Dutch locales in ram.
But maybe that's the case by default I'm not that familiar with how engines or ram bundles work.

from hermes.

longlho avatar longlho commented on April 26, 2024

Yeah I agree that's the better long term solution. Does Hermes implement dynamic import though? That's basically the backbone of code splitting.

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024

Does Hermes implement dynamic import though?

Not yet. It's in progress at https://github.com/facebook/hermes/blob/master/doc/Features.md

from hermes.

longlho avatar longlho commented on April 26, 2024

Ok looks like those 2 combined should be future-proofing Intl or any future ES spec changes/polyfill interop. Polyfills are also used to correct buggy native implementations AND unsupported locales which has a fairly long release cycle as well you already mentioned.

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024

import is itself polyfilled, so people can still use it for those purposes. They just can't do it dynamically.

from hermes.

longlho avatar longlho commented on April 26, 2024

@mhorowitz can you provide more details?

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024

@longlho About what exactly? the import polyfill?

from hermes.

longlho avatar longlho commented on April 26, 2024

The can't do it dynamically part? Does that mean static import works but not dynamic import?

from hermes.

mhorowitz avatar mhorowitz commented on April 26, 2024

We're a bit out of my domain here. I know you can use import in a React Native application's JavaScript. I believe, but I'm not sure, that this is managed by the metro bundler. What I do know is that from the perspective of Hermes, the JavaScript is precompiled at build time to a single bytecode file, which is included in the APK. Then at runtime, the bytecode file is mmapped into memory and processed by Hermes. This process is designed to be very fast at runtime, which is one of Hermes's startup performance advantages.

Because all the JavaScript is baked into a single mmapped bytecode file, it's not even obvious what dynamic means. Bytecode which hasn't been executed or data which hasn't been referenced may not even be in RAM, because pages in the mmapped file are only read on demand by the operating system.

from hermes.

longlho avatar longlho commented on April 26, 2024

By dynamic I mean the procedure described in the spec. Now the spec doesn't enforce I/O or the fact that the Module Record actually has to be dynamically loaded so it could be static anw. However in the interest of performance, it ideally should be dynamically loaded & evaluated from a JS engine perspective, otherwise you might get a slew of bug reports filed. In this scenario Hermes might have to re-evaluate its loading strategy. Anw sorry for digressing from the initial topic of this thread but I don't see a separate GH issue for dynamic import support 😒

from hermes.

RichardLindhout avatar RichardLindhout commented on April 26, 2024

It would be cool if Hermes could use the underlying native implementations of date so the bundle size would not grow at all for Intl support. In JavascriptCore in iOS Intl works without growing the bundle size. But I guess that won't be an options as Hermes would need to implement the Intl api for every platform.

from hermes.

vonovak avatar vonovak commented on April 26, 2024

I did a small bit of researching on formatting dates using Intl and iOS's NSDateFormatter that I quickly summarized in this tweet: https://twitter.com/vonovak/status/1296454407484256257

I think there is a chance that using Intl, it might be impossible to get the same date formatting iOS would use in date pickers and other places in the system and other apps, so a RN app using Int would display dates a little different from what would be desirable if one really cares about date formatting. A workaround would be making calls across the bridge to get a date formatted (not practical) or create a <Text /> component equivalent that would be used to render dates only (not straightforward).

Apologies if you find this a little off the topic πŸ™‚

from hermes.

longlho avatar longlho commented on April 26, 2024

I personally find that a bit hard to believe since they're all backed by libicu

from hermes.

RichardLindhout avatar RichardLindhout commented on April 26, 2024

With Turbomodules asking the native OS what the date format would maybe be just as fast as using a polyfill. Would be interesting because that way no big bundle sizes are required

from hermes.

SrBrahma avatar SrBrahma commented on April 26, 2024

Is DateTimeFormat already supported?

from hermes.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.