Skip to content

Commit

Permalink
fix: Several date/time components use locales correctly (#2440)
Browse files Browse the repository at this point in the history
vladitasev authored Nov 6, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 095204f commit dd87a53
Showing 11 changed files with 70 additions and 40 deletions.
14 changes: 12 additions & 2 deletions packages/base/src/locale/getLocale.js
Original file line number Diff line number Diff line change
@@ -2,10 +2,20 @@ import detectNavigatorLanguage from "../util/detectNavigatorLanguage.js";
import { getLanguage as getConfigLanguage } from "../config/Language.js";
import Locale from "./Locale.js";

const cache = new Map();

const getLocaleInstance = lang => {
if (!cache.has(lang)) {
cache.set(lang, new Locale(lang));
}

return cache.get(lang);
};

const convertToLocaleOrNull = lang => {
try {
if (lang && typeof lang === "string") {
return new Locale(lang);
return getLocaleInstance(lang);
}
} catch (e) {
// ignore
@@ -22,7 +32,7 @@ const getLocale = lang => {
}

if (getConfigLanguage()) {
return new Locale(getConfigLanguage());
return getLocaleInstance(getConfigLanguage());
}

return convertToLocaleOrNull(detectNavigatorLanguage());
13 changes: 13 additions & 0 deletions packages/localization/src/getCachedLocaleDataInstance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import LocaleData from "./LocaleData.js";

const cache = new Map();

const getCachedLocaleDataInstance = locale => {
if (!cache.has(locale)) {
cache.set(locale, LocaleData.getInstance(locale));
}

return cache.get(locale);
};

export default getCachedLocaleDataInstance;
10 changes: 5 additions & 5 deletions packages/main/src/Calendar.js
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ import { fetchCldr } from "@ui5/webcomponents-base/dist/asset-registries/LocaleD
import { getCalendarType } from "@ui5/webcomponents-base/dist/config/CalendarType.js";
import getLocale from "@ui5/webcomponents-base/dist/locale/getLocale.js";
import DateFormat from "@ui5/webcomponents-localization/dist/DateFormat.js";
import LocaleData from "@ui5/webcomponents-localization/dist/LocaleData.js";
import getCachedLocaleDataInstance from "@ui5/webcomponents-localization/dist/getCachedLocaleDataInstance.js";
import CalendarDate from "@ui5/webcomponents-localization/dist/dates/CalendarDate.js";
import CalendarType from "@ui5/webcomponents-base/dist/types/CalendarType.js";
import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
@@ -209,8 +209,6 @@ class Calendar extends UI5Element {

constructor() {
super();
this._oLocale = getLocale();
this._oLocaleData = new LocaleData(this._oLocale);
this._header = {};
this._header.onPressPrevious = this._handlePrevious.bind(this);
this._header.onPressNext = this._handleNext.bind(this);
@@ -235,6 +233,7 @@ class Calendar extends UI5Element {
}

onBeforeRendering() {
const localeData = getCachedLocaleDataInstance(getLocale());
const oYearFormat = DateFormat.getDateInstance({ format: "y", calendarType: this._primaryCalendarType });
const firstDayOfCalendarTimeStamp = this._getMinCalendarDate();

@@ -252,7 +251,7 @@ class Calendar extends UI5Element {
this._oMonth.primaryCalendarType = this._primaryCalendarType;
this._oMonth.minDate = this.minDate;
this._oMonth.maxDate = this.maxDate;
this._header.monthText = this._oLocaleData.getMonths("wide", this._primaryCalendarType)[this._month];
this._header.monthText = localeData.getMonths("wide", this._primaryCalendarType)[this._month];
this._header.yearText = oYearFormat.format(this._localDate, true);

// month picker
@@ -352,7 +351,8 @@ class Calendar extends UI5Element {
}

get _primaryCalendarType() {
return this.primaryCalendarType || getCalendarType() || LocaleData.getInstance(getLocale()).getPreferredCalendarType();
const localeData = getCachedLocaleDataInstance(getLocale());
return this.primaryCalendarType || getCalendarType() || localeData.getPreferredCalendarType();
}

get _formatPattern() {
5 changes: 3 additions & 2 deletions packages/main/src/DatePicker.js
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ import { fetchCldr } from "@ui5/webcomponents-base/dist/asset-registries/LocaleD
import { getCalendarType } from "@ui5/webcomponents-base/dist/config/CalendarType.js";
import getLocale from "@ui5/webcomponents-base/dist/locale/getLocale.js";
import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
import LocaleData from "@ui5/webcomponents-localization/dist/LocaleData.js";
import getCachedLocaleDataInstance from "@ui5/webcomponents-localization/dist/getCachedLocaleDataInstance.js";
import DateFormat from "@ui5/webcomponents-localization/dist/DateFormat.js";
import CalendarType from "@ui5/webcomponents-base/dist/types/CalendarType.js";
import CalendarDate from "@ui5/webcomponents-localization/dist/dates/CalendarDate.js";
@@ -761,7 +761,8 @@ class DatePicker extends UI5Element {
}

get _primaryCalendarType() {
return this.primaryCalendarType || getCalendarType() || LocaleData.getInstance(getLocale()).getPreferredCalendarType();
const localeData = getCachedLocaleDataInstance(getLocale());
return this.primaryCalendarType || getCalendarType() || localeData.getPreferredCalendarType();
}

get _formatPattern() {
5 changes: 3 additions & 2 deletions packages/main/src/DateTimePicker.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import getLocale from "@ui5/webcomponents-base/dist/locale/getLocale.js";
import LocaleData from "@ui5/webcomponents-localization/dist/LocaleData.js";
import getCachedLocaleDataInstance from "@ui5/webcomponents-localization/dist/getCachedLocaleDataInstance.js";
import CalendarDate from "@ui5/webcomponents-localization/dist/dates/CalendarDate.js";
import "@ui5/webcomponents-icons/dist/date-time.js";
import {
@@ -532,7 +532,8 @@ class DateTimePicker extends DatePicker {
const hasHours = !!pattern.match(/H/i);
const fallback = !pattern || !hasHours;

return fallback ? LocaleData.getInstance(getLocale()).getCombinedDateTimePattern("medium", "medium", this._primaryCalendarType) : pattern;
const localeData = getCachedLocaleDataInstance(getLocale());
return fallback ? localeData.getCombinedDateTimePattern("medium", "medium", this._primaryCalendarType) : pattern;
}

/**
27 changes: 16 additions & 11 deletions packages/main/src/DayPicker.js
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ import { fetchCldr } from "@ui5/webcomponents-base/dist/asset-registries/LocaleD
import getLocale from "@ui5/webcomponents-base/dist/locale/getLocale.js";
import { getFirstDayOfWeek } from "@ui5/webcomponents-base/dist/config/FormatSettings.js";
import DateFormat from "@ui5/webcomponents-localization/dist/DateFormat.js";
import LocaleData from "@ui5/webcomponents-localization/dist/LocaleData.js";
import getCachedLocaleDataInstance from "@ui5/webcomponents-localization/dist/getCachedLocaleDataInstance.js";
import { getCalendarType } from "@ui5/webcomponents-base/dist/config/CalendarType.js";
import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js";
import {
@@ -56,6 +56,7 @@ const monthDiff = (startDate, endDate) => {
*/
const metadata = {
tag: "ui5-daypicker",
languageAware: true,
properties: /** @lends sap.ui.webcomponents.main.DayPicker.prototype */ {
/**
* A UNIX timestamp - seconds since 00:00:00 UTC on Jan 1, 1970.
@@ -212,8 +213,6 @@ class DayPicker extends UI5Element {

constructor() {
super();
this._oLocale = getLocale();
this._oLocaleData = new LocaleData(this._oLocale);

this._itemNav = new ItemNavigation(this, {
rowSize: 7,
@@ -249,6 +248,8 @@ class DayPicker extends UI5Element {
}

onBeforeRendering() {
const localeData = getCachedLocaleDataInstance(getLocale());

let oCalDate,
day,
timestamp,
@@ -261,7 +262,7 @@ class DayPicker extends UI5Element {
let week = [];
this._weekNumbers = [];
let weekday;
const _monthsNameWide = this._oLocaleData.getMonths("wide", this._calendarDate._oUDate.sCalendarType);
const _monthsNameWide = localeData.getMonths("wide", this._calendarDate._oUDate.sCalendarType);

this._minDateObject = new Date(this._minDate);
this._maxDateObject = new Date(this._maxDate);
@@ -335,7 +336,7 @@ class DayPicker extends UI5Element {

if (day.classes.indexOf("ui5-dp-wday6") !== -1
|| _aVisibleDays.length - 1 === i) {
const weekNumber = calculateWeekNumber(getFirstDayOfWeek(), oCalDate.toUTCJSDate(), oCalDate.getYear(), this._oLocale, this._oLocaleData);
const weekNumber = calculateWeekNumber(getFirstDayOfWeek(), oCalDate.toUTCJSDate(), oCalDate.getYear(), getLocale(), localeData);
if (lastWeekNumber !== weekNumber) {
const weekNum = {
weekNum: weekNumber,
@@ -358,8 +359,8 @@ class DayPicker extends UI5Element {
this._itemNav.current = todayIndex;
}

const aDayNamesWide = this._oLocaleData.getDays("wide", this._primaryCalendarType);
const aDayNamesAbbreviated = this._oLocaleData.getDays("abbreviated", this._primaryCalendarType);
const aDayNamesWide = localeData.getDays("wide", this._primaryCalendarType);
const aDayNamesAbbreviated = localeData.getDays("abbreviated", this._primaryCalendarType);
const aUltraShortNames = aDayNamesAbbreviated.map(n => n);
let dayName;

@@ -607,7 +608,8 @@ class DayPicker extends UI5Element {
}

get _primaryCalendarType() {
return this.primaryCalendarType || getCalendarType() || LocaleData.getInstance(getLocale()).getPreferredCalendarType();
const localeData = getCachedLocaleDataInstance(getLocale());
return this.primaryCalendarType || getCalendarType() || localeData.getPreferredCalendarType();
}

get focusableDays() {
@@ -793,9 +795,11 @@ class DayPicker extends UI5Element {
}

_isWeekend(oDate) {
const localeData = getCachedLocaleDataInstance(getLocale());

const iWeekDay = oDate.getDay(),
iWeekendStart = this._oLocaleData.getWeekendStart(),
iWeekendEnd = this._oLocaleData.getWeekendEnd();
iWeekendStart = localeData.getWeekendStart(),
iWeekendEnd = localeData.getWeekendEnd();

return (iWeekDay >= iWeekendStart && iWeekDay <= iWeekendEnd)
|| (iWeekendEnd < iWeekendStart && (iWeekDay >= iWeekendStart || iWeekDay <= iWeekendEnd));
@@ -926,8 +930,9 @@ class DayPicker extends UI5Element {
}

_getFirstDayOfWeek() {
const localeData = getCachedLocaleDataInstance(getLocale());
const confFirstDayOfWeek = getFirstDayOfWeek();
return Number.isInteger(confFirstDayOfWeek) ? confFirstDayOfWeek : this._oLocaleData.getFirstDayOfWeek();
return Number.isInteger(confFirstDayOfWeek) ? confFirstDayOfWeek : localeData.getFirstDayOfWeek();
}

get styles() {
12 changes: 7 additions & 5 deletions packages/main/src/MonthPicker.js
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import { getCalendarType } from "@ui5/webcomponents-base/dist/config/CalendarType.js";
import DateFormat from "@ui5/webcomponents-localization/dist/DateFormat.js";
import LocaleData from "@ui5/webcomponents-localization/dist/LocaleData.js";
import getCachedLocaleDataInstance from "@ui5/webcomponents-localization/dist/getCachedLocaleDataInstance.js";
import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js";
import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js";
@@ -19,6 +19,7 @@ import styles from "./generated/themes/MonthPicker.css.js";
*/
const metadata = {
tag: "ui5-monthpicker",
languageAware: true,
properties: /** @lends sap.ui.webcomponents.main.MonthPicker.prototype */ {
/**
* A UNIX timestamp - seconds since 00:00:00 UTC on Jan 1, 1970.
@@ -133,8 +134,6 @@ class MonthPicker extends UI5Element {

constructor() {
super();
this._oLocale = getLocale();
this._oLocaleData = new LocaleData(this._oLocale);

this._itemNav = new ItemNavigation(this, {
pageSize: 12,
@@ -164,6 +163,8 @@ class MonthPicker extends UI5Element {
}

onBeforeRendering() {
const localeData = getCachedLocaleDataInstance(getLocale());

const quarters = [];
const oCalDate = CalendarDate.fromTimestamp(new Date().getTime(), this._primaryCalendarType);
let timestamp;
@@ -175,7 +176,7 @@ class MonthPicker extends UI5Element {
const month = {
timestamp: timestamp.toString(),
id: `${this._id}-m${i}`,
name: this._oLocaleData.getMonths("wide", this._primaryCalendarType)[i],
name: localeData.getMonths("wide", this._primaryCalendarType)[i],
classes: "ui5-mp-item",
};

@@ -221,7 +222,8 @@ class MonthPicker extends UI5Element {
}

get _primaryCalendarType() {
return this.primaryCalendarType || getCalendarType() || LocaleData.getInstance(getLocale()).getPreferredCalendarType();
const localeData = getCachedLocaleDataInstance(getLocale());
return this.primaryCalendarType || getCalendarType() || localeData.getPreferredCalendarType();
}

get _isPattern() {
5 changes: 3 additions & 2 deletions packages/main/src/TimePicker.js
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18
import getLocale from "@ui5/webcomponents-base/dist/locale/getLocale.js";
import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js";
import DateFormat from "@ui5/webcomponents-localization/dist/DateFormat.js";
import LocaleData from "@ui5/webcomponents-localization/dist/LocaleData.js";
import getCachedLocaleDataInstance from "@ui5/webcomponents-localization/dist/getCachedLocaleDataInstance.js";
import "@ui5/webcomponents-localization/dist/features/calendar/Gregorian.js"; // default calendar for bundling
import { fetchCldr } from "@ui5/webcomponents-base/dist/asset-registries/LocaleData.js";
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";
@@ -345,7 +345,8 @@ class TimePicker extends UI5Element {

onBeforeRendering() {
if (!this.formatPattern) {
this.formatPattern = LocaleData.getInstance(getLocale()).getTimePattern(this.getFormat().oFormatOptions.style);
const localeData = getCachedLocaleDataInstance(getLocale());
this.formatPattern = localeData.getTimePattern(this.getFormat().oFormatOptions.style);
}

if (this.value === undefined) {
6 changes: 4 additions & 2 deletions packages/main/src/YearPicker.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import LocaleData from "@ui5/webcomponents-localization/dist/LocaleData.js";
import getCachedLocaleDataInstance from "@ui5/webcomponents-localization/dist/getCachedLocaleDataInstance.js";
import DateFormat from "@ui5/webcomponents-localization/dist/DateFormat.js";
import { getCalendarType } from "@ui5/webcomponents-base/dist/config/CalendarType.js";
import { isEnter, isSpace } from "@ui5/webcomponents-base/dist/Keys.js";
@@ -20,6 +20,7 @@ import styles from "./generated/themes/YearPicker.css.js";
*/
const metadata = {
tag: "ui5-yearpicker",
languageAware: true,
properties: /** @lends sap.ui.webcomponents.main.YearPicker.prototype */ {
/**
* A UNIX timestamp - seconds since 00:00:00 UTC on Jan 1, 1970.
@@ -244,7 +245,8 @@ class YearPicker extends UI5Element {
}

get _primaryCalendarType() {
return this.primaryCalendarType || getCalendarType() || LocaleData.getInstance(getLocale()).getPreferredCalendarType();
const localeData = getCachedLocaleDataInstance(getLocale());
return this.primaryCalendarType || getCalendarType() || localeData.getPreferredCalendarType();
}

get _isPattern() {
11 changes: 2 additions & 9 deletions packages/main/test/pages/Simple.html
Original file line number Diff line number Diff line change
@@ -7,15 +7,7 @@

<title>Button</title>

<script data-ui5-config type="application/json">
{
"language": "EN",
"noConflict": {
"events": ["click"]
},
"calendarType": "Islamic"
}
</script>


<script src="../../webcomponentsjs/webcomponents-loader.js"></script>
<script src="../../resources/bundle.esm.js" type="module"></script>
@@ -26,6 +18,7 @@
<body style="background-color: var(--sapBackgroundColor);">

<ui5-button icon="download"></ui5-button>
<ui5-datepicker></ui5-datepicker>

</body>
</html>
2 changes: 2 additions & 0 deletions packages/main/test/specs/MultiComboBox.spec.js
Original file line number Diff line number Diff line change
@@ -25,10 +25,12 @@ describe("MultiComboBox general interaction", () => {
assert.ok(mcb.getProperty("focused"), "MultiComboBox should be focused.");

input.keys("ArrowLeft");
browser.pause(100);

assert.notOk(mcb.getProperty("focused"), "MultiComboBox should no longer be focused.");

input.keys("ArrowRight");
browser.pause(100);

assert.ok(mcb.getProperty("focused"), "MultiComboBox should be focused again.");
});

0 comments on commit dd87a53

Please sign in to comment.