Skip to content

Commit 6a8ee60

Browse files
Use new Intl formatter instances where applicable. (#1845)
--------- Co-authored-by: Radoslav Karaivanov <[email protected]>
1 parent 66a3896 commit 6a8ee60

38 files changed

+500
-644
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

77
## [Unreleased]
8+
### Added
9+
- #### Localization
10+
- New localization implementation. Now you can set global localization for all localized Ignite UI components using the `registerI18n` and `setCurrentI18n` methods.
11+
- Calendar, Date Input, Date Picker and Date Range Picker components now implement the new localization for formatting as well, which internally uses new implementation of the Intl.
12+
- Added localization for Carousel, Chip, Combo, File Input and Tree. They now have `locale` and `resourceStrings` properties as well, which you can set to customize them individually.
13+
814
### Fixed
915
- #### Tooltip
1016
- Do not show tooltip when target is clicked [#1828](https://github.com/IgniteUI/igniteui-webcomponents/issues/1828)
17+
- #### Date input, Date picker, Date range picker
18+
- Default display format now follows strictly locale format as per specification without leading zeros.
1119

1220
## [6.3.6] - 2025-11-14
1321
### Fixed

package-lock.json

Lines changed: 10 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"@floating-ui/dom": "^1.7.4",
5757
"@lit-labs/virtualizer": "^2.1.1",
5858
"@lit/context": "^1.1.6",
59-
"igniteui-i18n-core": "0.6.0-alpha.4",
59+
"igniteui-i18n-core": "0.7.0-alpha.8",
6060
"lit": "^3.3.1"
6161
},
6262
"devDependencies": {
@@ -81,7 +81,7 @@
8181
"globby": "^15.0.0",
8282
"husky": "^9.1.7",
8383
"ig-typedoc-theme": "^7.0.0",
84-
"igniteui-i18n-resources": "0.6.0-alpha.4",
84+
"igniteui-i18n-resources": "0.7.0-alpha.8",
8585
"igniteui-theming": "^22.1.0",
8686
"keep-a-changelog": "^2.7.1",
8787
"lint-staged": "^16.2.6",

src/components/calendar/calendar.ts

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getDateFormatter } from 'igniteui-i18n-core';
12
import { html, nothing } from 'lit';
23
import { property, query, queryAll, state } from 'lit/decorators.js';
34
import { choose } from 'lit/directives/choose.js';
@@ -15,9 +16,7 @@ import {
1516
pageUpKey,
1617
shiftKey,
1718
} from '../common/controllers/key-bindings.js';
18-
import { watch } from '../common/decorators/watch.js';
1919
import { registerComponent } from '../common/definitions/register.js';
20-
import { createDateTimeFormatters } from '../common/localization/intl-formatters.js';
2120
import type { Constructor } from '../common/mixins/constructor.js';
2221
import { EventEmitterMixin } from '../common/mixins/event-emitter.js';
2322
import { partMap } from '../common/part-map.js';
@@ -219,30 +218,21 @@ export default class IgcCalendarComponent extends EventEmitterMixin<
219218
public formatOptions: Pick<Intl.DateTimeFormatOptions, 'month' | 'weekday'> =
220219
{ month: 'long', weekday: 'narrow' };
221220

222-
private _intl = createDateTimeFormatters(this.locale, {
223-
month: {
224-
month: this.formatOptions.month,
225-
},
226-
monthLabel: { month: 'long' },
227-
weekday: { weekday: 'short' },
228-
monthDay: { month: 'short', day: 'numeric' },
229-
yearLabel: { month: 'long', year: 'numeric' },
230-
});
231-
232-
@watch('locale')
233-
protected localeChange() {
234-
this._intl.locale = this.locale;
235-
}
236-
237-
@watch('formatOptions')
238-
protected formatOptionsChange() {
239-
this._intl.update({
240-
month: {
241-
month: this.formatOptions.month,
242-
},
243-
});
221+
private get _monthOptions(): Intl.DateTimeFormatOptions {
222+
return { month: this.formatOptions.month };
244223
}
245224

225+
private _monthLabelOptions: Intl.DateTimeFormatOptions = { month: 'long' };
226+
private _weekdayOptions: Intl.DateTimeFormatOptions = { weekday: 'short' };
227+
private _monthDayOptions: Intl.DateTimeFormatOptions = {
228+
month: 'short',
229+
day: 'numeric',
230+
};
231+
private _yearLabelOptions: Intl.DateTimeFormatOptions = {
232+
month: 'long',
233+
year: 'numeric',
234+
};
235+
246236
/** @private @hidden @internal */
247237
public async [focusActiveDate](options?: FocusOptions) {
248238
await this.updateComplete;
@@ -462,23 +452,34 @@ export default class IgcCalendarComponent extends EventEmitterMixin<
462452
active: CalendarDay,
463453
viewIndex: number
464454
) {
465-
const labelFmt = this._intl.get('monthLabel').format;
466-
const valueFmt = this._intl.get('month').format;
467-
const ariaLabel = `${labelFmt(active.native)}, ${this.resourceStrings.selectMonth}`;
455+
const label = getDateFormatter().formatDateTime(
456+
active.native,
457+
this.locale,
458+
this._monthLabelOptions
459+
);
460+
const value = getDateFormatter().formatDateTime(
461+
active.native,
462+
this.locale,
463+
this._monthOptions
464+
);
465+
const ariaLabel = `${label}, ${this.resourceStrings.selectMonth}`;
468466

469467
return html`
470468
<button
471469
part="months-navigation"
472470
aria-label=${ariaLabel}
473471
@click=${() => this.switchToMonths(viewIndex)}
474472
>
475-
${valueFmt(active.native)}
473+
${value}
476474
</button>
477475
`;
478476
}
479477

480478
protected renderYearButtonNavigation(active: CalendarDay, viewIndex: number) {
481-
const fmt = this._intl.get('yearLabel').format;
479+
const fmt = getDateFormatter().getIntlFormatter(
480+
this.locale,
481+
this._yearLabelOptions
482+
).format;
482483
const ariaLabel = `${active.year}, ${this.resourceStrings.selectYear}`;
483484
const ariaSkip = this._isDayView ? fmt(active.native) : active.year;
484485

@@ -548,19 +549,30 @@ export default class IgcCalendarComponent extends EventEmitterMixin<
548549

549550
protected renderHeaderDateSingle() {
550551
const date = this.value ?? CalendarDay.today.native;
551-
const day = this._intl.get('weekday').format(date);
552-
const month = this._intl.get('monthDay').format(date);
552+
const weekday = getDateFormatter().formatDateTime(
553+
date,
554+
this.locale,
555+
this._weekdayOptions
556+
);
557+
const monthDay = getDateFormatter().formatDateTime(
558+
date,
559+
this.locale,
560+
this._monthDayOptions
561+
);
553562
const separator =
554563
this.headerOrientation === 'vertical' ? html`<br />` : ' ';
555564

556-
const formatted = html`${day},${separator}${month}`;
565+
const formatted = html`${weekday},${separator}${monthDay}`;
557566

558567
return html`<slot name="header-date">${formatted}</slot>`;
559568
}
560569

561570
protected renderHeaderDateRange() {
562571
const values = this.values;
563-
const fmt = this._intl.get('monthDay').format;
572+
const fmt = getDateFormatter().getIntlFormatter(
573+
this.locale,
574+
this._monthDayOptions
575+
).format;
564576
const { startDate, endDate } = this.resourceStrings;
565577

566578
const start = this._hasValues ? fmt(first(values)) : startDate;

src/components/calendar/days-view/days-view.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1+
import { getDateFormatter } from 'igniteui-i18n-core';
12
import { html, nothing } from 'lit';
23
import { property, query, state } from 'lit/decorators.js';
3-
44
import { addThemingController } from '../../../theming/theming-controller.js';
55
import { addKeybindings } from '../../common/controllers/key-bindings.js';
66
import { blazorIndirectRender } from '../../common/decorators/blazorIndirectRender.js';
77
import { blazorSuppressComponent } from '../../common/decorators/blazorSuppressComponent.js';
88
import { watch } from '../../common/decorators/watch.js';
99
import { registerComponent } from '../../common/definitions/register.js';
10-
import { createDateTimeFormatters } from '../../common/localization/intl-formatters.js';
1110
import type { Constructor } from '../../common/mixins/constructor.js';
1211
import { EventEmitterMixin } from '../../common/mixins/event-emitter.js';
1312
import { partMap } from '../../common/part-map.js';
@@ -107,21 +106,17 @@ export default class IgcDaysViewComponent extends EventEmitterMixin<
107106
@property({ attribute: 'week-day-format' })
108107
public weekDayFormat: 'long' | 'short' | 'narrow' = 'narrow';
109108

110-
private _intl = createDateTimeFormatters(this.locale, {
111-
weekday: { weekday: this.weekDayFormat },
112-
label: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' },
113-
ariaWeekday: { weekday: 'long' },
114-
});
115-
116-
@watch('locale')
117-
protected localeChange() {
118-
this._intl.locale = this.locale;
109+
private get _weekdayOptions(): Intl.DateTimeFormatOptions {
110+
return { weekday: this.weekDayFormat };
119111
}
120112

121-
@watch('weekDayFormat')
122-
protected weekDayFormatChange() {
123-
this._intl.update({ weekday: { weekday: this.weekDayFormat } });
124-
}
113+
private _labelOptions: Intl.DateTimeFormatOptions = {
114+
weekday: 'long',
115+
year: 'numeric',
116+
month: 'long',
117+
day: 'numeric',
118+
};
119+
private _ariaWeekdayOptions: Intl.DateTimeFormatOptions = { weekday: 'long' };
125120

126121
@watch('weekStart')
127122
@watch('activeDate')
@@ -336,7 +331,10 @@ export default class IgcDaysViewComponent extends EventEmitterMixin<
336331
}
337332

338333
private intlFormatDay(day: CalendarDay) {
339-
const fmt = this._intl.get('label');
334+
const fmt = getDateFormatter().getIntlFormatter(
335+
this.locale,
336+
this._labelOptions
337+
);
340338

341339
// Range selection in progress
342340
if (this._rangePreviewDate?.equalTo(day)) {
@@ -444,8 +442,14 @@ export default class IgcDaysViewComponent extends EventEmitterMixin<
444442
}
445443

446444
protected renderHeaders() {
447-
const label = this._intl.get('weekday');
448-
const aria = this._intl.get('ariaWeekday');
445+
const label = getDateFormatter().getIntlFormatter(
446+
this.locale,
447+
this._weekdayOptions
448+
);
449+
const aria = getDateFormatter().getIntlFormatter(
450+
this.locale,
451+
this._ariaWeekdayOptions
452+
);
449453
const days = take(
450454
generateMonth(this._activeDate, this._firstDayOfWeek),
451455
daysInWeek

src/components/calendar/months-view/months-view.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1+
import { getDateFormatter } from 'igniteui-i18n-core';
12
import { html, LitElement } from 'lit';
23
import { property, query, state } from 'lit/decorators.js';
34
import { range } from 'lit/directives/range.js';
4-
55
import { addThemingController } from '../../../theming/theming-controller.js';
66
import { addKeybindings } from '../../common/controllers/key-bindings.js';
77
import { blazorIndirectRender } from '../../common/decorators/blazorIndirectRender.js';
88
import { blazorSuppressComponent } from '../../common/decorators/blazorSuppressComponent.js';
9-
import { watch } from '../../common/decorators/watch.js';
109
import { registerComponent } from '../../common/definitions/register.js';
11-
import { createDateTimeFormatters } from '../../common/localization/intl-formatters.js';
1210
import type { Constructor } from '../../common/mixins/constructor.js';
1311
import { EventEmitterMixin } from '../../common/mixins/event-emitter.js';
1412
import { partMap } from '../../common/part-map.js';
@@ -67,20 +65,14 @@ export default class IgcMonthsViewComponent extends EventEmitterMixin<
6765
public monthFormat: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow' =
6866
'long';
6967

70-
private _intl = createDateTimeFormatters(this.locale, {
71-
month: { month: this.monthFormat },
72-
ariaMonth: { month: 'long', year: 'numeric' },
73-
});
74-
75-
@watch('locale')
76-
protected localeChange() {
77-
this._intl.locale = this.locale;
68+
private get _monthOptions(): Intl.DateTimeFormatOptions {
69+
return { month: this.monthFormat };
7870
}
7971

80-
@watch('monthFormat')
81-
protected formatChange() {
82-
this._intl.update({ month: { month: this.monthFormat } });
83-
}
72+
private _ariaMonthOptions: Intl.DateTimeFormatOptions = {
73+
month: 'long',
74+
year: 'numeric',
75+
};
8476

8577
constructor() {
8678
super();
@@ -110,8 +102,16 @@ export default class IgcMonthsViewComponent extends EventEmitterMixin<
110102
}
111103

112104
protected renderMonth(entry: CalendarDay, now: CalendarDay) {
113-
const ariaLabel = this._intl.get('ariaMonth').format(entry.native);
114-
const value = this._intl.get('month').format(entry.native);
105+
const ariaLabel = getDateFormatter().formatDateTime(
106+
entry.native,
107+
this.locale,
108+
this._ariaMonthOptions
109+
);
110+
const value = getDateFormatter().formatDateTime(
111+
entry.native,
112+
this.locale,
113+
this._monthOptions
114+
);
115115

116116
const active = areSameMonth(this._value, entry);
117117
const current = areSameMonth(now, entry);

src/components/carousel/carousel.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ export default class IgcCarouselComponent extends EventEmitterMixin<
281281
public animationType: HorizontalTransitionAnimation = 'slide';
282282

283283
/**
284-
* Gets/Sets the locale used for formatting and displaying the dates in the component.
284+
* Gets/Sets the locale used for getting language, affecting resource strings.
285285
* @attr locale
286286
*/
287287
@property()
@@ -295,6 +295,7 @@ export default class IgcCarouselComponent extends EventEmitterMixin<
295295

296296
/**
297297
* The resource strings for localization.
298+
* Currently only aria-label attributes are localized for the carousel.
298299
*/
299300
@property({ attribute: false })
300301
public set resourceStrings(value: ICarouselResourceStrings) {

0 commit comments

Comments
 (0)