Last active
April 5, 2018 02:52
-
-
Save justinobney/f6ccb14e0f7714046ec0229da7f1d23e to your computer and use it in GitHub Desktop.
React-L10N
This file contains hidden or 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 React, {PureComponent} from 'react'; | |
import isFunction from 'lodash/isFunction'; | |
const I18nContext = React.createContext(); | |
export const i18nDictionary = { | |
'en-US': safeTranslationAccessor({ | |
'navigation.report-issue': 'Report Issue', | |
'navigation.logout': 'Log Out', | |
'dashboard.favorites': 'Favorites', | |
'dashboard.history': 'History', | |
'dashboard.tab-title.purchase-orders': ({count}) => `Purchase Orders (${count})`, | |
'dashboard.tab-title.part-numbers': ({count}) => `Part Numbers (${count})`, | |
'dashboard.tab-title.serial-numbers': ({count}) => `Serial Numbers (${count})`, | |
}), | |
fr: safeTranslationAccessor({ | |
'navigation.report-issue': 'Report Issue', | |
'navigation.logout': 'Log Out', | |
'dashboard.favorites': 'Le´ Favorites', | |
'dashboard.history': 'Le´ History', | |
'dashboard.tab-title.purchase-orders': ({count}) => `Purchase Orders (${count})`, | |
'dashboard.tab-title.part-numbers': ({count}) => `Part Numbers (${count})`, | |
'dashboard.tab-title.serial-numbers': ({count}) => `Serial Numbers (${count})`, | |
}), | |
}; | |
export const getBrowserLanguage = (defaultLanguage = 'en-US') => | |
i18nDictionary[navigator.language] || i18nDictionary[defaultLanguage] || i18nDictionary['en-US']; | |
export function withLocale(Component) { | |
return function LocaleAwareComponent(props) { | |
return <I18nContext.Consumer>{locale => <Component {...props} locale={locale} />}</I18nContext.Consumer>; | |
}; | |
} | |
// Why bother with "PureComponent" | |
// This accesses the value via a proxy & inside a try/catch | |
// while fast, this isnt free... | |
// Since this component is intended to be used a lot, why render if we dont have to? | |
export const FormattedMessage = withLocale( | |
class extends PureComponent { | |
render() { | |
const {locale, id, values = {}} = this.props; | |
const accessor = locale[id]; | |
console.log(id); // checking to see if re-rendered | |
return isFunction(accessor) ? accessor(values) : accessor; | |
} | |
} | |
); | |
export const FormattedMessage_LessPerformant = withLocale(({locale, id, values = {}}) => { | |
const accessor = locale[id]; | |
console.log(id); // checking to see if re-rendered | |
return isFunction(accessor) ? accessor(values) : accessor; | |
}); | |
function safeTranslationAccessor(obj) { | |
const errorHistory = {}; | |
const logError = (key, ...rest) => { | |
// prevent logging the same missing key multiple times => aka dont spam TrackJS | |
if (errorHistory[key]) { | |
return; | |
} | |
errorHistory[key] = true; | |
console.error(key, ...rest); | |
}; | |
let handler = { | |
get(target, propKey, receiver) { | |
const origMethod = target[propKey]; | |
const formatTranslation = (valuesObject, ...rest) => { | |
try { | |
let result = origMethod.apply(this, [valuesObject, ...rest]); | |
return result; | |
} catch (error) { | |
logError(`Unable to retreive translation for key: ${propKey}`, [valuesObject, ...rest]); | |
return `UNKNOWN`; | |
} | |
}; | |
if (!origMethod) { | |
return (...args) => { | |
logError(`Unable to retreive translation for key: ${propKey}`, args); | |
return 'UNKNOWN'; | |
}; | |
} | |
return isFunction(origMethod) ? formatTranslation : origMethod; | |
}, | |
}; | |
return new Proxy(obj, handler); | |
} | |
export default I18nContext; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment