UNPKG

react-intl-formatted-duration

Version:
196 lines (135 loc) 7.37 kB
# Formatted Duration [react-intl](https://github.com/yahoo/react-intl) is an amazing library providing React components and API to localize your application, however it lacks a `Duration` component. If you want to show the time it takes to do something like `1 minute` or `5 minutes` or even a simple timer `0:30` you're [out of luck](https://github.com/yahoo/react-intl/issues/77) because the ECMA committee hasn't specified the [DurationFormat](https://github.com/tc39/ecma402/issues/47) yet. This component provides a very simple abstraction that works on React (DOM), React Native and any other target environment to format simple durations. ## Usage `npm i --save react-intl-formatted-duration` ### Extended format ```js // Using React DOM import React from 'react'; import FormattedDuration from 'react-intl-formatted-duration'; export default MyComponent() { return <FormattedDuration seconds={60} /> // will render `1 minute` } ``` The default format only shows minutes and seconds. For more complex needs check the [custom format section](#Custom_format). By default the output text is wrapped in a `span`, you can specify any component you like available on your target environment: ```js // Using React Native import React from 'react'; import FormattedDuration from 'react-intl-formatted-duration'; import { Text } from 'react-native'; export default MyComponent() { return <FormattedDuration seconds={60} textComponent={Text} /> // will render `1 minute` } ``` ```js // Using styled components import React from 'react'; import FormattedDuration from 'react-intl-formatted-duration'; import styled from 'styled-components'; const Text = styled.span``; export default MyComponent() { return <FormattedDuration seconds={60} textComponent={Text} /> // will render `1 minute` } ``` #### Styling numbers If you want to style numbers differently from text you can pass a `valueComponent` ```js <FormattedDuration seconds={90} textComponent={Text} valueComponent={Value} /> // renders <Value>1</Value> <Text>minute</Text> <Value>30</Value> <Text>seconds</Text> ``` Having different components is useful not only for styling. Some languages use different [numbering systems](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat). For example Japanese has full-width numbers, so you might want to render `10分` instead of `10分`, to do so you can use: ```js import React from 'react'; import { FormattedNumber } from 'react-intl'; import FormattedDuration from 'react-intl-formatted-duration'; /* You'll also need to select Japanese locale and configure the IntlProvider to use `ja-JP-u-nu-fullwide` Somewhere in you application import { IntlProvider } from 'react-intl'; <IntlProvider locale="ja-JP-u-nu-fullwide" /> */ export default MyComponent() { return <FormattedDuration seconds={600} textComponent={Text} valueComponent={FormattedNumber} /> // will render `10分` } ``` ### Custom format #### Hours and days By default the component only renders minutes and seconds, if you want to display hours or days you can use a custom format: ```js <FormattedDuration seconds={180000} format="{days} {hours} {minutes} {seconds}" /> // will render `2 days 2 hours` <FormattedDuration seconds={180000} format="{hours} {minutes} {seconds}" /> // will render `50 hours` <FormattedDuration seconds={180000} format="{minutes} {seconds}" /> // will render `3000 minutes` } ``` Seconds is also optional and if missing, minutes will be rounded to the closed value ```js <FormattedDuration seconds={10} format="{minutes}" /> // will render `0 minutes` <FormattedDuration seconds={30} format="{minutes}" /> // will render `1 minute` <FormattedDuration seconds={70} format="{minutes}" /> // will render `1 minute` ``` The custom format can itself be localized by passing a message id instead of the actual value ```js import React from 'react'; import FormattedDuration from 'react-intl-formatted-duration'; import messages from './messages'; export default MyComponent() { return ( <FormattedDuration seconds={600} format={messages.customFormat.id} /> ); } ``` #### Unit display While `format` allows to select which units to render, `unitDisplay` allows to configure the way each unit is rendered. ```js <FormattedDuration seconds={60} unitDisplay="long" /> // will render `1 minute` <FormattedDuration seconds={60} unitDisplay="short" /> // will render `1 min` <FormattedDuration seconds={60} unitDisplay="narrow" /> // will render `1m` ``` #### Timer format ```js import FormattedDuration, { TIMER_FORMAT } from 'react-intl-formatted-duration'; export default MyComponent() { return <FormattedDuration seconds={60} format={TIMER_FORMAT} /> // will render `1:00` } ``` ## Localization `react-intl-formatted-duration` expects the following keys inside your translation file * `react-intl-formatted-duration.longFormatting` the default format that generates something like `1 minute 30 seconds`. It uses the values `{days}`, `{hours}`, `{minutes}` and `{seconds}`. For example you can change it to `{minutes} and {seconds}`. * `react-intl-formatted-duration.duration` the format used by the `minutes` and `seconds` variables described above. It uses the values `{value}` and `{unit}`. The default is `{value} {unit}` where `value` is a number and `{unit}` is the textual unit like `minute(s)` or `second(s)`. * `react-intl-formatted-duration.timerFormatting` format for `TIMER_FORMAT`, defaults to `{minutes}:{seconds}` where both values are numbers padded to have a minimum length of 2 characters * `react-intl-formatted-duration.daysUnit` string for formatting days, default `{value, plural, one {day} other {days}}` * `react-intl-formatted-duration.hoursUnit` string for formatting hours, default `{value, plural, one {hour} other {hours}}` * `react-intl-formatted-duration.minutesUnit` string for formatting minutes, default `{value, plural, one {minute} other {minutes}}` * `react-intl-formatted-duration.secondsUnit` string for formatting seconds, default `{value, plural, one {second} other {seconds}}` The messages for `daysUnit`, `hoursUnit`, `minutesUnit`, `secondsUnit` use the [format-js syntax](https://formatjs.io/guides/message-syntax/) and are only used when `unitDisplay` is not specified. If you're using the `extract-intl` script from [react-boilerplate](https://github.com/react-boilerplate/react-boilerplate) you can import `react-intl-formatted-duration/messages` to automatically generate the keys in your translation files. ## Upgrading from version 1.0 Version `2.x` allows to use the whole power of format-js message syntax. All you need to do is remove all keys like `daysSingular`, `dayPlural` and simply use `daysUnit` with the format described above. ## Upgrading from version 2.0 Version `3.x` has exactly the same API as version `2.x` but is a complete rewrite. You don't need to change your code. ## Upgrading from version 3.0 Version `4.x` doesn't change any of the default behavior of version `3.x` and only contains new features. However internally it bumps the version of `intl-unofficial-duration-unit-format` from `1.x` to `3.x` which now requires `Intl.NumberFormat` to be available globally. If you've installed `react-intl` correctly, chances are you don't need to change your code.