feat(errors): dynamic fallback locale

This commit is contained in:
Benedikt Rötsch
2018-02-14 16:15:02 +01:00
committed by Benedikt Rötsch
parent 92fcbdf4d8
commit 3c9089af98
3 changed files with 45 additions and 17 deletions

6
app.js
View File

@@ -11,7 +11,7 @@ const helmet = require('helmet')
require('dotenv').config({ path: 'variables.env' }) require('dotenv').config({ path: 'variables.env' })
const helpers = require('./helpers') const helpers = require('./helpers')
const { translate, initializeTranslations } = require('./i18n/i18n') const { translate, initializeTranslations, setFallbackLocale } = require('./i18n/i18n')
const breadcrumb = require('./lib/breadcrumb') const breadcrumb = require('./lib/breadcrumb')
const { updateCookie } = require('./lib/cookies') const { updateCookie } = require('./lib/cookies')
const settings = require('./lib/settings') const settings = require('./lib/settings')
@@ -110,6 +110,10 @@ app.use(catchErrors(async function (request, response, next) {
response.locals.currentLocale = defaultLocale response.locals.currentLocale = defaultLocale
} }
if (response.locals.fallbackCode) {
setFallbackLocale(response.locals.fallbackCode)
}
// Creates a query string which adds the current credentials to links // Creates a query string which adds the current credentials to links
// To other implementations of this app in the about modal // To other implementations of this app in the about modal
helpers.updateSettingsQuery(request, response, response.locals.settings) helpers.updateSettingsQuery(request, response, response.locals.settings)

View File

@@ -2,12 +2,19 @@ const fs = require('fs')
const path = require('path') const path = require('path')
let translations = null let translations = null
// Initializes translation dictionary with contents from /public/locales let fallbackLocale = null
module.exports.initializeTranslations = () => {
/**
* Initializes translation dictionary with contents from /public/locales
*/
function initializeTranslations () {
if (translations) { if (translations) {
return return
} }
// Default fallbock locale is english
setFallbackLocale('en-US')
translations = {} translations = {}
const localesPath = path.join(__dirname, 'locales') const localesPath = path.join(__dirname, 'locales')
@@ -26,6 +33,14 @@ module.exports.initializeTranslations = () => {
} }
} }
/**
* Sets the fallback locale
* @param locale string Locale code
*/
function setFallbackLocale (locale) {
fallbackLocale = locale
}
/** /**
* Translate a static string * Translate a static string
* @param symbol string Identifier for static text * @param symbol string Identifier for static text
@@ -33,14 +48,20 @@ module.exports.initializeTranslations = () => {
* *
* @returns string * @returns string
*/ */
module.exports.translate = (symbol, locale = 'en-US') => { function translate (symbol, locale = 'en-US') {
const localeDict = translations[locale] const localeDict = translations[locale]
if (!localeDict) { let translatedValue
return `Localization file for ${locale} is not available`
if (localeDict) {
translatedValue = localeDict[symbol]
} }
const translatedValue = localeDict[symbol]
if (!translatedValue) { if (!translatedValue) {
return `Translation not found for ${symbol} in ${locale}` translatedValue = translations[fallbackLocale][symbol]
}
if (!translatedValue) {
return `Translation not found for ${symbol}`
} }
return translatedValue return translatedValue
@@ -53,6 +74,11 @@ module.exports.translate = (symbol, locale = 'en-US') => {
* *
* @returns boolean * @returns boolean
*/ */
module.exports.translationAvaliable = (symbol, locale = 'en-US') => { function translationAvaliable (symbol, locale = 'en-US') {
return !!(translations[locale] || {})[symbol] return !!(translations[locale] || translations[fallbackLocale] || {})[symbol]
} }
module.exports.initializeTranslations = initializeTranslations
module.exports.setFallbackLocale = setFallbackLocale
module.exports.translate = translate
module.exports.translationAvaliable = translationAvaliable

View File

@@ -99,12 +99,12 @@ describe('Settings', () => {
}) })
describe('i18n', () => { describe('i18n', () => {
test('It returns an error when locale file is not found', () => { test('It returns the fallback value when locale file is not found', () => {
expect(translate('foo', 'bar-locale')).toBe('Localization file for bar-locale is not available') expect(translate('defaultTitle', 'not-existing-locale-file')).toBe('The Example App')
}) })
test('It returns an error when symbol is not found on locale file', () => { test('It returns an error when symbol is not found on locale file', () => {
expect(translate('foo', 'en-US')).toBe('Translation not found for foo in en-US') expect(translate('foo', 'en-US')).toBe('Translation not found for foo')
}) })
test('It returns the translated string when symbol is found on locale file', () => { test('It returns the translated string when symbol is found on locale file', () => {
@@ -113,10 +113,8 @@ describe('i18n', () => {
test('It returns true if string is found for locale', () => { test('It returns true if string is found for locale', () => {
expect(translationAvaliable('coursesLabel', 'en-US')).toBe(true) expect(translationAvaliable('coursesLabel', 'en-US')).toBe(true)
}) })
test('It returns false if string is not found for locale', () => {
expect(translationAvaliable('foo-symbol', 'en-US')).toBe(false)
})
test('It returns false if locale is not found', () => { test('It returns false if locale is not found', () => {
expect(translationAvaliable('coursesLabel', 'foo-locale')).toBe(false) expect(translationAvaliable('foo-symbol', 'en-US')).toBe(false)
expect(translationAvaliable('foo-symbol', 'not-existing-locale')).toBe(false)
}) })
}) })