How to add multilingualism to my application using i18n React - i18next

import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Home from './routes/Home';
import Pricing from './routes/Pricing';
import Portfolio from './routes/Portfolio';
import Booking from './routes/Booking';
import { withTranslation } from 'react-i18next';
import i18next from 'i18next';
import { initReactI18next } from 'react-i18next';
import en from './locales/en.json';
import fr from './locales/he.json';
import LanguageSwitcher from './LanguageSwitcher';
class App extends React.Component {
componentDidMount() {
i18next
.use(initReactI18next)
.init({
resources: {
en: {
translation: en
},
he: {
translation: he
}
},
lng: 'en',
fallbackLng: 'en',
interpolation: {
escapeValue: false
}
});
}
render() {
const { t } = this.props;
return (
<>
<LanguageSwitcher />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/pricing" element={<Pricing />} />
<Route path="/portfolio" element={<Portfolio />} />
<Route path="/booking" element={<Booking />} />
</Routes>
</>
);
}
}
export default withTranslation()(App);

If you're using the withTranslation HOC, you may have a look at this example:
// use hoc for class based components
class LegacyWelcomeClass extends Component {
render() {
const { t } = this.props;
return <h2>{t('title')}</h2>;
}
}
const Welcome = withTranslation()(LegacyWelcomeClass);
I would also suggest to checkout this guide about react-i18next.

Related

react-native Unable to retrieve params via deep link

unable to pass params from deep link. getting undefined when running:
npx uri-scheme open [prefix]://news/3 --android
NewsScreen.js
import React from 'react';
const NewsScreen = ({ route, navigation }) => {
console.log(route.params); // undefined
};
Linking.js
import LINKING_PREFIXES from 'src/shared/constants';
export const linking = {
prefixes: LINKING_PREFIXES,
config: {
screens: {
Home: {
screens: {
News: {
path: 'news/:id?',
parse: {
id: id => `${id}`,
},
},
},
},
NotFound: '*',
},
},
};
Router.js
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import {useAuth} from 'src/contexts/AuthContext';
import {Loading} from 'src/components/Loading';
import {AppStack} from './AppStack';
import {AuthStack} from './AuthStack';
import {GuestStack} from './GuestStack';
import SplashScreen from 'src/screens/guest/SplashScreen';
import linking from './Linking.js';
export const Router = () => {
const {authData, loading, isFirstTime, appBooting} = useAuth();
if (loading) {
return <Loading />;
}
const loadRoutes = () => {
if (appBooting) {
return <SplashScreen />;
}
if (isFirstTime) {
return <GuestStack />;
}
if (!authData || !authData.name || !authData.confirmed) {
return <AuthStack />;
}
return <AppStack />;
};
return <NavigationContainer>{loadRoutes()}</NavigationContainer>;
};
AppStack.js
import React from 'react';
import {createDrawerNavigator} from '#react-navigation/drawer';
import {SpeedNewsStack} from 'src/routes/NewsStack';
const Drawer = createDrawerNavigator();
export const AppStack = () => {
return (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={NewsStack} />
</Drawer.Navigator>
);
};
NewsStack.js
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import SpeedNewsScreen from 'src/screens/NewsScreen';
const Stack = createStackNavigator();
export const NewsStack = () => {
return (
<Stack.Navigator>
<Stack.Screen name="News" component={NewsScreen} />
</Stack.Navigator>
);
};

react native, how to jump page in network request

I want to jump to the login page when the server returns a 401 status code,Where should i set
my app.js:
...
import React, { Component } from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import Test from './pages/test'
import Login from './pages/login'
...
const Stack = createStackNavigator();
class App extends Component{
render(){
return(
<NavigationContainer>
<Stack.Navigator initialRouteName="Test" headerMode="none">
<Stack.Screen name="Test" component={Test} />
<Stack.Screen name="Login" component={Login} />
...
</Stack.Navigator>
</NavigationContainer>
)
}
}
export default App ;
I have a request.js to handle the all request
every page will use this axios instance to send a request
For example
/pages/test
import {test} from './request.js'
import React, {Component} from 'react';
export default class Test extends Component {
componentDidMount(){
test()
}
}
request.js
import axios from 'axios';
const instance = axios.create({
baseURL: 'http://192.168.10.10:51000',
});
instance.interceptors.response.use(
(response) => {
return response;
},
(error) => {
if(error.response.status === 401){
/*
*** jump page
*/
}
return Promise.reject(error);
},
);
export function test() {
return instance.get('/test');
}
first,Create a new file named RootNavigation.js:
import React from 'react';
export const navigationRef = React.createRef();
export function navigate(name, params) {
navigationRef.current?.navigate(name, params);
}
and then,Import in app.js,Then add ref={navigationRef} in the NavigationContainer of app.js
import { navigationRef } from './RootNavigation';
// ...
class App extends Component{
render(){
return(
<NavigationContainer ref={navigationRef}>
</NavigationContainer>
)
}
}
Finally, modify request.js like this
import * as RootNavigation from './RootNavigation';
// ...
if(error.response.status === 401){
RootNavigation.navigate('Login');
}
done,It works

React Native props from App.js through react-navigation to Screen not working

i tried first steps with Theming in react-native with react-native-paper but the first step is not working.
AppViewContainer
export default compose(
lifecycle({
componentDidMount() {
if (Platform.OS === 'android') {
// eslint-disable-next-line no-unused-expressions
UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(true);
}
},
}),
)(AppView);
AppView.js
export default function App() {
return(
<PaperProvider theme={theme}>
<Navigator onNavigationStateChange={() => { }} uriPrefix="/app" />
</PaperProvider>
)
}
Navigator
export default createAppContainer( createSwitchNavigator({
AuthLoading: LoadingScreen,
App: AppStack,
Tabs: TabNavigator,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}
));
in next step my HomeScreen is coming but there
this.props.theme //undefined
It seems the props not going through react navigation. How i can tell the Navigator to loop it through?
Many Thx
My Solution was now:
App.tsx - including redux
import React from 'react';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { AppearanceProvider } from 'react-native-appearance';
import { Provider } from 'react-redux';
import { Main } from './src/main';
import store from "./src/store"; //redux store
export default function App() {
return (
<Provider store={store}>
<SafeAreaProvider>
<AppearanceProvider>
<Main />
</AppearanceProvider>
</SafeAreaProvider>
</Provider>
);
}
Main.tsx
import React from 'react';
import {
Provider as PaperProvider,
DefaultTheme,
DarkTheme,
} from 'react-native-paper';
import { I18nManager } from 'react-native';
import * as Updates from 'expo-updates';
import { useColorScheme } from 'react-native-appearance';
import { PreferencesContext } from './context/preferencesContext';
import { RootNavigator } from './rootNavigator';
...
return (
<PreferencesContext.Provider value={preferences}>
<PaperProvider
theme={
theme === 'light'
? {
...DefaultTheme,
colors: { ...DefaultTheme.colors,
primary: 'red',
background: '#f8f8f8',
listbg: '#ffffff',
bg: require('../assets/splash.png')
},
}
: {
...DarkTheme,
colors: { ...DarkTheme.colors,
primary: '#1ba1f2',
listbg: 'rgba(255, 255, 255, 0.1)',
bg: require('../assets/splash.png')
},
}
}
>
<RootNavigator />
</PaperProvider>
</PreferencesContext.Provider>
);
};
now u can use 'theme' in every function component with global defined values and switch between dark and light mode.
const theme = useTheme(); // imported from react-native-paper
The complete example found on github here: https://github.com/Trancever/twitterClone
if this info was useful, vote up. thx.

I can't navigate without the navigation prop of react-navigation with react-i18next container

I apply the navigation example without the navigation prop of the react-navigations docs (NavigationService), but I can't make it work with react-i18next.
I applied the example of the documentation https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html in my code:
// App.js
import React from 'react';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/lib/integration/react';
import { createAppContainer } from 'react-navigation';
import { I18nextProvider, withNamespaces } from 'react-i18next';
import { persistor, store } from './src/store';
import I18n from './src/localization';
import Navigation from './src/navigation';
import NavigationService from './src/navigation/NavigationService';
import Loader from './src/screens/components/Loader';
class NavigationStack extends React.Component {
static router = Navigation.router;
render() {
const { t } = this.props;
return <Navigation screenProps={{ t, I18n }} {...this.props} />;
}
};
const ReloadNavOnLanguageChange = withNamespaces(['common', 'server'], {
bindI18n: 'languageChanged',
bindStore: false,
})(createAppContainer(NavigationStack));
export default class App extends React.Component {
...
render() {
return (
<Provider store={store}>
<PersistGate loading={<Loader />} persistor={persistor}>
<I18nextProvider i18n={ I18n } >
<ReloadNavOnLanguageChange ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef);
}} />
</I18nextProvider>
</PersistGate>
</Provider>
);
};
};
// Navigation.js
...
export default Navigation = createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
Login: LoginScreen,
App: AppScreen
},
{
initialRouteName: 'AuthLoading'
}
);
// NavigationService.js
Apply the same code that's in https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html
// Any JS module of my project (actions, helpers, components, etc.)
import NavigationService from 'path-to-NavigationService.js';
...
NavigationService.navigate('Login');
When the authorization token is validated and the result is negative, the login screen must be opened (NavigationService.navigate('Login')) but it returns the error _navigator.dispatch is not a function in NavigationService.js:
const navigate = (routeName, params) => {
// DISPATCH ERROR
   _navigator.dispatch(
     NavigationActions.navigate({
       routeName,
       params
     })
   );
};
Dependencies:
react 16.5.0
react-native 57.1
react-i18next 9.0.0
react-navigation 3.1.2
Any suggestion? Has anyone else found this scenario?
Using the innerRef option of the withNamespaces hoc of react-i18next instead of passing the function through the ref property of the root component… AS THE DOCUMENTATION OF REACT-I18NETX SAYS!
// App.js
...
const ReloadNavOnLanguageChange = withNamespaces(['common', 'server'], {
bindI18n: 'languageChanged',
bindStore: false,
innerRef: (ref) => NavigationService.setTopLevelNavigator(ref)
})(createAppContainer(NavigationStack));
export default class App extends React.Component {
...
render() {
return (
...
<ReloadNavOnLanguageChange />
...
);
};
}

Redux-Saga Component Setup

I'm having trouble getting redux-saga to work. I'm thinking the issue lies somewhere between the saga_component.js and saga_screen.js files. It may be I'm not using the correct syntax to map out the API?
I'm getting eror:
"undefined is not a function (near '...ConnectData.map' ".
This is located in the Saga_component.js file.
I've been working on this for a while now, not sure what to adjust at this point. Would greatly appreciate some guidance. This is a link to the repo. All screens and components can be found in the 'src' file.
App.js File
import React from "react";
import Setup from "./src/boot/setup";
import { Provider } from 'react-redux';
import store from './src/store';
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<Setup/>
</Provider>
);
}}
Store.js
import {createStore, applyMiddleware} from 'redux';
import createSagaMiddleware from 'redux-saga';
import AllReducers from '../src/reducers';
import rootSaga from '../src/saga';
const sagaMiddleware = createSagaMiddleware()
const store = createStore(
AllReducers,
applyMiddleware(sagaMiddleware));
sagaMiddleware.run(rootSaga);
export default store;
saga.js
import { call, put, takeEvery, takeLatest } from "redux-saga/effects";
import { REQUEST_API_DATA, receiveApiData } from "./actions";
import { fetchData } from "./api";
function* getApiData(action) {
try {
// do api call
const data = yield call(fetchData);
yield put(receiveApiData(data));
} catch (e) {
console.log(e);
}
}
export default function* rootSaga() {
yield takeLatest(REQUEST_API_DATA, getApiData);
}
data.js (this is the reducer)
import { RECEIVE_API_DATA } from "../actions";
export default (state = {}, { type, data }) => {
switch (type) {
case RECEIVE_API_DATA:
return data;
default:
return state;
}
};
actionsCreators.js
import { REQUEST_API_DATA, RECEIVE_API_DATA} from './types';
export const requestApiData = () => {
return {
type: REQUEST_API_DATA
}
};
export const receiveApiData = (data) => {
return {
type: RECEIVE_API_DATA,
data
}
};
saga_component.js
import React from "react";
import { AppRegistry, View, StatusBar } from "react-native";
import { Container, Body, Content, Header, Left, Right, Icon, Title,
Input, Item, Label, Button, Text } from "native-base";
export default class SagaComponent extends React.Component {
renderList() {
const ConnectData = this.props.data;
return ConnectData.map((data) => {
return (
<View style={{width: 280}}>
<Text style={styles.TextLight}><Text style={styles.TextDark}>Dest City:</Text> {data.name}</Text>
<Text style={styles.TextLight}><Text style={styles.TextDark}>ETA:</Text> {data.email}</Text>
</View>
);
});
}
render() {
return (
<View>
<Label>Username</Label>
{this.renderList()}
</View>
);
}
}
saga_screen.js
import React, { Component } from "react";
import { Container, Text, Button } from "native-base";
import { View, StatusBar } from "react-native";
import { connect } from "react-redux";
import styles from "../styles/styles";
import { bindActionCreators } from "redux";
import { requestApiData } from "../actions";
import SagaComponent from '../components/saga_component';
class SagaScreen extends React.Component {
render() {
return (
<Container style={styles.container}>
<View style={{marginTop: 50 }}>
<SagaComponent data={this.props.data}/>
</View>
<Button block style={styles.Home_btns}
onPress={() => this.props.navigation.navigate("Home")}>
<Text>Home</Text>
</Button>
</Container>
);
}
}
function mapStateToProps(state) {
return {
data: state.data,
};
}
const mapDispatchToProps = dispatch =>
bindActionCreators({ requestApiData }, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(SagaScreen);
Api.js
export const fetchData = async () => {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
const data = await response.json();
return data;
} catch (e) {
console.log(e);
}
};
index.js(reducer index.js file)
import { combineReducers } from 'redux';
import data from "./data";
const AllReducers = combineReducers({
data,
});
export default AllReducers;
It looks like the problem could be in your reducer. Instead of returning data you should return { data };
Also, as an aside, you might want to guard against falsey data in your saga_component (ConnectData || []).map((data) => {