Skip to content

Commit

Permalink
Merge pull request #226 from gpbl/spread-locale-utils
Browse files Browse the repository at this point in the history
New props for localization
  • Loading branch information
gpbl authored Oct 14, 2016
2 parents d10c436 + e74e884 commit a5db426
Show file tree
Hide file tree
Showing 20 changed files with 292 additions and 86 deletions.
4 changes: 4 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
| [captionElement](APIProps.md#captionelement) | | `Element` |
| [disabledDays](APIProps.md#disableddays) | | `Bool` |
| [enableOutsideDays](APIProps.md#enableoutsidedays) | false | `Bool` |
| [firstDayOfWeek](APIProps.md#firstdayofweek) | 0 | `Number` |
| [fixedWeeks](APIProps.md#fixedWeeks) | false | `Bool` |
| [fromMonth](APIProps.md#frommonth) | | `Date` |
| [initialMonth](APIProps.md#initialmonth) | Current month | `Date` |
| [locale](APIProps.md#locale) | en | `String` |
| [localeUtils](APIProps.md#localeutils) | | `Object` |
| [modifiers](APIProps.md#modifiers) | | `Object` |
| [months](APIProps.md#months) | | `Array<String>` |
| [navbarElement](APIProps.md#navbarelement) | | `Element` |
| [numberOfMonths](APIProps.md#numberofmonths) | 1 | `Number` |
| [onCaptionClick](APIProps.md#oncaptionclick) | | `(e: SyntethicEvent, currentMonth: Date) ⇒ void` |
Expand All @@ -33,3 +35,5 @@
| [tabIndex](APIProps.md#tabindex) | | `Number` |
| [toMonth](APIProps.md#tomonth) | | `Date` |
| [weekdayElement](APIProps.md#weekdayelement) | | `Element` |
| [weekdaysShort](APIProps.md#weekdaysshort) | | `Array<String>` |
| [weekdaysLong](APIProps.md#weekdayslong) | | `Array<String>` |
24 changes: 24 additions & 0 deletions docs/APIProps.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ A function returning a boolean indicating if a day is disabled. Set a `disabled`

Display the days outside the current month.

### firstDayOfWeek

**Type**: `Number` **Default**: `0` (Sunday)

The day to use as first day of the week, starting from `0` (Sunday) to `6` (Saturday).

### fixedWeeks

**Type**: `Bool` **Default**: `false`
Expand Down Expand Up @@ -74,6 +80,12 @@ By default the used locale is English (US). See also [Localization](Localization
An object of named functions returning a boolean: `modifier(day: Date) -> Bool`. When a function of this object evaluates `true`, its name is used as CSS modifier for the day's cell.
As default, the calendar includes `today` and `outside` modifiers. (_Outside_ are the days that appear on the calendar but don't belong to the current month).

### months

**Type**: `Array<String>` **Default**: `['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']`

An array containing the long weekdays names to use in the month's header.

### navbarElement

**Type**: `Element`
Expand Down Expand Up @@ -138,6 +150,18 @@ Custom React element to render the weekday cells in the header. It will receive
* localeUtils `Object`
* locale `String`

### weekdaysLong

**Type**: `Array<String>` **Default**: `['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']`

An array containing the long weekdays names to use in the month's header. Must start from Sunday.

### weekdaysShort

**Type**: `Array<String>` **Default**: `['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']`

An array containing the short weekdays names to use in the month's header. Must start from Sunday.

## Event handlers

### onCaptionClick
Expand Down
4 changes: 3 additions & 1 deletion docs/LocaleUtils.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# LocaleUtils

`LocaleUtils` is a set of functions used to localize the component (see: [Custom localization](LocalizationCustom.md)). You may want to implement your own `LocaleUtils`, or override some of its functions.
`LocaleUtils` is a set of functions used to localize the component (see: [Advanced localization](LocalizationAdvanced.md)). You may want to implement your own `LocaleUtils`, or override some of its functions.

> Usually you won't need to use these functions. The component can be localized using `months`, `weekdaysLong`, `weekdaysShort` and `firstDayOfWeek` props.
For example, this code renders the month's title as `M/YYYY` instead of the default:

Expand Down
38 changes: 35 additions & 3 deletions docs/Localization.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,39 @@

react-day-picker can be localized into any language (English being the default).

Here there are two options:
You can either set the localization props (`months`, `weekdaysLong`, `weekdaysShort` and `firstDayOfWeek` as shown in this [example](http://react-day-picker.js.org/Localization.html)) or use [moment.js](http://momentjs.com/) by importing the [provided utility](LocalizationMoment.md).

## Example

The following code will render the Day Picker in Italian, using Monday as first day of the week.

```jsx
import React from 'react';
import DayPicker from 'react-day-picker';

const MONTHS = ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio',
'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre',
'Dicembre'];

const WEEKDAYS_LONG = ['Domenica', 'Lunedì', 'Martedì',
'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'];

const WEEKDAYS_SHORT = ['Do', 'Lu', 'Ma', 'Me', 'Gi', 'Ve', 'Sa'];

export default function Localized() {
return (
<div>
<DayPicker
locale="it"
months={ MONTHS }
weekdaysLong={ WEEKDAYS_LONG }
weekdaysShort={ WEEKDAYS_SHORT }
firstDayOfWeek={ 1 }
/>
</div>
);
}
```

> For more advanced options, such as changing the way days and caption is displayed, see [Advanced Localization](LocalizationAdvanced.md).
1. [use the provided utility based on moment.js](LocalizationMoment.md)
2. [create your own localization (or use another i18n library)](LocalizationCustom.md)
4 changes: 2 additions & 2 deletions docs/LocalizationCustom.md → docs/LocalizationAdvanced.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Custom localization

You can define your custom utility to localize the day picker – for example to reduce the size of your JavaScript bundle without using [external libraries](LocalizationMoment.md).
You can define your custom utility to localize the day picker.

The `DayPicker` component uses [localeUtils](LocaleUtils.md), a small set of functions defining how to display the day picker for the given locale. To localize the component, you can overwrite its behavior by passing your own custom set of functions to the `localeUtils` props.
The `DayPicker` component internally uses [localeUtils](LocaleUtils.md), a small set of functions defining how to display the day picker for the given locale. You can overwrite its behavior by passing your own custom set of functions to the `localeUtils` props.

[See an example](http://react-day-picker.js.org/examples?localizedCustom).

Expand Down
14 changes: 7 additions & 7 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
* [react-day-picker](README.md)
* [Examples with code](Examples.md)
* [Basic usage](Basic.md)
* [Use of modifiers](Modifiers.md)
* [Examples with Code](Examples.md)
* [Basic Usage](Basic.md)
* [Use of Modifiers](Modifiers.md)
* [Styling](Styling.md)
* [Component API](API.md)
* [Component props](APIProps.md)
* [Component methods](APIMethods.md)
* [Component Props](APIProps.md)
* [Component Methods](APIMethods.md)
* [Localization](Localization.md)
* [Localization with moment.js](LocalizationMoment.md)
* [Custom localization](LocalizationCustom.md)
* [With moment.js](LocalizationMoment.md)
* [Advanced Localization](LocalizationAdvanced.md)
* [Tips](Tips.md)
* [Utilities](Utilities.md)
* [DateUtils](DateUtils.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/Utilities.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Utilities

* [DateUtils](DateUtils.md) – contain some date functions useful to setup modifiers.
* [LocaleUtils](LocaleUtils.md) - set of functions used to localize the component, usually [overridden](LocalizationCustom.md) by implementers.
* [LocaleUtils](LocaleUtils.md) - set of functions used to localize the component, usually [overridden](LocalizationAdvanced.md) by implementers.
24 changes: 15 additions & 9 deletions examples/src/Examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import FixedWeeks from './examples/FixedWeeks';
import InputField from './examples/InputField';
import InputFieldOverlay from './examples/InputFieldOverlay';
import Localized from './examples/Localized';
import LocalizedMoment from './examples/LocalizedMoment';
import LocalizedCustom from './examples/LocalizedCustom';
import Modifiers from './examples/Modifiers';
import Range from './examples/Range';
Expand Down Expand Up @@ -44,7 +45,7 @@ const EXAMPLES = {
},
selectable: {
title: 'Selectable Day',
description: "Use the <code>selectedDays</code> prop and <a href='http://react-day-picker.js.org/docs/DateUtils.html'>DateUtils</a> to select a day. Note how the selected day is stored in the parent component’s state.",
description: "Use the <code>selectedDays</code> prop and <a href='http://react-day-picker.js.org/DateUtils.html'>DateUtils</a> to select a day. Note how the selected day is stored in the parent component’s state.",
Component: SelectableDay,
},
disabled: {
Expand All @@ -64,7 +65,7 @@ const EXAMPLES = {
},
range: {
title: 'Range of Days - click',
description: "Select a range of days using the range functions available in <a href='http://react-day-picker.js.org/docs/DateUtils.html'>DateUtils</a>.",
description: "Select a range of days using the range functions available in <a href='http://react-day-picker.js.org/DateUtils.html'>DateUtils</a>.",
Component: Range,
},
rangeAdvanced: {
Expand All @@ -88,13 +89,18 @@ const EXAMPLES = {
Component: Restricted,
},
localized: {
title: 'Localization (moment.js)',
description: "This day picker is localized using moment.js. Note the use of the <a href='https://www.w3.org/TR/html/dom.html#the-dir-attribute'>dir attribute</a> to support <abbr title='Right to left'>RTL</abbr> languages. <a href='http://react-day-picker.js.org/docs/Localization.html'>Read more about localization</a>.",
title: 'Localization',
description: 'This example shows how to localize the calendar in Italian. Note the use of <code>firstDayOfWeek</code> to set Monday as first day of the week.',
Component: Localized,
},
localizedMoment: {
title: 'Localization with moment.js',
description: "This day picker is localized using moment.js. Note the use of the <a href='https://www.w3.org/TR/html/dom.html#the-dir-attribute'>dir attribute</a> to support <abbr title='Right to left'>RTL</abbr> languages. <a href='http://react-day-picker.js.org/Localization.html'>Read more about localization</a>.",
Component: LocalizedMoment,
},
localizedCustom: {
title: 'Localization (custom)',
description: "If you prefer to not include external libraries to localize the calendar, you can provide your own <code>localeUtils</code> which is basically a rewrite of the <a href='https://github.com/gpbl/react-day-picker/blob/master/src/LocaleUtils.js'>original one</a>. The following example provides Russian and English localizations. <a href='http://react-day-picker.js.org/docs/Localization.html'>Read more about localization</a>.",
title: 'Localization (advanced)',
description: "You can provide your own <code>localeUtils</code>. The following example provides Russian and English localizations. <a href='http://react-day-picker.js.org/Localization.html'>Read more about localization</a>.",
Component: LocalizedCustom,
},
yearNavigation: {
Expand Down Expand Up @@ -159,7 +165,7 @@ export default class Examples extends Component {
const links = Object.keys(EXAMPLES).map(name =>
<a
href={ `.?${name}` }
onClick={ e => {
onClick={ (e) => {
e.preventDefault();
history.push({ pathname: history.getCurrentLocation().pathname, search: `?${name}` });
} }
Expand Down Expand Up @@ -206,13 +212,13 @@ export default class Examples extends Component {
style={ { marginLeft: '1rem', marginTop: '0.5rem' } }
src="https://ghbtns.com/github-btn.html?user=gpbl&amp;repo=react-day-picker&amp;type=star&amp;count=true"
frameBorder={ 0 } scrolling={ 0 } width="110px" height="20px"
></iframe>
/>
</div>
</div>

<div className="Examples">
<h2>
{ EXAMPLES[currentExample].title }
{ EXAMPLES[currentExample].title }
</h2>
<p dangerouslySetInnerHTML={ { __html: EXAMPLES[currentExample].description } } />
<div className="Example">
Expand Down
60 changes: 19 additions & 41 deletions examples/src/examples/Localized.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,26 @@
import React from 'react';
import DayPicker from '../../../src';

// Use a custom util to format the calendar values according to the
// selected locale. This one is based on moment.js
import MomentLocaleUtils from 'react-day-picker/moment';
const MONTHS = ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio',
'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre',
'Dicembre'];

// Make sure moment.js has the required locale data
import 'moment/locale/ja';
import 'moment/locale/ar';
import 'moment/locale/it';
const WEEKDAYS_LONG = ['Domenica', 'Lunedì', 'Martedì',
'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'];

import '../../../src/style.css';
const WEEKDAYS_SHORT = ['Do', 'Lu', 'Ma', 'Me', 'Gi', 'Ve', 'Sa'];

export default class Localized extends React.Component {
constructor(props) {
super(props);
this.switchLocale = this.switchLocale.bind(this);
}
state = {
locale: 'en',
};
switchLocale(e) {
const locale = e.target.value || 'en';
this.setState({ locale });
}
render() {
const { locale } = this.state;
return (
<div>
<p>
<select onChange={ this.switchLocale }>
<option value="en">English</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ar">Arabic</option>
</select>
</p>
<DayPicker
dir={ locale === 'ar' ? 'rtl' : 'ltr' }
locale={ locale }
localeUtils={ MomentLocaleUtils }
modifiers={ { sunday: day => day.getDay() === 0 } }
/>
</div>
);
}
export default function Localized() {
return (
<div>
<DayPicker
locale="it"
months={ MONTHS }
weekdaysLong={ WEEKDAYS_LONG }
weekdaysShort={ WEEKDAYS_SHORT }
firstDayOfWeek={ 1 }
modifiers={ { sunday: day => day.getDay() === 0 } }
/>
</div>
);
}
48 changes: 48 additions & 0 deletions examples/src/examples/LocalizedMoment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import DayPicker from '../../../src';

// Use a custom util to format the calendar values according to the
// selected locale. This one is based on moment.js
import MomentLocaleUtils from 'react-day-picker/moment';

// Make sure moment.js has the required locale data
import 'moment/locale/ja';
import 'moment/locale/ar';
import 'moment/locale/it';

import '../../../src/style.css';

export default class LocalizedMoment extends React.Component {
constructor(props) {
super(props);
this.switchLocale = this.switchLocale.bind(this);
}
state = {
locale: 'en',
};
switchLocale(e) {
const locale = e.target.value || 'en';
this.setState({ locale });
}
render() {
const { locale } = this.state;
return (
<div>
<p>
<select onChange={ this.switchLocale }>
<option value="en">English</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ar">Arabic</option>
</select>
</p>
<DayPicker
dir={ locale === 'ar' ? 'rtl' : 'ltr' }
locale={ locale }
localeUtils={ MomentLocaleUtils }
modifiers={ { sunday: day => day.getDay() === 0 } }
/>
</div>
);
}
}
5 changes: 5 additions & 0 deletions examples/src/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,8 @@ select {
margin-bottom: 2em;
display: inline-block;
}

.Example-Code {
max-width: 800px;
margin: 0 auto;
}
5 changes: 3 additions & 2 deletions examples/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var webpack = require('webpack');
var path = require('path');
const webpack = require('webpack');
const path = require('path');

module.exports = {
devtool: 'source-map',
Expand Down Expand Up @@ -55,6 +55,7 @@ module.exports = {
'InputField',
'InputFieldOverlay',
'Localized',
'LocalizedMoment',
'LocalizedCustom',
'Modifiers',
'Range',
Expand Down
8 changes: 6 additions & 2 deletions src/Caption.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import React, { PropTypes } from 'react';
import DayPickerPropTypes from './PropTypes';

export default function Caption({ date, locale, localeUtils, onClick }) {
export default function Caption({ date, months, locale, localeUtils, onClick }) {
return (
<div className="DayPicker-Caption" onClick={ onClick } role="heading">
{localeUtils.formatMonthTitle(date, locale)}
{ months ?
`${months[date.getMonth()]} ${date.getFullYear()}` :
localeUtils.formatMonthTitle(date, locale)
}
</div>
);
}

Caption.propTypes = {
date: PropTypes.instanceOf(Date),
months: React.PropTypes.arrayOf(React.PropTypes.string),
locale: PropTypes.string,
localeUtils: DayPickerPropTypes.localeUtils,
onClick: PropTypes.func,
Expand Down
Loading

0 comments on commit a5db426

Please sign in to comment.