Skip to content

Commit

Permalink
feat(i18n): new locale interface, and translation configs (#1710)
Browse files Browse the repository at this point in the history
* feat(localeInterface):addition of locale interface in options and and implementation of translations property

* formatting rectified

* feat(localeOptions):updated translations prop and addition of numberFormatter to table and tooltip

* fix(type):deleted unrequired imports

* feat(localeOptions):updated locale object and locale conversion for axis

* fix(localeInterface):axis ticks format

* fix(localeInterface):change in optionsObject property structure

* fix(localeInterface):added locale demo

* fix(localeInterface):date translation for modal and colorScale

* fix(model):removing unused imports
  • Loading branch information
RiyaJethwa committed Feb 13, 2024
1 parent fdf0da0 commit 60ef1ec
Show file tree
Hide file tree
Showing 43 changed files with 628 additions and 109 deletions.
8 changes: 5 additions & 3 deletions packages/core/src/components/axes/axis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ export class Axis extends Component {
// create the right ticks formatter
let formatter: any
const userProvidedFormatter = getProperty(axisOptions, 'ticks', 'formatter')
const { code: localeCode, number: numberFormatter } = getProperty(options, 'locale')
if (isTimeScaleType) {
const timeInterval = computeTimeIntervalName(
axis.tickValues(),
Expand All @@ -232,23 +233,24 @@ export class Axis extends Component {

if (userProvidedFormatter === null) {
formatter = (t: number, i: number) =>
formatTick(t, i, axis.tickValues(), timeInterval, timeScaleOptions)
formatTick(t, i, axis.tickValues(), timeInterval, timeScaleOptions, options.locale)
} else {
formatter = (t: number, i: number) => {
const defaultFormattedValue = formatTick(
t,
i,
axis.tickValues(),
timeInterval,
timeScaleOptions
timeScaleOptions,
options.locale
)
return userProvidedFormatter(t, i, defaultFormattedValue)
}
}
} else {
if (userProvidedFormatter === null) {
if (scaleType === ScaleTypes.LINEAR) {
formatter = (t: any) => t.toLocaleString()
formatter = (t: any) => numberFormatter(t, localeCode)
}
} else {
formatter = userProvidedFormatter
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/components/axes/ruler-binned.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ export class BinnedRuler extends Ruler {
...(getProperty(options, 'tooltip', 'showTotal') === true
? [
{
label: get(options, 'tooltip.totalLabel') || 'Total',
label:
get(options, 'locale.translations.total') ||
get(options, 'tooltip.totalLabel') ||
'Total',
value: activeDataGroupNames.reduce(
(accum: number, currentValue: any) =>
accum + parseFloat(get(sampleMatchData, `data.${currentValue}`)),
Expand Down
16 changes: 11 additions & 5 deletions packages/core/src/components/axes/toolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export class Toolbar extends Component {
.classed('cds--overflow-menu-options__option--disabled', (d: any) => d.shouldBeDisabled())
.attr('aria-disabled', (d: any) => d.shouldBeDisabled())
.selectAll('button')
.text((d: any) => d.text)
.text((d: any) => d.title)
}

isOverflowMenuOpen() {
Expand Down Expand Up @@ -367,7 +367,6 @@ export class Toolbar extends Component {
getControlConfigs() {
const numberOfIcons = getProperty(this.getOptions(), 'toolbar', 'numberOfIcons') - 1
const controls = getProperty(this.getOptions(), 'toolbar', 'controls')

const overflowSpecificControls: any[] = []
const buttonList: any[] = []
const overflowList: any[] = []
Expand Down Expand Up @@ -475,6 +474,13 @@ export class Toolbar extends Component {
!this.services.zoom.isEmptyState()

const displayData = this.model.getDisplayData()
const options = this.model.getOptions()
const { exportAsCSV, exportAsJPG, exportAsPNG } = getProperty(
options,
'locale',
'translations',
'toolbar'
)

let controlConfig: any
switch (controlType) {
Expand Down Expand Up @@ -561,7 +567,7 @@ export class Toolbar extends Component {
case ToolbarControlTypes.EXPORT_CSV:
controlConfig = {
id: 'toolbar-export-CSV',
title: 'Export as CSV',
title: exportAsCSV,
shouldBeDisabled: () => false,
iconSVG: {
content: this.getControlIconByType(controlType)
Expand All @@ -572,7 +578,7 @@ export class Toolbar extends Component {
case ToolbarControlTypes.EXPORT_PNG:
controlConfig = {
id: 'toolbar-export-PNG',
title: 'Export as PNG',
title: exportAsPNG,
shouldBeDisabled: () => false,
iconSVG: {
content: this.getControlIconByType(controlType)
Expand All @@ -583,7 +589,7 @@ export class Toolbar extends Component {
case ToolbarControlTypes.EXPORT_JPG:
controlConfig = {
id: 'toolbar-export-JPG',
title: 'Export as JPG',
title: exportAsJPG,
shouldBeDisabled: () => false,
iconSVG: {
content: this.getControlIconByType(controlType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,12 @@ export class ColorScaleLegend extends Legend {

// Create scale & ticks
const linearScale = scaleLinear().domain(domain).range([0, barWidth])

const legendAxis = axisBottom(linearScale).tickSize(0).tickValues(quant)

//translating ticks into given locale language
const { code: localeCode, number: numberFormatter } = getProperty(options, 'locale')
legendAxis.tickFormat(d => numberFormatter(d, localeCode))

let rangeStart: any // avoid unexpected lexical declaration in case block
switch (colorScaleType) {
case ColorLegendType.LINEAR:
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/components/essentials/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,17 @@ export class Modal extends Component {

const options = this.model.getOptions()

const { title, downloadAsCSV } = getProperty(options, 'locale', 'translations', 'tabularRep')

const chartprefix = getProperty(options, 'style', 'prefix')

const tableArray = this.model.getTabularDataArray()

return `
<div class="cds--modal-container cds--modal-container">
<div class="cds--modal-header cds--modal-header">
<p class="cds--modal-header__label cds--type-delta cds--modal-header__label cds--type-delta" id="${id}__modal-title">Tabular representation</p>
<p class="cds--modal-header__label cds--type-delta cds--modal-header__label cds--type-delta" id="modal-title">${title}</p>
<p class="cds--modal-header__heading cds--type-beta cds--modal-header__heading cds--type-beta" id="${id}__modal-description">${sanitizeText(
options.title
Expand Down Expand Up @@ -122,7 +125,7 @@ export class Modal extends Component {
<div class="cds--modal-footer cds--modal-footer">
<div class="${carbonPrefix}--${chartprefix}-modal-footer-spacer"></div>
<button class="cds--btn cds--btn--primary cds--btn cds--btn--primary" type="button" data-modal-primary-focus>Download as CSV</button>
<button class="cds--btn cds--btn--primary cds--btn cds--btn--primary" type="button" data-modal-primary-focus>${downloadAsCSV}</button>
</div>
</div>`
}
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/components/essentials/threshold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export class Threshold extends Component {
const { value, axisPosition } = datum
const options = this.getOptions()
const scaleType = this.services.cartesianScales.getScaleTypeByPosition(axisPosition)

const { code: localeCode, number: numberFormatter } = getProperty(options, 'locale')
// If scale is time, format the threshold date as the ticks format
if (scaleType === ScaleTypes.TIME) {
const isVertical = [AxisPositions.LEFT, AxisPositions.RIGHT].includes(axisPosition)
Expand All @@ -215,10 +215,10 @@ export class Threshold extends Component {
getProperty(timeScaleOptions, 'timeInterval')
)

return formatTick(value, 0, scale.ticks(), timeInterval, timeScaleOptions)
return formatTick(value, 0, scale.ticks(), timeInterval, timeScaleOptions, options.locale)
}

return value.toLocaleString('en')
return numberFormatter(value, localeCode)
}

appendThresholdLabel() {
Expand Down
19 changes: 12 additions & 7 deletions packages/core/src/components/essentials/title-meter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ export class MeterTitle extends Title {
const options = this.getOptions()
const svg = this.getComponentContainer()
const { groupMapsTo } = options.data

const meterTitle = options.locale.translations.meter.title
const proportional = getProperty(options, 'meter', 'proportional')

if (proportional) {
this.displayTotal()
this.displayBreakdownTitle()
} else {
// the title for a meter, is the label for that dataset
const title = svg.selectAll('text.meter-title').data([dataset[groupMapsTo]])

const title = svg
.selectAll('text.meter-title')
.data(meterTitle ? [meterTitle] : [dataset[groupMapsTo]])
title
.enter()
.append('text')
Expand Down Expand Up @@ -73,13 +74,14 @@ export class MeterTitle extends Title {
const difference = total !== null ? total - datasetsTotal : datasetsTotal
//breakdownFormatter
const breakdownFormatter = getProperty(options, 'meter', 'proportional', 'breakdownFormatter')
const { code: localeCode, number: numberFormatter } = getProperty(options, 'locale')
data =
breakdownFormatter !== null
? breakdownFormatter({
datasetsTotal: datasetsTotal,
total: total
})
: `${datasetsTotal} ${unit} used (${difference} ${unit} available)`
: `${numberFormatter(datasetsTotal, localeCode)} ${unit} used (${numberFormatter(difference, localeCode)} ${unit} available)`
}

// the breakdown part to whole of the datasets to the overall total
Expand Down Expand Up @@ -121,9 +123,12 @@ export class MeterTitle extends Title {

// totalFormatter function
const totalFormatter = getProperty(options, 'meter', 'proportional', 'totalFormatter')
const { code: localeCode, number: numberFormatter } = getProperty(options, 'locale')

const totalString =
totalFormatter !== null ? totalFormatter(totalValue) : `${total} ${unit} total`
totalFormatter !== null
? totalFormatter(totalValue)
: `${numberFormatter(total, localeCode)} ${unit} total`

const containerBounds = DOMUtils.getHTMLElementSize(this.services.domUtils.getMainContainer())

Expand Down Expand Up @@ -214,7 +219,7 @@ export class MeterTitle extends Title {
*/
appendPercentage() {
const dataValue = getProperty(this.model.getDisplayData(), 0, 'value')

const { code: localeCode, number: numberFormatter } = getProperty(this.getOptions(), 'locale')
// use the title's position to append the percentage to the end
const svg = this.getComponentContainer()
const title = DOMUtils.appendOrSelect(svg, 'text.meter-title')
Expand All @@ -237,7 +242,7 @@ export class MeterTitle extends Title {
.append('text')
.classed('percent-value', true)
.merge(percentage as any)
.text((d: any) => `${d}%`)
.text((d: any) => `${numberFormatter(d, localeCode)}%`)
.attr('x', +title.attr('x') + title.node().getComputedTextLength() + offset) // set the position to after the title
.attr('y', title.attr('y'))

Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/components/essentials/tooltip-axis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export class AxisChartsTooltip extends Tooltip {
}

items.push({
label: options.tooltip.groupLabel,
label: get(options, 'locale.translations.group') || get(options, 'tooltip.groupLabel'),
value: datum[groupMapsTo],
color: this.model.getFillColor(datum[groupMapsTo]),
class: this.model.getColorClassName({
Expand Down Expand Up @@ -113,7 +113,10 @@ export class AxisChartsTooltip extends Tooltip {
// use the primary/only range id
const rangeIdentifier = cartesianScales.getRangeIdentifier()
items.push({
label: get(options, 'tooltip.totalLabel') || 'Total',
label:
get(options, 'locale.translations.total') ||
get(options, 'tooltip.totalLabel') ||
'Total',
value: data.reduce(
(accumulator: number, datum: any) => accumulator + datum[rangeIdentifier],
0
Expand Down
17 changes: 13 additions & 4 deletions packages/core/src/components/essentials/tooltip.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { select, pointer } from 'd3'
import { format } from 'date-fns/format'
import Position, { PLACEMENTS } from '@carbon/utils-position' // position service
import { getProperty, truncateLabel } from '@/tools'
import { zoomBar as zoomBarConfigs, tooltips as tooltipConfigs } from '@/configuration'
Expand Down Expand Up @@ -182,25 +181,35 @@ export class Tooltip extends Component {
valueFormatter(value: any, label: string) {
const options = this.getOptions()
const valueFormatter = getProperty(options, 'tooltip', 'valueFormatter')
const {
code: localeCode,
number: numberFormatter,
date: dateFormatter
} = getProperty(options, 'locale')

if (valueFormatter) {
return valueFormatter(value, label)
}

if (typeof value.getTime === 'function') {
return format(value, 'MMM d, yyyy')
return dateFormatter(value, localeCode, { month: 'short', day: 'numeric', year: 'numeric' })
}

try {
// it's a correct ISO format Date string
if (typeof value === 'string' && /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(value)) {
return format(Date.parse(value), 'MMM d, yyyy')
const newDate = new Date(value)
return dateFormatter(newDate, localeCode, {
month: 'short',
day: 'numeric',
year: 'numeric'
})
}
} catch (e) {
// not a valid ISO format string
}

return value.toLocaleString()
return numberFormatter(value, localeCode)
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
Expand Down
9 changes: 7 additions & 2 deletions packages/core/src/components/graphs/alluvial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ export class Alluvial extends Component {
this.services.domUtils.generateElementIDString(`alluvial-node-title-${d.index}`)
)

const { code: localeCode, number: numberFormatter } = getProperty(options, 'locale')
// Node title - text
textNode
.append('text')
Expand All @@ -267,7 +268,7 @@ export class Alluvial extends Component {
// shift 13 pixels down to fit background container
.attr('dy', 13)
.text((d: any) => {
return `${d.name} (${d.value})`
return `${d.name} (${numberFormatter(d.value, localeCode)})`
})
.attr('aria-label', (d: any) => {
return `${d.name} (${d.value})`
Expand Down Expand Up @@ -327,6 +328,7 @@ export class Alluvial extends Component {
addLineEventListener() {
const options = this.getOptions()
const self = this
const { number: numberFormatter, code: localeCode } = getProperty(this.getOptions(), 'locale')

// Set delay to counter flashy behaviour
const debouncedLineHighlight = debounce((link, event = 'mouseover') => {
Expand Down Expand Up @@ -379,7 +381,10 @@ export class Alluvial extends Component {
items: [
{
label: datum.target.name,
value: datum.value + (options.alluvial.units ? ` ${options.alluvial.units}` : ''),
value:
(numberFormatter(datum.value, localeCode)
? `${numberFormatter(datum.value, localeCode)}`
: '-') + (options.alluvial.units ? ` ${options.alluvial.units}` : ''),
color: strokeColor,
labelIcon: self.getRightArrowIcon()
}
Expand Down
12 changes: 9 additions & 3 deletions packages/core/src/components/graphs/boxplot.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { select } from 'd3'
import { flipDomainAndRangeBasedOnOrientation, generateSVGPathString } from '@/tools'
import { flipDomainAndRangeBasedOnOrientation, generateSVGPathString, getProperty } from '@/tools'
import { boxplot as boxplotConfigs } from '@/configuration'
import { BoxplotChartModel } from '@/model/boxplot'
import { Component } from '@/components/component'
Expand Down Expand Up @@ -334,7 +334,10 @@ export class Boxplot extends Component {
hoveredElement,
items: [
{
label: options.tooltip.groupLabel,
label:
getProperty(options, 'locale', 'translations', 'group') ||
getProperty(options, 'tooltip', 'groupLabel') ||
'Group',
value: datum[groupMapsTo],
class: self.model.getColorClassName({
classNameTypes: [ColorClassNameTypes.TOOLTIP]
Expand Down Expand Up @@ -442,7 +445,10 @@ export class Boxplot extends Component {
hoveredElement,
items: [
{
label: options.tooltip.groupLabel,
label:
getProperty(options, 'locale', 'translations', 'group') ||
getProperty(options, 'tooltip', 'groupLabel') ||
'Group',
value: datum[groupMapsTo],
class: self.model.getColorClassName({
classNameTypes: [ColorClassNameTypes.TOOLTIP]
Expand Down
Loading

0 comments on commit 60ef1ec

Please sign in to comment.