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

Async APIs for Intl loading #434

Open
littledan opened this issue May 6, 2020 · 5 comments
Open

Async APIs for Intl loading #434

littledan opened this issue May 6, 2020 · 5 comments
Labels
c: meta Component: intl-wide issues Data Related to locale data Proposal Larger change requiring a proposal s: discuss Status: TG2 must discuss to move forward

Comments

@littledan
Copy link
Member

There's a lot of data in CLDR (or whatever other locale data an Intl implementation uses), so much that it doesn't work in practice to ship it all with JS implementations. For example:

  • Engines generally support some locales and not others. The lack of support for particular locales is a very frequently filed issue against certain engines (e.g., V8/Chromium)
  • Intl.NumberFormat includes just certain units, not all of them Units: Spec and Data Size proposal-unified-intl-numberformat#39
  • Intl.DisplayNames doesn't include all the strings that it might include (though there are non-data-size reasons for this as well, having to do with alignment with Temporal).
  • We can't begin to consider including emoji-related data, even though it'd be useful for emoji pickers

Could we address some of this by creating async APIs which have the chance to fetch the relevant data, in a way provided by the engine? As a straw-person, each Intl constructor could have a create static method, which returns a Promise, which resolves with the instance, based on a host hook to fetch the data. Usage could look like this:

let displayNames = await Intl.DisplayNames.create("fr", {type: "emoji-keywords"})
displayNames.of("🦻")  // ["accessibilité", "malentendant", "oreille appareillée", "prothèse auditive"]

One risk is that async APIs would be open to timing attacks: if the data is cached locally, you could see whether someone else has requested this locale data by checking how long it takes for this API to return. Browsers have adopted "double-keyed caching" to cache based on not just the URL of the resource but also the origin which referred it. However, if the fetch is going to a browser-provided resource, I don't know whether this would reveal significantly interesting information to constitute a meaningful attack. We should check with a security expert (which I am not) before proceeding, to be sure.

@sffc
Copy link
Contributor

sffc commented May 6, 2020

I definitely agree with this direction. This issue has a lot of overlap with #210, but is more specific: async APIs is one piece that will be required before moving onto the full-stack data loading problem.

The model of adding an async method like .create() to Intl objects is good. Since all of the settings are available in the constructor, this operation will be able to load all required data for that specific operation (for example, only load time zone names if the skeleton requires it).

A small number of other Intl functions, like Intl.Locale.prototype.maximize, may also want to be async, unless we want to pre-load the likely subtags in the constructor just in case the programmer wants to use them later.

@sffc
Copy link
Contributor

sffc commented May 6, 2020

@littledan
Copy link
Member Author

I think async constructors are a cool idea. At the same time, I think this would work in Intl just fine as a static async factor method, if async constructors aren't a thing when we want to move this to Stage 3.

@littledan
Copy link
Member Author

It's interesting to mention #210. I guess I was imagining these on separate axes--that if you use the data-driven API, you'd provide that data synchronously to the constructor. At the same time, practically speaking, you may fetch that data asynchronously, so they might end up looking analogous to an application developer using a framework which provides that data.

Nit: I'd like to stick with the pattern of making each method either always-sync or always-async. So, if we want to make Intl.Locale.prototype.maximize load data sometimes, I'd suggest that the loading version be a separate method name. Either way, we have to solve a lot of the same problems between async instance methods and async constructors/factory functions, e.g., developing a model we're OK with for caching, where the data comes from, etc.

@sffc sffc added c: meta Component: intl-wide issues Data Related to locale data Proposal Larger change requiring a proposal s: discuss Status: TG2 must discuss to move forward labels Jun 5, 2020
@eemeli
Copy link
Member

eemeli commented Aug 13, 2020

A while ago, I put together an idea of a proposal for this, but never really took it anywhere: https://github.com/eemeli/proposal-intl-loadlocales

In other words, a big +1 on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: meta Component: intl-wide issues Data Related to locale data Proposal Larger change requiring a proposal s: discuss Status: TG2 must discuss to move forward
Projects
Status: Other Issues
Development

No branches or pull requests

3 participants