I have an app that created by awesome React-native
and my layout designed to be in RTL mode. I\'ve set up an option for forcing the layout to be RT
Make sure that on iOS, next to having added all relevant RTL locales to your Xcode project (e.g. Arabic). You should also make sure that your .ipa contains .lproj folders for each locale. Otherwise iOS doesn't pick up on the supported languages.
This is a common issue in React Native projects where you don't typically write a lot of Swift/Obj-C code & most of the translations happen in JavaScript (apart maybe from some stuff in you Info.plist).
I had the same problem and solved it by invoking forceRTL
in MainApplication.java
in the onCreate
method.
...
import com.facebook.react.modules.i18nmanager.I18nUtil;
...
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance();
sharedI18nUtilInstance.forceRTL(this,true);
sharedI18nUtilInstance.allowRTL(this, true);
}
...
On IOS add in the AppDelegate.m
...
NSURL *jsCodeLocation; // this probably already exists!
[[RCTI18nUtil sharedInstance] allowRTL:YES];
[[RCTI18nUtil sharedInstance] forceRTL:YES];
...
Source
I went through the same issue this helped me. This is abit modified answer without the need to use redux.
First you check current state with I18nManager.isRTL
then forceRTL if not and restart with react-native-restart.
constructor(props) {
//Force RTL
if(!I18nManager.isRTL){
I18nManager.forceRTL(true);
RNRestart.Restart();
}
}
Thats because you should use I18nManager with try and catch! it needs "await" to do his job.
try {
I18nManager.allowRTL(false);
} catch (e) {
console.log(e);
}
use it like this, and it will work.
After a week finally i found a logicly way to solve this issue with using Redux
& react-native-restart
plugin. I'm also use a nice splash screen to user don't show a restarting progress for this purpose.
So let's dive into code:
Redux action:
export const GET_APP_LAYOUT_DIRECTION = 'GET_APP_LAYOUT_DIRECTION';
export const SET_APP_LAYOUT_DIRECTION = 'SET_APP_LAYOUT_DIRECTION';
export const getAppLayoutDirection = () => ({
type: GET_APP_LAYOUT_DIRECTION,
});
export const setAppLayoutDirection = direction => ({
type: SET_APP_LAYOUT_DIRECTION,
direction
});
Redux Reducer:
import {
GET_APP_LAYOUT_DIRECTION,
SET_APP_LAYOUT_DIRECTION,
} from '../actions/app';
const initialState = {
layout: 'ltr',
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case GET_APP_LAYOUT_DIRECTION:
return {
...state,
};
case SET_APP_LAYOUT_DIRECTION:
return {
...state,
layout: action.direction,
};
default:
return state;
}
};
export default reducer;
Home Screen:
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import RNRestart from 'react-native-restart'; // Import package from node modules
import { getAppLayoutDirection, setAppLayoutDirection } from '../actions/app';
class Home extends PureComponent {
constructor(props) {
super(props);
this.props.dispatch(getAppLayoutDirection());
if(this.props.layout === 'ltr'){
this.props.dispatch(setAppLayoutDirection('rtl'));
RNRestart.Restart();
}
}
componentDidMount() {
if(this.props.layout && this.props.layout === 'rtl'){
SplashScreen.hide();
}
}
}
const mapStateToProps = (state) => {
const { layout } = state.app;
return {
layout
};
}
export default connect(mapStateToProps)(Home);