Report missing `en` locale messages to Sentry (#7197)

Any missing messages in the `en` locale are now reported to Sentry as
errors. They are printed to the console as an error upon the first
encounter as well.

If a missing message is found during e2e testing, the error is thrown.
This will likely break the e2e test even if it isn't looking for
console errors, as the UI with the missing message will fail to render.

The `tOrDefault` method was updated to no longer attempt looking for
messages with a key that is a falsey value (e.g. `undefined`). There
are a few places where they key is determined dynamically, where it's
expected during the normal flow for it to be `undefined` sometimes.
In these cases we don't want the error to be thrown.
feature/default_network_editable
Mark Stacey 5 years ago committed by GitHub
parent 9f21317a30
commit f100d753cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      ui/app/helpers/higher-order-components/i18n-provider.js
  2. 22
      ui/app/helpers/utils/i18n-helper.js

@ -3,12 +3,15 @@ const connect = require('react-redux').connect
const PropTypes = require('prop-types') const PropTypes = require('prop-types')
const { withRouter } = require('react-router-dom') const { withRouter } = require('react-router-dom')
const { compose } = require('recompose') const { compose } = require('recompose')
const t = require('../utils/i18n-helper').getMessage const { getMessage } = require('../utils/i18n-helper')
class I18nProvider extends Component { class I18nProvider extends Component {
tOrDefault = (key, defaultValue, ...args) => { tOrDefault = (key, defaultValue, ...args) => {
if (!key) {
return defaultValue
}
const { localeMessages: { current, en } = {}, currentLocale } = this.props const { localeMessages: { current, en } = {}, currentLocale } = this.props
return t(currentLocale, current, key, ...args) || t(currentLocale, en, key, ...args) || defaultValue return getMessage(currentLocale, current, key, ...args) || getMessage(currentLocale, en, key, ...args) || defaultValue
} }
getChildContext () { getChildContext () {
@ -22,11 +25,7 @@ class I18nProvider extends Component {
* @return {string|undefined|null} The localized message if available * @return {string|undefined|null} The localized message if available
*/ */
t (key, ...args) { t (key, ...args) {
if (key === undefined || key === null) { return getMessage(currentLocale, current, key, ...args) || getMessage(currentLocale, en, key, ...args) || `[${key}]`
return key
}
return t(currentLocale, current, key, ...args) || t(currentLocale, en, key, ...args) || `[${key}]`
}, },
tOrDefault: this.tOrDefault, tOrDefault: this.tOrDefault,
tOrKey: (key, ...args) => { tOrKey: (key, ...args) => {

@ -1,7 +1,10 @@
// cross-browser connection to extension i18n API // cross-browser connection to extension i18n API
const log = require('loglevel') const log = require('loglevel')
const Sentry = require('@sentry/browser')
const warned = {} const warned = {}
const missingMessageErrors = {}
/** /**
* Returns a localized message for the given key * Returns a localized message for the given key
* @param {string} localeCode The code for the current locale * @param {string} localeCode The code for the current locale
@ -10,12 +13,21 @@ const warned = {}
* @param {string[]} substitutions A list of message substitution replacements * @param {string[]} substitutions A list of message substitution replacements
* @return {null|string} The localized message * @return {null|string} The localized message
*/ */
const getMessage = (localeCode, localeMessages, key, substitutions) => { export const getMessage = (localeCode, localeMessages, key, substitutions) => {
if (!localeMessages) { if (!localeMessages) {
return null return null
} }
if (!localeMessages[key]) { if (!localeMessages[key]) {
if (!warned[localeCode] || !warned[localeCode][key]) { if (localeCode === 'en') {
if (!missingMessageErrors[key]) {
missingMessageErrors[key] = new Error(`Unable to find value of key "${key}" for locale "${localeCode}"`)
Sentry.captureException(missingMessageErrors[key])
log.error(missingMessageErrors[key])
if (process.env.IN_TEST === 'true') {
throw missingMessageErrors[key]
}
}
} else if (!warned[localeCode] || !warned[localeCode][key]) {
if (!warned[localeCode]) { if (!warned[localeCode]) {
warned[localeCode] = {} warned[localeCode] = {}
} }
@ -36,7 +48,7 @@ const getMessage = (localeCode, localeMessages, key, substitutions) => {
return phrase return phrase
} }
async function fetchLocale (localeCode) { export async function fetchLocale (localeCode) {
try { try {
const response = await fetch(`./_locales/${localeCode}/messages.json`) const response = await fetch(`./_locales/${localeCode}/messages.json`)
return await response.json() return await response.json()
@ -46,7 +58,3 @@ async function fetchLocale (localeCode) {
} }
} }
module.exports = {
getMessage,
fetchLocale,
}

Loading…
Cancel
Save