Issue
Closed: This issue is because of a bug on my side. See the answer for more information.
I am testing a custom JavaScript runtime on android, with a sample React Native application (specifically: Zulip Mobile). The runtime supports most modern JavaScript features, but it lacks support for Intl
.
However, the RN app uses Intl
via react-intl
's IntlProvider
type (see here). To continue testing with this app, I would need to polyfill the API myself, but none of my tries succeeded in putting the polyfilled Intl
into global variables.
import { IntlProvider, IntlContext } from 'react-intl';
// ...
export default function TranslationProvider(props: Props): Node {
const { children } = props;
const language = useGlobalSelector(state => getGlobalSettings(state).language);
return (
<IntlProvider locale={language} textComponent={Text} messages={messages[language]}>
<TranslationContextTranslator>{children}</TranslationContextTranslator>
</IntlProvider>
);
}
The error stacktrace was:
ReferenceError: 'Intl' is not defined
Component Stack:
in IntlProvider
in Unknown
in RCTView
in Unknown
in L
in Connect(L)
in Unknown
in RNCSafeAreaProvider
in Unknown
in Unknown
in n
in Unknown
in b
in O
in Unknown
in RCTView
in Unknown
in RCTView
in Unknown
in b
Call Stack:
at <anonymous> (index.android.bundle)
at <anonymous> (index.android.bundle)
at <anonymous> (index.android.bundle)
at o (index.android.bundle)
at jt (index.android.bundle)
at ul (index.android.bundle)
at ql (index.android.bundle)
at Fa (index.android.bundle)
at Ua (index.android.bundle)
at La (index.android.bundle)
at Ea (index.android.bundle)
at ft (index.android.bundle)
at Te (index.android.bundle)
at Pe (index.android.bundle)
at notify (index.android.bundle)
at notifyNestedSubs (index.android.bundle)
at f (index.android.bundle)
at b (index.android.bundle)
at <anonymous> (index.android.bundle)
at <anonymous> (index.android.bundle)
at <anonymous> (index.android.bundle)
at <anonymous> (index.android.bundle)
at call (native)
at v (index.android.bundle)
at <anonymous> (index.android.bundle)
at <anonymous> (index.android.bundle)
at call (native)
at v (index.android.bundle)
at o (index.android.bundle)
at <anonymous> (index.android.bundle)
at u (index.android.bundle)
at <anonymous> (index.android.bundle)
at apply (native)
at <anonymous> (index.android.bundle)
at k (index.android.bundle)
at w (index.android.bundle)
at callReactNativeMicrotasks (index.android.bundle)
at value (index.android.bundle)
at <anonymous> (index.android.bundle)
at value (index.android.bundle)
at value (index.android.bundle)
at value (index.android.bundle)
I tried polyfilling the Intl API using both intl
and formatjs
packages from NPM. Neither succeeded, and the error was the same as above.
I do not have any previous experience writing React Native apps (I'm testing the ability of the runtime). My method of polyfilling could be completely wrong -- if that's the case I would like to be kindly pointed out.
// index.js
/* @flow strict-local */
// React Navigation requires this react-native-gesture-handler import,
// as the very first import of this entry-point file. See our #5373.
import 'react-native-gesture-handler';
import IntlPolyfill from 'intl'; // <-
import { AppRegistry } from 'react-native';
import ZulipMobile from './src/ZulipMobile';
if (!globalThis.Intl) {
globalThis.Intl = IntlPolyfill;
}
AppRegistry.registerComponent('ZulipMobile', () => ZulipMobile);
// index.js
/* @flow strict-local */
// React Navigation requires this react-native-gesture-handler import,
// as the very first import of this entry-point file. See our #5373.
import 'react-native-gesture-handler';
import { AppRegistry } from 'react-native';
import ZulipMobile from './src/ZulipMobile';
// polyfills
import '@formatjs/intl-getcanonicallocales/polyfill';
import '@formatjs/intl-locale/polyfill';
import '@formatjs/intl-displaynames/polyfill';
import '@formatjs/intl-displaynames/locale-data/en';
if (!global.Intl) {
throw new Error('Intl is missing???');
}
AppRegistry.registerComponent('ZulipMobile', () => ZulipMobile);
I have also reviewed and tried the answers under these questions, but also didn't succeed:
- Using Intl properly in Android React Native app
- React-Native and Intl polyfill required on Android device
- Intl polyfills for React Native 0.63 and hermes
Solution
It was a bug on my side.
Specifically, it was the script not updating at all when I was editing, for some reason.
In order to build and profile the app with Android Studio, I had to bundle the script manually, and then put it in the android app assets. Although the build script would run the bundler again while building for release, the result cannot be recognized by the android app assets, and I needed to build it manually.
npx react-native bundle \
--platform android \
--dev false \
--entry-file index.js \
--bundle-output android/app/src/main/assets/index.android.bundle \
--assets-dest test-assets
However, I totally forgot the fact that the script was there while I was trying to fix the bug. Having found that the bundled script was not updated, I just need to manually run the bundler on each build.
As of polyfilling Intl
, this is the piece of code (and packages) I used:
// index.js
import '@formatjs/intl-getcanonicallocales/polyfill';
import '@formatjs/intl-locale/polyfill';
import '@formatjs/intl-numberformat/polyfill';
import '@formatjs/intl-numberformat/locale-data/en';
import '@formatjs/intl-datetimeformat/polyfill';
import '@formatjs/intl-datetimeformat/locale-data/en';
import '@formatjs/intl-pluralrules/polyfill';
import '@formatjs/intl-pluralrules/locale-data/en';
import '@formatjs/intl-relativetimeformat/polyfill';
import '@formatjs/intl-relativetimeformat/locale-data/en';
import '@formatjs/intl-displaynames/polyfill';
Answered By - Rynco Maekawa
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.