Giter Club home page Giter Club logo

Comments (15)

joshswan avatar joshswan commented on August 24, 2024

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.

willymulyana avatar willymulyana commented on August 24, 2024

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.

joshswan avatar joshswan commented on August 24, 2024

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.

AndersGerner avatar AndersGerner commented on August 24, 2024

@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:
Screenshot

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.

joshswan avatar joshswan commented on August 24, 2024

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.

AndersGerner avatar AndersGerner commented on August 24, 2024

@joshswan

New screenshot

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.

AndersGerner avatar AndersGerner commented on August 24, 2024

@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.

joshswan avatar joshswan commented on August 24, 2024

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.

AndersGerner avatar AndersGerner commented on August 24, 2024

screen shot 2018-04-07 at 19 58 54

screen shot 2018-04-07 at 19 59 00

@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.

joshswan avatar joshswan commented on August 24, 2024

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.

AndersGerner avatar AndersGerner commented on August 24, 2024

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.

joshswan avatar joshswan commented on August 24, 2024

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.

AndersGerner avatar AndersGerner commented on August 24, 2024

@joshswan AWESOME!

I have swapped the FormattedWrapper with a FormattedProvider and then it start complaining about context.changedBits.
See:
screen shot 2018-04-09 at 11 23 57

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.

joshswan avatar joshswan commented on August 24, 2024

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.

AndersGerner avatar AndersGerner commented on August 24, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.