Skip to content

Instantly share code, notes, and snippets.

@justinobney
Last active April 5, 2018 02:52
Show Gist options
  • Save justinobney/f6ccb14e0f7714046ec0229da7f1d23e to your computer and use it in GitHub Desktop.
Save justinobney/f6ccb14e0f7714046ec0229da7f1d23e to your computer and use it in GitHub Desktop.
React-L10N
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