React Native Bread supports right-to-left (RTL) layouts for languages like Arabic, Hebrew, Farsi, and Urdu. There are two approaches depending on how you handle RTL in your app.
Native RTL vs code-level RTL
React Native provides two ways to handle RTL:
Native RTL (recommended)
Code-level RTL
Using I18nManager.forceRTL(true) flips the entire app layout at the native level. This is the recommended approach and requires no additional configuration in React Native Bread. // App.tsx or index.js (before app initialization)
import { I18nManager } from 'react-native' ;
// Enable RTL for the entire app
I18nManager . forceRTL ( true );
I18nManager . allowRTL ( true );
With native RTL enabled, React Native Bread toasts will automatically:
Render from right to left
Show the icon on the right side
Align text to the right
Flip swipe gestures appropriately
No rtl config needed - everything works automatically.If you handle RTL in JavaScript without using I18nManager (e.g., manually setting flexDirection based on language), enable the rtl option in your toast config: import { BreadLoaf } from 'react-native-bread' ;
export default function RootLayout () {
const isRTL = useRTL (); // Your RTL detection logic
return (
<>
< Stack />
< BreadLoaf config = { { rtl: isRTL } } />
</>
);
}
This manually reverses:
Icon and text order
Text alignment
Close button position
If you’re using I18nManager.forceRTL(), do not enable the rtl config option. The native RTL behavior will handle everything automatically.
Native RTL setup (recommended)
For full RTL support using I18nManager:
Enable RTL in your app
Add this code before your app initializes (e.g., in index.js or App.tsx): import { AppRegistry , I18nManager } from 'react-native' ;
import App from './App' ;
// Force RTL layout
I18nManager . forceRTL ( true );
I18nManager . allowRTL ( true );
AppRegistry . registerComponent ( 'main' , () => App );
Add BreadLoaf to your layout
No special configuration needed: import { BreadLoaf } from 'react-native-bread' ;
export default function App () {
return (
<>
< NavigationContainer >
< Stack.Navigator />
</ NavigationContainer >
< BreadLoaf />
</>
);
}
Use toasts normally
Toasts will automatically render RTL: import { toast } from 'react-native-bread' ;
toast . success ( 'تم الحفظ' , 'تم حفظ التغييرات بنجاح' );
toast . error ( 'خطأ' , 'حدث خطأ ما' );
Changing I18nManager.forceRTL() requires a full app restart to take effect. It won’t update when hot reloading.
Code-level RTL setup
If you’re not using I18nManager and handle RTL manually:
Detect RTL language
Create a hook or context to detect the current language direction: import { create } from 'zustand' ;
type Language = 'en' | 'ar' | 'he' ;
interface LanguageStore {
language : Language ;
setLanguage : ( lang : Language ) => void ;
isRTL : boolean ;
}
export const useLanguageStore = create < LanguageStore >(( set ) => ({
language: 'en' ,
isRTL: false ,
setLanguage : ( language ) => {
const isRTL = [ 'ar' , 'he' , 'fa' , 'ur' ]. includes ( language );
set ({ language , isRTL });
},
}));
Configure BreadLoaf with RTL
Pass the rtl option to BreadLoaf: import { BreadLoaf } from 'react-native-bread' ;
import { useLanguageStore } from '@/store/language' ;
export default function RootLayout () {
const isRTL = useLanguageStore (( state ) => state . isRTL );
return (
<>
< Stack />
< BreadLoaf config = { { rtl: isRTL } } />
</>
);
}
Use toasts with RTL text
Toasts will now render with RTL layout: import { toast } from 'react-native-bread' ;
import { useLanguageStore } from '@/store/language' ;
export default function Screen () {
const language = useLanguageStore (( state ) => state . language );
const handleSave = () => {
if ( language === 'ar' ) {
toast . success ( 'تم الحفظ' , 'تم حفظ التغييرات بنجاح' );
} else {
toast . success ( 'Saved' , 'Changes saved successfully' );
}
};
return < Button title = "Save" onPress = { handleSave } /> ;
}
Visual differences
When RTL is enabled, toasts display:
Element LTR (default) RTL Icon position Left Right Text alignment Left Right Close button Right Left Content order Icon → Text → Close Close → Text → Icon Swipe direction Right to dismiss Left to dismiss
Dynamic RTL switching
With I18nManager (requires restart)
import { I18nManager , Alert } from 'react-native' ;
import RNRestart from 'react-native-restart' ;
const switchToRTL = () => {
if ( ! I18nManager . isRTL ) {
I18nManager . forceRTL ( true );
Alert . alert (
'RTL Enabled' ,
'App will restart to apply changes' ,
[
{
text: 'Restart Now' ,
onPress : () => RNRestart . Restart (),
},
]
);
}
};
With code-level RTL (dynamic)
import { BreadLoaf } from 'react-native-bread' ;
import { useLanguageStore } from '@/store/language' ;
import { useEffect } from 'react' ;
export default function RootLayout () {
const { isRTL , setLanguage } = useLanguageStore ();
useEffect (() => {
// Detect device language on mount
const deviceLanguage = getDeviceLanguage ();
setLanguage ( deviceLanguage );
}, []);
return (
<>
< Stack />
< BreadLoaf config = { { rtl: isRTL } } />
</>
);
}
RTL with custom toasts
When using custom toasts, you’re responsible for RTL layout in your custom content:
import { toast } from 'react-native-bread' ;
import { View , Text , I18nManager } from 'react-native' ;
const showCustomRTLToast = () => {
const isRTL = I18nManager . isRTL ;
toast . custom (
< View
style = { {
flexDirection: isRTL ? 'row-reverse' : 'row' ,
padding: 16 ,
backgroundColor: '#fff' ,
borderRadius: 12 ,
gap: 12 ,
} }
>
< Image source = { icon } style = { { width: 40 , height: 40 } } />
< View style = { { flex: 1 } } >
< Text style = { { textAlign: isRTL ? 'right' : 'left' } } >
{ isRTL ? 'رسالة مخصصة' : 'Custom message' }
</ Text >
</ View >
</ View >
);
};
Complete RTL example
Here’s a full example with language switching:
import { create } from 'zustand' ;
import { persist } from 'zustand/middleware' ;
type Language = 'en' | 'ar' ;
interface LanguageStore {
language : Language ;
isRTL : boolean ;
setLanguage : ( lang : Language ) => void ;
}
export const useLanguageStore = create < LanguageStore >()()
persist (
( set ) => ({
language: 'en' ,
isRTL: false ,
setLanguage : ( language ) => {
const isRTL = language === 'ar' ;
set ({ language , isRTL });
},
}),
{ name: 'language-storage' }
)
);
import { Stack } from 'expo-router' ;
import { BreadLoaf } from 'react-native-bread' ;
import { useLanguageStore } from '@/store/language' ;
export default function RootLayout () {
const isRTL = useLanguageStore (( state ) => state . isRTL );
return (
<>
< Stack >
< Stack.Screen name = "(tabs)" options = { { headerShown: false } } />
</ Stack >
< BreadLoaf
config = { {
rtl: isRTL ,
position: 'top' ,
} }
/>
</>
);
}
import { View , Text , Button , StyleSheet } from 'react-native' ;
import { toast } from 'react-native-bread' ;
import { useLanguageStore } from '@/store/language' ;
const translations = {
en: {
title: 'Settings' ,
switchToArabic: 'Switch to Arabic' ,
switchToEnglish: 'Switch to English' ,
languageChanged: 'Language changed' ,
languageChangedDesc: 'The app is now in' ,
},
ar: {
title: 'الإعدادات' ,
switchToArabic: 'التبديل إلى العربية' ,
switchToEnglish: 'التبديل إلى الإنجليزية' ,
languageChanged: 'تم تغيير اللغة' ,
languageChangedDesc: 'التطبيق الآن باللغة' ,
},
};
export default function SettingsScreen () {
const { language , setLanguage } = useLanguageStore ();
const t = translations [ language ];
const handleLanguageSwitch = ( newLang : 'en' | 'ar' ) => {
setLanguage ( newLang );
const newT = translations [ newLang ];
toast . success (
newT . languageChanged ,
` ${ newT . languageChangedDesc } ${ newLang === 'ar' ? 'العربية' : 'English' } `
);
};
return (
< View style = { styles . container } >
< Text style = { styles . title } > { t . title } </ Text >
< Button
title = { t . switchToArabic }
onPress = { () => handleLanguageSwitch ( 'ar' ) }
disabled = { language === 'ar' }
/>
< Button
title = { t . switchToEnglish }
onPress = { () => handleLanguageSwitch ( 'en' ) }
disabled = { language === 'en' }
/>
</ View >
);
}
const styles = StyleSheet . create ({
container: {
flex: 1 ,
padding: 16 ,
gap: 12 ,
},
title: {
fontSize: 24 ,
fontWeight: 'bold' ,
marginBottom: 16 ,
},
});
Best practices
Use native RTL when possible I18nManager.forceRTL() provides the most consistent RTL experience and requires no configuration.
Test with real RTL text Arabic and Hebrew text behaves differently than English. Always test with actual RTL content.
Consider text direction RTL languages align text to the right. Ensure your custom toasts handle text alignment properly.
Handle mixed content If you have mixed LTR/RTL content (e.g., English names in Arabic text), use Unicode direction markers.
Troubleshooting
If using I18nManager.forceRTL(), make sure you don’t set rtl: true in the config. Native RTL and code-level RTL should not be used together. If using code-level RTL, verify that rtl: true is being passed to <BreadLoaf />.
RTL text should align to the right. If it’s still left-aligned, you may need to explicitly set text direction: toast . success ( 'مرحبا' , {
titleStyle: { textAlign: 'right' },
descriptionStyle: { textAlign: 'right' },
});
Icon is on the wrong side
If the icon is not flipping, check:
Are you using native RTL (I18nManager.forceRTL())? If yes, don’t set rtl: true in config.
Are you using code-level RTL? If yes, ensure rtl: true is in your BreadLoaf config.
Custom toasts require manual RTL handling in your component: import { I18nManager } from 'react-native' ;
toast . custom (
< View style = { { flexDirection: I18nManager . isRTL ? 'row-reverse' : 'row' } } >
{ /* Your content */ }
</ View >
);
API reference
RTL configuration
interface ToastConfig {
/**
* Enable right-to-left layout at the code level.
*
* Only needed when handling RTL in JavaScript.
* If using native RTL (I18nManager.forceRTL), this option is unnecessary
* as the entire layout flips automatically.
*
* @default false
*/
rtl ?: boolean ;
}
Using with I18nManager
import { I18nManager } from 'react-native' ;
import { BreadLoaf } from 'react-native-bread' ;
// Enable native RTL (in index.js, before app starts)
I18nManager . forceRTL ( true );
I18nManager . allowRTL ( true );
// No rtl config needed
export default function App () {
return (
<>
< Stack />
< BreadLoaf /> { /* Automatically RTL */ }
</>
);
}
Code-level RTL
import { BreadLoaf } from 'react-native-bread' ;
export default function App () {
const isRTL = useRTLDetection (); // Your logic
return (
<>
< Stack />
< BreadLoaf config = { { rtl: isRTL } } />
</>
);
}