Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial i18n lookup function #2814

Merged
merged 1 commit into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions src/govuk/components/accordion/accordion.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import { nodeListForEach } from '../../common.mjs'
import I18n from '../../i18n.mjs'
import '../../vendor/polyfills/Function/prototype/bind.mjs'
import '../../vendor/polyfills/Element/prototype/classList.mjs'

Expand All @@ -25,6 +26,16 @@ function Accordion ($module) {
this.$showAllButton = ''
this.browserSupportsSessionStorage = helper.checkForSessionStorage()

var defaultConfig = {
i18n: {
hideAllSections: 'Hide all sections',
hideSection: 'Hide<span class="govuk-visually-hidden"> this section</span>',
showAllSections: 'Show all sections',
showSection: 'Show<span class="govuk-visually-hidden"> this section</span>'
}
}
this.i18n = new I18n(defaultConfig.i18n)

this.controlsClass = 'govuk-accordion__controls'
this.showAllClass = 'govuk-accordion__show-all'
this.showAllTextClass = 'govuk-accordion__show-all-text'
Expand Down Expand Up @@ -232,15 +243,11 @@ Accordion.prototype.setExpanded = function (expanded, $section) {
var $icon = $section.querySelector('.' + this.upChevronIconClass)
var $showHideText = $section.querySelector('.' + this.sectionShowHideTextClass)
var $button = $section.querySelector('.' + this.sectionButtonClass)
var newButtonText = expanded ? 'Hide' : 'Show'

// Build additional copy of "this section" for assistive technology and place inside toggle link
var $visuallyHiddenText = document.createElement('span')
$visuallyHiddenText.classList.add('govuk-visually-hidden')
$visuallyHiddenText.innerHTML = ' this section'
var newButtonText = expanded
? this.i18n.t('hideSection')
: this.i18n.t('showSection')

$showHideText.innerHTML = newButtonText
$showHideText.appendChild($visuallyHiddenText)
$button.setAttribute('aria-expanded', expanded)

// Swap icon, change class
Expand Down Expand Up @@ -277,7 +284,9 @@ Accordion.prototype.checkIfAllSectionsOpen = function () {
Accordion.prototype.updateShowAllButton = function (expanded) {
var $showAllIcon = this.$showAllButton.querySelector('.' + this.upChevronIconClass)
var $showAllText = this.$showAllButton.querySelector('.' + this.showAllTextClass)
var newButtonText = expanded ? 'Hide all sections' : 'Show all sections'
var newButtonText = expanded
? this.i18n.t('hideAllSections')
: this.i18n.t('showAllSections')
this.$showAllButton.setAttribute('aria-expanded', expanded)
$showAllText.innerHTML = newButtonText

Expand Down
33 changes: 33 additions & 0 deletions src/govuk/i18n.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* i18n support initialisation function
*
* @constructor
* @param {Object} translations - Key-value pairs of the translation
strings to use.
*/
function I18n (translations) {
// Make list of translations available throughout function
this.translations = translations || {}
}

/**
* The most used function - takes the key for a given piece of UI text and
* returns the appropriate string.
*
* @param {String} lookupKey - The lookup key of the string to use.
* @returns {String} - The appropriate translation string.
*/
I18n.prototype.t = function (lookupKey) {
if (!lookupKey) {
// Print a console error if no lookup key has been provided
throw new Error('i18n lookup key missing.')
} else if (lookupKey in this.translations) {
// Return the translation string if it exists in the object
return this.translations[lookupKey]
} else {
// Otherwise, return the lookup key itself as the fallback
return lookupKey
}
}

export default I18n
42 changes: 42 additions & 0 deletions src/govuk/i18n.unit.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* @jest-environment jsdom
*/
/* eslint-env jest */

import I18n from './i18n.mjs'

describe('I18n', () => {
describe('retrieving translations', () => {
let config = {}

beforeEach(() => {
config = {
textString: 'Hello world',
htmlString: 'Hello<span class="govuk-visually-hidden"> world</span>'
}
})

test('returns the text for a given lookup key', () => {
const i18n = new I18n(config)
const returnString = i18n.t('textString')
expect(returnString).toBe('Hello world')
})

test('returns the HTML for a given lookup key', () => {
const i18n = new I18n(config)
const returnString = i18n.t('htmlString')
expect(returnString).toBe('Hello<span class="govuk-visually-hidden"> world</span>')
})

test('returns the lookup key if no translation is defined', () => {
const i18n = new I18n(config)
const returnString = i18n.t('missingString')
expect(returnString).toBe('missingString')
})

test('throws an error if no lookup key is provided', () => {
const i18n = new I18n(config)
expect(() => i18n.t()).toThrow('i18n lookup key missing.')
})
})
})