Skip to content

Instantly share code, notes, and snippets.

@necolas
Last active April 17, 2022 19:13
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save necolas/ad81f4f144e1d9b171108e0c0635e16a to your computer and use it in GitHub Desktop.
Save necolas/ad81f4f144e1d9b171108e0c0635e16a to your computer and use it in GitHub Desktop.
Localized typography with React Native
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;
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;
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