Skip to content

Commit

Permalink
Feat: Detect and apply page language automatically
Browse files Browse the repository at this point in the history
  • Loading branch information
sandypockets committed Dec 8, 2023
1 parent d76caee commit 03c6dd5
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 16 deletions.
32 changes: 22 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ Is this the right library for me?

- You need a date picker with zero external dependencies.
- You need both single and/or range date selection.
- You need a localized date picker with translations included .
- You need a localized date picker with 10 languages included.
- You need a date picker that can automatically detect and display the correct language.
- Accessibility and cross-browser compatibility are important for your project.
- You need a date picker that can be easily styled beyond the defaults.
- Your project does not use a virtual DOM.
- You need a date picker that's lightning fast to set up.

## Getting started
Our Date Picker is as quick to set up as it is lightweight. Follow the directions and example below to learn how to integrate `easy-dates-picker` in your project.

### Package manager

Expand Down Expand Up @@ -55,7 +57,9 @@ const options = {
showDayNames: true, // Display the day name at the top of the calendar
textInputEnabled: true, // Display an input field with the selected date. The calendar becomes visible when clicking the input
darkMode: false, // Use light or dark colour scheme
language: 'en', // language ISO code, defaults to en
language: 'en', // language ISO code, defaults to en -> ignored if usePageLanguage is true
usePageLanguage: true, // Looks for a lang attribute on the page, and if the language is supported, uses it
usePageLanguageFallback: 'en' // If usePageLanguage is true, and the page language is not supported, use this language
};
```

Expand Down Expand Up @@ -93,14 +97,16 @@ datePicker.init();

```html
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<title>Test DatePicker</title>
<title>Easy Dates Picker Demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easy-dates-picker/dist/datepicker.css">
</head>
<body>
<!-- Date Picker mounted here -->
<div id="easy-dates-picker"></div>
<script src="https://cdn.jsdelivr.net/npm/easy-dates-picker/dist/datepicker.bundle.js"></script>
<!-- Initialize Date Picker in script -->
<script>
document.addEventListener('DOMContentLoaded', function () {
Expand All @@ -116,14 +122,20 @@ datePicker.init();
console.log('Date Selected:', startDate.toDateString());
}
}
const datePickerOptions = {
mode: 'single',
onSelect: datePickerCallback,
blockedDays: [0,6]
const options = {
mode: 'single', // 'single' or 'range', defaults to 'single'
onSelect: datePickerCallback, // Callback for whenever a date or date range is selected - Required
blockedDays: [0, 6], // Prevent Saturday and Sunday from being selected
showDayNames: true,
textInputEnabled: true, // Show input field, calendar displays on click
darkMode: false,
language: 'en', // language ISO code, defaults to en -> ignored if usePageLanguage is true
usePageLanguage: true, // Looks for a lang attribute on the page, and if the language is supported, uses it
usePageLanguageFallback: 'en' // If usePageLanguage is true, and the page language is not supported, use this language
};
const datePicker = new DatePicker('easy-dates-picker', datePickerOptions);
const datePicker = new DatePicker('easy-dates-picker', options);
datePicker.init();
});
</script>
Expand Down
50 changes: 50 additions & 0 deletions __tests__/datePicker.localization.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,55 @@ describe('Localization', () => {
const monthDisplay = datePicker.element.querySelector('.month-display').textContent;
expect(monthDisplay).toContain('八月 2023');
});
});

describe('Localization with Page Language', () => {
let datePicker;
const containerId = 'test-container';

beforeEach(() => {
document.body.innerHTML = `<div id="${containerId}"></div>`;
});

const setHtmlLangAttribute = (lang) => {
document.documentElement.lang = lang;
};

const testPageLanguageSetting = (lang, expectedDayName, expectedMonthName) => {
test(`adapts to page language ${lang}`, () => {
setHtmlLangAttribute(lang);
datePicker = new DatePicker(containerId, {
mode: 'single',
onSelect: jest.fn(),
usePageLanguage: true
});
datePicker.init();
datePicker.currentDate = new Date(2023, 0, 1); // January 1, 2023
datePicker.render();

const dayNames = datePicker.element.querySelector('.datepicker-day-names').textContent;
const monthDisplay = datePicker.element.querySelector('.month-display').textContent;

expect(dayNames).toContain(expectedDayName);
expect(monthDisplay).toContain(expectedMonthName);
});
};


testPageLanguageSetting('en', 'Sun', 'January 2023');
testPageLanguageSetting('fr', 'Dim', 'Janvier 2023');
testPageLanguageSetting('es', 'Dom', 'Enero 2023');
testPageLanguageSetting('de', 'So', 'Januar 2023');
testPageLanguageSetting('it', 'Dom', 'Gennaio 2023');
testPageLanguageSetting('nl', 'Zo', 'Januari 2023');
testPageLanguageSetting('pt', 'Dom', 'Janeiro 2023');
testPageLanguageSetting('ja', '日', '一月 2023');
testPageLanguageSetting('zh-CN', '日', '一月 2023');
testPageLanguageSetting('zh-TW', '日', '一月 2023');
testPageLanguageSetting('ru', 'Вс', 'Январь 2023');

afterEach(() => {
setHtmlLangAttribute('en');
});
});

2 changes: 1 addition & 1 deletion dist/datepicker.bundle.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions example/index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
Expand All @@ -26,7 +26,9 @@
showDayNames: true,
textInputEnabled: true, // Show input field, calendar displays on click
darkMode: false,
language: 'en', // language ISO code, defaults to en
language: 'en', // language ISO code, defaults to en -> ignored if usePageLanguage is true
usePageLanguage: true, // Looks for a lang attribute on the page, and if the language is supported, uses it
usePageLanguageFallback: 'en', // If usePageLanguage is true, and the page language is not supported, use this language
};

const datePicker = new DatePicker('easy-dates-picker', options);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "easy-dates-picker",
"version": "0.0.14",
"version": "0.0.15",
"description": "A super lightweight vanilla JS date picker",
"main": "dist/datepicker.bundle.js",
"files": [
Expand Down
9 changes: 7 additions & 2 deletions src/datePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { attachEventListeners } from './eventHandlers';
import { generateCalendarContainer } from './generateCalendarContainer';
import currentDates from './currentDates';
import { inputPlaceholderTranslations } from './localization';
import { getPageLanguage } from './utils';

export default function DatePicker(elementId, options) {
this.element = document.getElementById(elementId);
Expand All @@ -17,8 +18,12 @@ export default function DatePicker(elementId, options) {
showDayNames: options?.showDayNames ?? true,
textInputEnabled: options?.textInputEnabled ?? false,
darkMode: options?.darkMode ?? false,
language: options?.language ?? 'en',
textInputPlaceholder: options?.textInputPlaceholder ?? inputPlaceholderTranslations[options?.language ?? 'en'],
usePageLanguage: options?.usePageLanguage ?? false,
usePageLanguageFallback: options?.usePageLanguageFallback ?? 'en',
language: options?.usePageLanguage ? getPageLanguage(options?.usePageLanguageFallback) : options?.language ?? 'en',
textInputPlaceholder:
options?.textInputPlaceholder ??
inputPlaceholderTranslations[options?.usePageLanguage ? getPageLanguage() : options?.language ?? 'en'],
};
this.init = function () {
if (this.options.darkMode) this.element.classList.add('dark');
Expand Down
7 changes: 7 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ export function getMonthName(monthIndex, language) {
export function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}

export function getPageLanguage(fallbackLang) {
const supportedLanguages = ['en', 'fr', 'es', 'de', 'it', 'nl', 'pt', 'ja', 'zh-CN', 'zh-TW', 'ru'];
const documentPageLang = document.documentElement.lang;
// Check if the page language is supported, if not, default to English
return supportedLanguages.includes(documentPageLang) ? documentPageLang : fallbackLang;
}

0 comments on commit 03c6dd5

Please sign in to comment.