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

fix: Several date/time components use locales correctly #2440

Merged
merged 6 commits into from
Nov 6, 2020
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
14 changes: 12 additions & 2 deletions packages/base/src/locale/getLocale.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -22,7 +32,7 @@ const getLocale = lang => {
}

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

return convertToLocaleOrNull(detectNavigatorLanguage());
Expand Down
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
Expand Up @@ -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";
Expand Down Expand Up @@ -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);
Expand All @@ -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();

Expand All @@ -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
Expand Down Expand Up @@ -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() {
Expand Down
5 changes: 3 additions & 2 deletions packages/main/src/DatePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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() {
Expand Down
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 {
Expand Down Expand Up @@ -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;
}

/**
Expand Down
27 changes: 16 additions & 11 deletions packages/main/src/DayPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -249,6 +248,8 @@ class DayPicker extends UI5Element {
}

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

let oCalDate,
day,
timestamp,
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -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;

Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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() {
Expand Down
12 changes: 7 additions & 5 deletions packages/main/src/MonthPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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",
};

Expand Down Expand Up @@ -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() {
Expand Down
5 changes: 3 additions & 2 deletions packages/main/src/TimePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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) {
Expand Down
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";
Expand All @@ -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.
Expand Down Expand Up @@ -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() {
Expand Down
11 changes: 2 additions & 9 deletions packages/main/test/pages/Simple.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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
Expand Up @@ -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.");
});
Expand Down