Last active
April 17, 2022 19:13
-
-
Save necolas/ad81f4f144e1d9b171108e0c0635e16a to your computer and use it in GitHub Desktop.
Localized typography with React Native
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import i18n from './i18n'; | |
import theme from './theme'; | |
import { bool, string } from 'prop-types'; | |
import { I18nManager, StyleSheet, Text } from 'react-native'; | |
import React, { Component } from 'react'; | |
/** | |
* React Component | |
*/ | |
class AppText extends Component { | |
static displayName = '@acme/AppText'; | |
static propTypes = { | |
...Text.propTypes, | |
lang: string | |
}; | |
static contextTypes = { | |
language: string | |
}; | |
render() { | |
const style = [ | |
styles.root, | |
getLanguageFontFamily(this.props.lang || this.context.language), | |
this.props.style | |
]; | |
return <Text {...this.props} style={style} />; | |
} | |
} | |
const styles = StyleSheet.create({ | |
root: { | |
fontWeight: 'normal', | |
wordWrap: 'break-word' | |
} | |
}); | |
const languageStyles = StyleSheet.create({ | |
normal: { | |
fontFamily: theme.fontFamilies.normal | |
}, | |
ja: { | |
fontFamily: theme.fontFamilies.japan | |
}, | |
rtl: { | |
fontFamily: theme.fontFamilies.rtl | |
} | |
}); | |
/** | |
* Font-family picker | |
*/ | |
const getLanguageFontFamily = language => { | |
const isGlobalRTL = I18nManager.isRTL; | |
// if there is a language | |
if (language) { | |
if (language === 'ja') { | |
return languageStyles.ja; | |
} | |
if (i18n.isLocaleRTL(language)) { | |
return languageStyles.rtl; | |
} | |
return languageStyles.normal; | |
} | |
return isGlobalRTL ? languageStyles.rtl : languageStyles.normal; | |
}; | |
export default AppText; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const rtlLocaleMap = { | |
'ae': true, // Avestan | |
'ar': true, // Arabic | |
'arc': true, // Aramaic | |
'bcc': true, // Southern Balochi | |
'bqi': true, // Bakthiari | |
'ckb': true, // Sorani | |
'dv': true, // Dhivehi | |
'fa': true, 'far': true, // Persian | |
'glk': true, // Gilaki | |
'he': true, 'iw': true, // Hebrew | |
'khw': true, // Khowar | |
'ks': true, // Kashmiri | |
'ku': true, // Kurdish | |
'mzn': true, // Mazanderani | |
'nqo': true, // N'Ko | |
'pnb': true, // Western Punjabi | |
'ps': true, // Pashto | |
'sd': true, // Sindhi | |
'ug': true, // Uyghur | |
'ur': true, // Urdu | |
'yi': true // Yiddish | |
}; | |
const isLocaleRTL = locale => Boolean(rtlLocaleMap[locale]); | |
const i18n = { | |
isLocaleRTL, | |
getLocaleDirection(locale) { | |
return isLocaleRTL(locale) ? 'rtl' : 'ltr'; | |
} | |
}; | |
export default i18n; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Dimensions, Platform } from 'react-native'; | |
const canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); | |
const baseFontSize = 14; | |
const baseUnit = 1.3125; | |
const createPlatformLength = multiplier => | |
Platform.select({ web: `${multiplier}rem`, default: multiplier * baseFontSize }); | |
/** | |
* Exported variables | |
*/ | |
const fontFamilies = { | |
normal: 'System', | |
japan: Platform.select({ | |
web: 'Noto, System', | |
default: 'System' | |
}), | |
rtl: Platform.select({ | |
web: 'Noto, Segoe UI, System', | |
default: 'System' | |
}) | |
}; | |
const fontSizes = { | |
// font scale | |
small: createPlatformLength(0.85), | |
normal: createPlatformLength(1), | |
large: createPlatformLength(1.25), | |
xLarge: createPlatformLength(1.5), | |
jumbo: createPlatformLength(2) | |
}; | |
// On web, change the root font-size at specific breakpoints to scale the UI | |
// for larger viewports. | |
if (Platform.OS === 'web' && canUseDOM) { | |
const { medium, large } = breakpoints; | |
const htmlElement = document.documentElement; | |
const setFontSize = width => { | |
const fontSize = width > medium ? (width > large ? '16px' : '15px') : '14px'; | |
if (htmlElement) { | |
htmlElement.style.fontSize = fontSize; | |
} | |
}; | |
setFontSize(Dimensions.get('window').width); | |
Dimensions.addEventListener('change', dimensions => { | |
setFontSize(dimensions.window.width); | |
}); | |
} | |
module.exports = { | |
borderRadii, | |
fontFamilies, | |
fontSizes | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment