andyearnshaw / Intl.js

Compatibility implementation of the ECMAScript Internationalization API (ECMA-402) for JavaScript -- UNMAINTAINED
Other
1.7k stars 215 forks source link

Can't find variable: IntlPolyfill #330

Open koen-dev opened 5 years ago

koen-dev commented 5 years ago

Hi 👋

I recently implemented this package and our Error Reporting tool is catching a lot of the following error for Safari 9.x

ReferenceError
Can't find variable: IntlPolyfill

My implementation is:

async function initIntl() {
    if (typeof Intl === "object") {
        return;
    }
    await Promise.all([
        import("intl"),
        import("intl/locale-data/jsonp/nl"),
        import("intl/locale-data/jsonp/de")
    ]);
}

initIntl().then(() => {
    ReactDOM.render(
        // Render App,
        document.getElementById("root")
    );
});

I can't seem to reproduce the error in BrowserStack but we do get messages from users where they can't load the page but after a refresh it works again.

Any idea what is going wrong and how to fix it?

ghostd commented 5 years ago

Maybe you can try to add try/catch around the await Promise.all et log the stack.

cipater commented 5 years ago

The error is most likely coming from the locale-data being loaded before the main package.

Try:

async function initIntl() {
    if (typeof Intl === "object") {
        return;
    }
    await import("intl");
    await Promise.all([
        import("intl/locale-data/jsonp/nl"),
        import("intl/locale-data/jsonp/de")
    ]);
}
melissafzhang commented 5 years ago

Any updates about whether @cipater's solution fixed it? I'm seeing the same issue.

albingroen commented 4 years ago

This is happening on our platform as well. We get the errors from our bug tracking tool called Sentry, quite often. It seems to mostly happen in Safari browsers although sometimes in Chrome as well. Our initialization of intl looks like this:

if (!global.Intl) {
  Promise.all([import('intl'), import('intl/locale-data/jsonp/sv')]).then(() => run())
} else {
  run()
}

Any further tips or suggestions on how to solve this?

janczizikow commented 4 years ago

I've also experienced this error. I think this might happen because Promise.all resolves first the import('intl/locale-data/jsonp/sv') before the import('intl'). My initialization of intl looked similart to @albingroen . Right now I've changed it to:

if (!window.Intl) {
  import('intl').then(() => {
    Promise.all([import('intl/locale-data/jsonp/sv')]).then(() => run())
  })
} else {
  run()
}
albingroen commented 4 years ago

I've also experienced this error. I think this might happen because Promise.all resolves first the import('intl/locale-data/jsonp/sv') before the import('intl'). My initialization of intl looked similart to @albingroen . Right now I've changed it to:

if (!window.Intl) {
  import('intl').then(() => {
    Promise.all([import('intl/locale-data/jsonp/sv')]).then(() => run())
  })
} else {
  run()
}

Alright, we might give this a shot? Although, is this even working for you?

janczizikow commented 4 years ago

@albingroen I can't tell yet - I just implemented this change :(

cipater commented 4 years ago

@albingroen The promises in Promise.all will run asynchronously/concurrently. So as @janczizikow has surmised, the locale data may sometimes end up loading before the main package, thus causing the error.

My previous example is more or less what I'm using in production, and it has fixed the errors for me. If you can use async functions, await the import of the intl package before loading the rest as in my example. Otherwise, something like @janczizikow solution should work too.

Although, strictly speaking, Promise.all is unnecessary unless you're loading multiple locales. In which case something like import('intl').then(() => import('intl/locale-data/jsonp/sv')).then(run) should suffice.

albingroen commented 4 years ago

@cipater Yeah we actually ended up chaining the imports instead of using Promise.all. This is now in production and we're waiting to see if we get any more errors:

import('intl')
    .then(() => import('intl/locale-data/jsonp/sv'))
    .then(() => run())