Multilanguage calendar

by Qwerty_Wasd

HTML

<div class="control">
    <input type="number" id="month" min="1" max="12" placeholder="Месяц" value="6">
    <input type="number" id="year" min="1970" placeholder="Год" value="2018">
    <button>ru</button>
    <button>en</button>
    <button>uk</button>
    <button>fr</button>
    <button>de</button>
    <button>pl</button>
    <button>ar</button>
</div>
<output></output>

CSS

.calendar {
    display: grid;
    grid-template-columns: 3.125rem 3.125rem 3.125rem 3.125rem 3.125rem 3.125rem 3.125rem;
    grid-template-rows: 3.125rem 3.125rem 3.125rem 3.125rem 3.125rem 3.125rem 3.125rem 3.125rem;
    grid-gap: 0.0625rem;
}

.calendar div {
    text-align: center;
    border: 0.0625rem solid #999;
}

.calendar div.blur {
    color: #ccc;
}

.calendar div:nth-child(1),
.calendar div.day_name {
    background: -webkit-linear-gradient(top, #ffffff 0%, #e5e5e5 100%);
    background: linear-gradient(to bottom, #ffffff 0%, #e5e5e5 100%);
    font-weight: bold;
    text-shadow: 0.0625rem 0.0625rem 0.0625rem #ffffff;
}

.calendar div:nth-child(1) {
    grid-column: 1/8;
    padding-right: 1rem;
    font-weight: bold;
    text-align: right;
    font-size: 1.2rem;
}

.calendar div:nth-child(7),
.calendar div:nth-child(8) {
    color: #f00;
}

.calendar div::before {
    content: '';
    display: inline-block;
    height: 100%;
    vertical-align: middle;
}

.calendar div:nth-child(2) div {
    font-weight: bold;
}

.control {
    margin-bottom: 0.625rem;
}

output {
    display: inline-block;
}

button {
    text-transform: uppercase;
}

JavaScript

[...document.querySelectorAll('button')].forEach(btn => {
    btn.addEventListener('click', e => {
        let cl = new Calendar(+month.value, +year.value);
        cl.setLocale(e.target.textContent);
        cl.render('output');
    });
});

class Calendar {
    constructor(m = 1, y = 2018) {
        this.m = m;
        this.y = y;
        this.prevMonth = this.startFrom();
        let lsatDate = this.mDate(this.y, this.m, 0);
        this.currMonth = this.fillRange(1, lsatDate.getDate());
        this.nextMonth = this.fillRange(1, 7 - lsatDate.getDay());
        this.locale = 'ru';
    }
    setLocale(lc = '') {
        this.locale = lc;
    }
    startFrom() {
        let dn = this.mDate(this.y, this.m - 1, 1).getDay() || 7,
            ld = this.mDate(this.y, this.m - 1, 0).getDate();
        console.log(dn, ld);
        return dn !== 0 ? this.fillRange(ld - dn + 2, ld) : [];
    }
    mDate(y, m, d) {
        return new Date(y, m, d);
    }
    fillRange(start, end) {
        return Array(end - start + 1).fill().map((item, index) => start + index);
    }
    nonMonthDays(a) {
        return a.map(n => `<div class="blur">${n}</div>`);
    }
    daysName() {
        let str = '';
        let d = new Date();
        d.setDate(1);
        while (d.getDay() !== 1) {
            d.setDate(d.getDate() + 1);
        }

        for (var i = 0; i < 7; i++) {
            str += `<div class="day_name">${d.toLocaleString(this.locale, {
        weekday: 'short'
      })}</div>`;
            d.setDate(d.getDate() + 1)
        }
        return str;
    }
    firstLines() {
        return `<div>
    ${this.mDate(this.y, this.m-1, 1).toLocaleString(this.locale, {
    	month: 'long',
      year: 'numeric'
    })}
    </div>`;
    }
    render(target = 'body') {
        const days = this.nonMonthDays(this.prevMonth)
            .concat(this.currMonth.map(n => `<div>${n}</div>`))
            .concat(this.nonMonthDays(this.nextMonth));
       ...