diff --git a/android/app/build.gradle b/android/app/build.gradle
index 74396642fdec..234a3b244955 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -150,8 +150,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
- versionCode 1001008106
- versionName "1.0.81-6"
+ versionCode 1001008107
+ versionName "1.0.81-7"
}
splits {
abi {
diff --git a/ios/ExpensifyCash/Info.plist b/ios/ExpensifyCash/Info.plist
index da951d33c0b8..a47caf0ec781 100644
--- a/ios/ExpensifyCash/Info.plist
+++ b/ios/ExpensifyCash/Info.plist
@@ -30,7 +30,7 @@
CFBundleVersion
- 1.0.81.6
+ 1.0.81.7
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/ExpensifyCashTests/Info.plist b/ios/ExpensifyCashTests/Info.plist
index 326c3d0e2fe0..853346d9591c 100644
--- a/ios/ExpensifyCashTests/Info.plist
+++ b/ios/ExpensifyCashTests/Info.plist
@@ -19,6 +19,6 @@
CFBundleSignature
????
CFBundleVersion
- 1.0.81.6
+ 1.0.81.7
diff --git a/package-lock.json b/package-lock.json
index 70e58fc525ff..80ecc9197d33 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "expensify.cash",
- "version": "1.0.81-6",
+ "version": "1.0.81-7",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index dace87611ca3..9574555c0ce8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "expensify.cash",
- "version": "1.0.81-6",
+ "version": "1.0.81-7",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "Expensify.cash is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
diff --git a/src/App.js b/src/App.js
index 0ac8e0ac8e60..3fd37312645e 100644
--- a/src/App.js
+++ b/src/App.js
@@ -4,6 +4,7 @@ import {SafeAreaProvider} from 'react-native-safe-area-context';
import CustomStatusBar from './components/CustomStatusBar';
import ErrorBoundary from './components/ErrorBoundary';
import Expensify from './Expensify';
+import {LocaleContextProvider} from './components/withLocalize';
LogBox.ignoreLogs([
// Basically it means that if the app goes in the background and back to foreground on Android,
@@ -17,10 +18,12 @@ LogBox.ignoreLogs([
const App = () => (
-
-
-
-
+
+
+
+
+
+
);
diff --git a/src/components/withLocalize.js b/src/components/withLocalize.js
index 435a2df71629..4eb5ca18d6d8 100755
--- a/src/components/withLocalize.js
+++ b/src/components/withLocalize.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, {createContext, forwardRef} from 'react';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import getComponentDisplayName from '../libs/getComponentDisplayName';
@@ -9,6 +9,8 @@ import {toLocalPhone, fromLocalPhone} from '../libs/LocalePhoneNumber';
import numberFormat from '../libs/numberFormat';
import CONST from '../CONST';
+const LocaleContext = createContext(null);
+
const withLocalizePropTypes = {
/** Returns translated string for given locale and phrase */
translate: PropTypes.func.isRequired,
@@ -29,124 +31,122 @@ const withLocalizePropTypes = {
fromLocalPhone: PropTypes.func.isRequired,
};
-export default (WrappedComponent) => {
- const propTypes = {
- /** The user's preferred locale e.g. 'en', 'es-ES' */
- preferredLocale: PropTypes.string,
-
- /** Passed ref from whatever component is wrapped in the HOC */
- forwardedRef: PropTypes.oneOfType([
- PropTypes.func,
- PropTypes.shape({current: PropTypes.instanceOf(React.Component)}),
- ]),
- };
-
- const defaultProps = {
- preferredLocale: CONST.DEFAULT_LOCALE,
- forwardedRef: undefined,
- };
-
- class WithLocalize extends React.Component {
- constructor(props) {
- super(props);
-
- this.translate = this.translate.bind(this);
- this.numberFormat = this.numberFormat.bind(this);
- this.timestampToRelative = this.timestampToRelative.bind(this);
- this.timestampToDateTime = this.timestampToDateTime.bind(this);
- this.fromLocalPhone = this.fromLocalPhone.bind(this);
- this.toLocalPhone = this.toLocalPhone.bind(this);
- }
-
- /**
- * @param {String} phrase
- * @param {Object} [variables]
- * @returns {String}
- */
- translate(phrase, variables) {
- return translate(this.props.preferredLocale, phrase, variables);
- }
-
- /**
- * @param {Number} number
- * @param {Intl.NumberFormatOptions} options
- * @returns {String}
- */
- numberFormat(number, options) {
- return numberFormat(this.props.preferredLocale, number, options);
- }
-
- /**
- * @param {Number} timestamp
- * @returns {String}
- */
- timestampToRelative(timestamp) {
- return DateUtils.timestampToRelative(this.props.preferredLocale, timestamp);
- }
-
- /**
- * @param {Number} timestamp
- * @param {Boolean} [includeTimezone]
- * @returns {String}
- */
- timestampToDateTime(timestamp, includeTimezone) {
- return DateUtils.timestampToDateTime(
- this.props.preferredLocale,
- timestamp,
- includeTimezone,
- );
- }
-
- /**
- * @param {Number} number
- * @returns {String}
- */
- toLocalPhone(number) {
- return toLocalPhone(this.props.preferredLocale, number);
- }
-
- /**
- * @param {Number} number
- * @returns {String}
- */
- fromLocalPhone(number) {
- return fromLocalPhone(this.props.preferredLocale, number);
- }
-
- render() {
- return (
-
- );
- }
+const localeProviderPropTypes = {
+ /** The user's preferred locale e.g. 'en', 'es-ES' */
+ preferredLocale: PropTypes.string,
+
+ /* Actual content wrapped by this component */
+ children: PropTypes.node.isRequired,
+};
+
+const localeProviderDefaultProps = {
+ preferredLocale: CONST.DEFAULT_LOCALE,
+};
+
+class LocaleContextProvider extends React.Component {
+ constructor(props) {
+ super(props);
+
+ /* The context this component exposes to consumers */
+ this.translateUtils = {
+ translate: this.translate.bind(this),
+ numberFormat: this.numberFormat.bind(this),
+ timestampToRelative: this.timestampToRelative.bind(this),
+ timestampToDateTime: this.timestampToDateTime.bind(this),
+ fromLocalPhone: this.fromLocalPhone.bind(this),
+ toLocalPhone: this.toLocalPhone.bind(this),
+ };
}
- WithLocalize.propTypes = propTypes;
- WithLocalize.defaultProps = defaultProps;
+ /**
+ * @param {String} phrase
+ * @param {Object} [variables]
+ * @returns {String}
+ */
+ translate(phrase, variables) {
+ return translate(this.props.preferredLocale, phrase, variables);
+ }
+
+ /**
+ * @param {Number} number
+ * @param {Intl.NumberFormatOptions} options
+ * @returns {String}
+ */
+ numberFormat(number, options) {
+ return numberFormat(this.props.preferredLocale, number, options);
+ }
- const withForwardedRef = React.forwardRef((props, ref) => (
- // eslint-disable-next-line react/jsx-props-no-spreading
-
+ /**
+ * @param {Number} timestamp
+ * @returns {String}
+ */
+ timestampToRelative(timestamp) {
+ return DateUtils.timestampToRelative(this.props.preferredLocale, timestamp);
+ }
+
+ /**
+ * @param {Number} timestamp
+ * @param {Boolean} [includeTimezone]
+ * @returns {String}
+ */
+ timestampToDateTime(timestamp, includeTimezone) {
+ return DateUtils.timestampToDateTime(
+ this.props.preferredLocale,
+ timestamp,
+ includeTimezone,
+ );
+ }
+
+ /**
+ * @param {Number} number
+ * @returns {String}
+ */
+ toLocalPhone(number) {
+ return toLocalPhone(this.props.preferredLocale, number);
+ }
+
+ /**
+ * @param {Number} number
+ * @returns {String}
+ */
+ fromLocalPhone(number) {
+ return fromLocalPhone(this.props.preferredLocale, number);
+ }
+
+ render() {
+ return (
+
+ {this.props.children}
+
+ );
+ }
+}
+
+LocaleContextProvider.propTypes = localeProviderPropTypes;
+LocaleContextProvider.defaultProps = localeProviderDefaultProps;
+
+const Provider = withOnyx({
+ preferredLocale: {
+ key: ONYXKEYS.NVP_PREFERRED_LOCALE,
+ },
+})(LocaleContextProvider);
+
+Provider.displayName = 'withOnyx(LocaleContextProvider)';
+
+export default function withLocalize(WrappedComponent) {
+ const WithLocalize = forwardRef((props, ref) => (
+
+ {/* eslint-disable-next-line react/jsx-props-no-spreading */}
+ { translateUtils => }
+
));
- withForwardedRef.displayName = `withLocalize(${getComponentDisplayName(WrappedComponent)})`;
+ WithLocalize.displayName = `withLocalize(${getComponentDisplayName(WrappedComponent)})`;
- return withOnyx({
- preferredLocale: {
- key: ONYXKEYS.NVP_PREFERRED_LOCALE,
- },
- })(withForwardedRef);
-};
+ return WithLocalize;
+}
export {
withLocalizePropTypes,
+ Provider as LocaleContextProvider,
};