Comments (15)
Are you using FormattedWrapper
or your own getChildContext
implementation?
With FormattedWrapper
it should work out of the box:
const App = ({ currency, locale }) => (
<FormattedWrapper locale={locale} currency={currency} messages={Messages}>
<App />
</FormattedWrapper>
);
// Redux example
function mapStateToProps(state) {
return {
currency: state.currency,
locale: state.locale,
};
}
export default connect(mapStateToProps)(App);
Basically you just need to update the locale and/or currency props on FormattedWrapper
and that should propagate throughout the app. If you're using your own implementation, check out FormattedWrapper
to see if anything is different. The key is the componentWillReceiveProps
method switching out the Globalize
instance. I see that you were attempting to do that by setting this.context.globalize
to a new instance, but you can't do that directly. You need to update it in the component providing getChildContext
, which FormattedWrapper
does for you when you change the props.
from react-native-globalize.
Thanks for the direction, it really help to fix the problem.
The app setup make it's not straightforward though, It use custom fonts, react navigation, apollo (graphql), and it is an Expo.io project. So my setup become like this:
... (render method portion of App class)
return this.state.fontLoaded ?
<FormattedWrapper locale={this.props.locale.locale} currency="USD" messages={lang.MESSAGES}>
<View style={{paddingTop:24,flex:1}}>
<MainNavigator />
</View>
</FormattedWrapper>
: null
;
}
}
const mapStateToProps = (state) => {
return {
locale: state.locale,
}
}
const ConnectedApp = connect(mapStateToProps)(App);
const AppWithProvider = () => (
<ApolloProvider client={apolloClient} store={store}>
<ConnectedApp />
</ApolloProvider>
)
Expo.registerRootComponent(AppWithProvider);
Maybe it can be put more nicely as I realize I'm not good enough with wrapping things up :)
By the way, I was looking for a method like setLocale("en")
to simply change locale programatically but not exists. I'm not sure if it's possible or can be implemented.
Thanks.
from react-native-globalize.
Based on the example code you posted, your current locale is stored in your redux store. You could therefore easily make an action creator called setLocale
that dispatches and action and sets the locale. That sort of function is outside the scope of this library as the locale can already be changed very simply be changing the prop on FormattedWrapper
. How you manage your locale and other state is not part of this package.
from react-native-globalize.
@joshswan I have tried to archive the same as @willymulyana but even when I tried to switch my RootComponent to a const like your example, I couldn't get it to work. It only works if I add a FormattedWrapper in every component where I need to use the FormattedMessage.
Here is the root component:
... //imports and styles
class RootContainer extends Component {
render() {
const locale = this.props.locale;
console.log("RootLocale",locale);
return (
<ThemeProvider theme={colors}>
<FormattedWrapper locale={locale} messages={messages}>
<Root>
<StatusBar barStyle='light-content' backgroundColor='transparent' translucent />
{ Platform.OS === 'android' && Platform.Version >= 20 ? <StatusBarAndroid /> : null }
<Navigator />
</Root>
</FormattedWrapper>
</ThemeProvider>
);
}
}
const mapStateToProps = (state) => ({
state,
locale: state.Language.language
});
const ConnectedRootContainer = connect(mapStateToProps,null)(RootContainer);
class App extends Component {
render() {
return (
<Provider store={store}>
<ConnectedRootContainer />
</Provider>
);
}
}
export default App;
My locale is changed with Redux, and to show it, I have add a console.log to the RootComponent.
Here is an screenshot of the log:
As mentioned, if I add a FormattedWrapper in my component, then it works:
class MainScreen extends Component {
render() {
return (
<FormattedWrapper locale={this.props.state.Language.language} messages={messages}>
<ContainerView>
<TitleText text={<FormattedMessage
message="Welcome"/>} />
</ContainerView>
</FormattedWrapper>
);
}
}
Same version without the FormattedWrapper:
class MainScreen extends Component {
render() {
return (
<ContainerView>
<TitleText text={<FormattedMessage
message="Welcome"/>} />
</ContainerView>
);
}
}
Am I doing something wrong?
from react-native-globalize.
I don't see anything super obvious, but I just tried a basic setup loosely based on yours and had no issue. So there must be some issue somewhere in your hierarchy. You definitely shouldn't need to put FormattedWrapper
in more than one place. Are you sure you have messages set up for your different locales?
You can also try putting a test component in to see what the current locale is, i.e.
import React, { Component } from 'react';
import { PropTypes as GlobalizePropTypes } from 'react-native-globalize';
import { Text } from 'react-native';
class Test extends Component {
static contextTypes = {
globalize: GlobalizePropTypes.globalizeShape,
}
render() {
return (
<Text>{this.context.globalize.globalize.cldr.locale}</Text>
);
}
}
// The above component will output a Text node with the locale string (e.g. en). Place it somewhere and you can see what's being propagated.
class MainScreen extends Component {
render() {
<ContainerView>
<Test />
</ContainerView>
}
}
from react-native-globalize.
CODE:
import React, { Component } from 'react';
import { StatusBar, Platform, Text } from 'react-native';
import { Provider, connect } from 'react-redux';
import { ThemeProvider } from 'styled-components';
import styled from 'styled-components/native';
import { PropTypes as GlobalizePropTypes, FormattedWrapper } from 'react-native-globalize';
import messages from './Messages';
import store from './store';
import Navigator from './Navigator';
import { colors } from './utils/constants';
const Root = styled.View`
flex: 1;
background-color: ${props => props.theme.BACKGROUND_GREY};
`;
const StatusBarAndroid = styled.View`
height: 24;
background-color: ${props => props.theme.HEADER_DARK};
`;
class Test extends Component {
static contextTypes = {
globalize: GlobalizePropTypes.globalizeShape,
}
render() {
console.log("globalize",this.context.globalize.globalize.cldr.locale);
return (
<Text>{this.context.globalize.globalize.cldr.locale}</Text>
);
}
}
class RootContainer extends Component {
render() {
const locale = this.props.locale;
console.log("RootLocale",locale);
return (
<ThemeProvider theme={colors}>
<FormattedWrapper locale={locale} messages={messages}>
<Root>
<StatusBar barStyle='light-content' backgroundColor='transparent' translucent />
{ Platform.OS === 'android' && Platform.Version >= 20 ? <StatusBarAndroid /> : null }
<Test />
<Navigator />
</Root>
</FormattedWrapper>
</ThemeProvider>
);
}
}
const mapStateToProps = (state) => ({
state,
locale: state.Language.language
});
const ConnectedRootContainer = connect(mapStateToProps,null)(RootContainer);
class App extends Component {
render() {
return (
<Provider store={store}>
<ConnectedRootContainer />
</Provider>
);
}
}
export default App;
Messages:
const messages = {
en: {
Welcome: 'Welcome!!',
Settings: 'Settings'
},
es: {
Welcome: 'Bienvenido',
Settings: 'Configuraciones'
},
};
export default messages;
It is in fact changed :)
I'm using Expo.io by the way, but the lib should be compatible? :)
from react-native-globalize.
@joshswan By the way, it's an open source boilerplate I'm trying to contribute to: https://github.com/ipeedy/react-native-boilerplate
I have gotten my initial version merged, but I would really like to finish it off with the correct change of language :D
from react-native-globalize.
If the locale is propagating correctly, then the issue is probably elsewhere. Try putting the test component in your screen and also try rendering the FormattedMessage
directly in the component instead of as a prop of TitleText
.
from react-native-globalize.
@joshswan It's changed back to "en" right after.
The render code for that screen is:
render() {
return (
<ContainerView>
<TitleText><FormattedMessage
message="Settings"
/></TitleText>
<Text><FormattedMessage
message="Settings"/></Text>
<FormattedMessage
message="Settings"/>
<Test />
<Button text="Change language to es" onPress={() => {this.props.changeLanguage('es')}} />
</ContainerView>
);
}
I really appreciate you trying to help me solve this! Do you have any ideas why this happens?
from react-native-globalize.
I dug into this a bit deeper and the issue here is the use of PureComponent
throughout react-navigation and the flaws of the old context API in React. This should be fixed by the new context API in 16.3, but this package still needs to be updated to support it.
In the meantime, if you remove the FormattedWrapper
in App.js
, the language change in screens/Settings.js
will start working. Basically the workaround would be to put FormattedWrapper
at the top level of the stack after the navigator. There may also be a way of forcing the react-navigation components to update, but I didn't look too deep into that.
from react-native-globalize.
Thanks for the update.
I'm trying to figure out how it works with adding a component to the top of the stack in React-Navigator.
Do you have any input of how to do that? I really think it would be nice, if we could somehow sum up this issue, and add a small "Troubleshoot" part to the README.md :)
from react-native-globalize.
v2.0.0
has just been published which uses the new React Context API. This fixes the issues you've had. However, react >= 16.3.0
is required so you'll need to update expo/react-native based on the versions I see in the repo you linked. Be sure to check out the notes in Releases because there are a couple of breaking changes and new features.
from react-native-globalize.
@joshswan AWESOME!
I have swapped the FormattedWrapper with a FormattedProvider and then it start complaining about context.changedBits.
See:
Code:
class RootContainer extends Component {
render() {
const locale = this.props.locale;
console.log("RootLocale",locale);
return (
<ThemeProvider theme={colors}>
<FormattedProvider locale={locale} messages={messages}>
<Root>
<StatusBar barStyle='dark-content' backgroundColor='transparent' translucent />
{ Platform.OS === 'android' && Platform.Version >= 20 ? <StatusBarAndroid /> : null }
<Navigator />
</Root>
</FormattedProvider>
</ThemeProvider>
);
}
}
App.js:30 is: <FormattedProvider locale={locale} messages={messages}>
All dependencies are updated:
"dependencies": {
"expo": "26.0.0",
"react": "16.3.1",
"react-native": "github:expo/react-native#sdk-26.0.0",
"react-native-globalize": "2.0.0",
"react-navigation": "1.5.11",
"react-redux": "5.0.7",
"redux": "3.7.2",
"redux-logger": "3.0.6",
"redux-thunk": "2.2.0",
"styled-components": "3.2.5"
}
from react-native-globalize.
React >= 16.3.1
and React Native >= 0.55.0
are required. Expo SDK 26 is still on RN 0.54
. Should be an update soon based on their update history.
from react-native-globalize.
For Expo, these are the correct dependency versions:
"dependencies": {
"expo": "26.0.0",
"react": "16.3.0-alpha.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-26.0.0.tar.gz",
"react-native-globalize": "2.0.0",
"react-navigation": "1.5.8",
"react-redux": "5.0.7",
"redux": "3.7.2",
"redux-logger": "3.0.6",
"redux-thunk": "2.2.0",
"styled-components": "3.2.5"
}
Souce: https://blog.expo.io/expo-sdk-v26-0-0-is-now-available-2be6d9805b31
Thank you so much for you help @joshswan !! The app works so great now!
from react-native-globalize.
Related Issues (20)
- Support for getting the currency symbol directly. HOT 6
- Is there a way this library can detect the locale automatically? HOT 2
- Undefinided is not an object <FormattedCurrency> HOT 1
- gulp cldr error HOT 1
- pt-BR is missing HOT 1
- Typescript support HOT 4
- postinstall step failing on CircleCI HOT 2
- typing of `useGlobalize().formatMessage` HOT 1
- [Proposal] useGlobalize generic type HOT 7
- getCurrencySymbol() with GlobalizeProvider throwing TypeError HOT 4
- How to use useGlobalize with class component HOT 4
- formatCurrency always return Error value must be anumber HOT 5
- Fallback locale in case formatMessage failure HOT 3
- Fallback locale does not fork HOT 4
- Customizing Formatted Currency Component HOT 4
- [RNGlobalize] Error processing message welcome HOT 1
- Translate functions strings HOT 1
- Access functions outside components HOT 2
- On demand loading of locales in a web app HOT 2
- Unable to resolve "../../../../../globalize" HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-native-globalize.