28 KiB
I18n Contribution Guide
Table of Contents
Adding a new locale
To add a new locale:
-
Copy the content of an existing locale (e.g.
en-US
) into the newly created directory. -
Replace the values in the content with yours file-by-file. Use CLDR data as a point of reference which values to choose.
All locales contain a number of properties:
formatDistance
— distance localizer function used byformatDistance
andformatDistanceStrict
.formatLong
— contains long date localizer functions used byformat
andformatRelative
.formatRelative
— relative date localizer function used byformatRelative
.localize
— contains functions, which localize the various date values. Required byformat
andformatRelative
.match
— contains functions to parse date values. Required byparse
.options
— contains the index of the first day of the week for functions such asstartOfWeek
, and the value which determines the first week of the year for functions likesetWeek
.
Choosing a directory name for a locale
Use the four letter code for the directory name (e.g. en-GB
),
Use the two/three letter code:
-
if the language code and the country code are the same (e.g.
pt
instead ofpt-PT
). -
if the language is used in only one country (e.g.
fil
instead offil-PH
). -
if all countries who use the language also use the same regional standards: the first day of the week, the week numbering (see: https://en.wikipedia.org/wiki/Week#Week_numbering), calendar date format (see: https://en.wikipedia.org/wiki/Calendar_date) and date representation (see: https://en.wikipedia.org/wiki/Date_and_time_representation_by_country and: https://en.wikipedia.org/wiki/Date_format_by_country) (e.g.
ca
instead ofca-ES
andca-AD
).
index.js
Locale's index.js
is where all the properties of the locale are combined in a single file,
documented in JSDoc format.
import formatDistance from './_lib/formatDistance/index.js'
import formatLong from './_lib/formatLong/index.js'
import formatRelative from './_lib/formatRelative/index.js'
import localize from './_lib/localize/index.js'
import match from './_lib/match/index.js'
/**
* @type {Locale}
* @category Locales
*
* // Name of the locale.
* // Inside the parentheses - name of the country - if the locale uses the four letter code, e.g. en-US, fr-CA or pt-BR.
* @summary English locale (United States).
*
* // Name of the language (used by https://date-fns.org/ website)
* @language English
*
* // ISO 639-2 code. See the list here:
* // https://www.loc.gov/standards/iso639-2/php/code_list.php
* // Used by https://date-fns.org/ to detect the list of the countries that uses the language.
* @iso-639-2 eng
*
* // Authors of the locale (including anyone who corrected or fixed the locale)
* @author Sasha Koss [@kossnocorp]{@link https://github.com/kossnocorp}
* @author Lesha Koss [@leshakoss]{@link https://github.com/leshakoss}
*/
var locale = {
code: 'en',
formatDistance: formatDistance,
formatLong: formatLong,
formatRelative: formatRelative,
localize: localize,
match: match,
options: {
// Index of the first day of the week.
// Sunday is 0, Monday is 1, Saturday is 6.
weekStartsOn: 0,
// Nth of January which is always in the first week of the year. See:
// https://en.wikipedia.org/wiki/Week#Week_numbering
// http://www.pjh2.de/datetime/weeknumber/wnd.php?l=en
firstWeekContainsDate: 1
}
}
export default locale
localize
Put this object in _lib/localize/index.js
inside your locale directory.
Contains a number of functions for used by format
:
var localize = {
ordinalNumber,
era,
quarter,
month,
day,
dayPeriod
}
export default localize
localize.ordinalNumber
Function that takes a numeric argument and returns a string with ordinal number:
// In `en-US` locale:
function ordinalNumber (dirtyNumber, dirtyOptions) {
var number = Number(dirtyNumber)
var rem100 = number % 100
if (rem100 > 20 || rem100 < 10) {
switch (rem100 % 10) {
case 1:
return number + 'st'
case 2:
return number + 'nd'
case 3:
return number + 'rd'
}
}
return number + 'th'
}
var localize = {
ordinalNumber: ordinalNumber,
// ...
}
If the form of the ordinal number depends on the grammatical case (or other grammatical structures),
use options.unit
argument which could be one of the values 'year', 'quarter', 'month', 'week',
'date', 'dayOfYear', 'day', 'hour', 'minute' or 'second':
// In `ru` locale:
function ordinalNumber (dirtyNumber, dirtyOptions) {
var options = dirtyOptions || {}
var unit = String(options.unit)
var suffix
if (unit === 'date') {
suffix = '-е'
} else if (unit === 'week' || unit === 'minute' || unit === 'second') {
suffix = '-я'
} else {
suffix = '-й'
}
return dirtyNumber + suffix
}
localize.era and using buildLocalizeFn function
Localizes a numeric era. Takes either 0 or 1 as the first argument.
As with many of the localize
functions, they can be generated by built-in
buildLocalizeFn
function.
From CLDR chart, use 'Date & Time'/'Gregorian'/'Eras' values.
// In `en-US` locale:
import buildLocalizeFn from '../../../_lib/buildLocalizeFn/index.js'
var eraValues = {
narrow: ['B', 'A'],
abbreviated: ['BC', 'AD'],
wide: ['Before Christ', 'Anno Domini']
}
var localize = {
// ...
era: buildLocalizeFn({
values: eraValues,
defaultWidth: 'wide'
}),
// ...
}
export default localize
General usage of the function:
var result = locale.localize.era(1, {width: 'abbreviated'})
//=> 'AD'
If width
is not provided or the values
object does not contain values for the provided width,
defaultWidth
will be used. defaultWidth
should indicate the longest form of the localized value.
The same is true for all other localize
functions.
width
for localize.era
function could be either 'narrow', 'abbreviated' or 'wide'.
var result = locale.localize.era(1, {width: 'foobar'})
//=> 'Anno Domini'
Formatting localizers
For some languages, there is a difference for "stand-alone" localizers and "formatting" localizers.
"Stand-alone" means that the resulting value should make grammatical sense without context.
"Formatting" means that the resulting value should be declined using the grammar rules of the language
as if the value was a part of a date.
For example, for languages with grammatical cases, stand-alone month could be in the nominative case ("January"),
and formatting month could decline as a part of phrase "1st of January".
In this case, use parameters formattingValues
and defaultFormattingWidth
of buildLocalizeFn
function.
Any localizer could be stand-alone and formatting.
Check the CLDR chart for the unit to see if stand-alone and formatting values are different for a certain unit.
If there's no difference (usually it happens in languages without grammatical cases),
parameters formattingValues
and defaultFormattingWidth
are not needed.
In this example, in Russian language a stand-alone month is in the nominative case ("январь"), and formatting month is in the genitive case ("января" as in "1-е января"). Notice the different endings:
// In `ru` locale:
var monthValues = {
narrow: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О', 'Н', 'Д'],
abbreviated: ['янв.', 'фев.', 'март', 'апр.', 'май', 'июнь', 'июль', 'авг.', 'сент.', 'окт.', 'нояб.', 'дек.'],
wide: ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь']
}
var formattingMonthValues = {
narrow: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О', 'Н', 'Д'],
abbreviated: ['янв.', 'фев.', 'мар.', 'апр.', 'мая', 'июн.', 'июл.', 'авг.', 'сент.', 'окт.', 'нояб.', 'дек.'],
wide: ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря']
}
var localize = {
// ...
month: buildLocalizeFn({
values: monthValues,
defaultWidth: 'wide',
formattingValues: formattingMonthValues,
defaultFormattingWidth: 'wide'
}),
// ...
}
export default localize
localize.quarter
Localizes a quarter. Takes 1, 2, 3 or 4 as the first argument.
width
could be either 'narrow', 'abbreviated' or 'wide'.
From CLDR chart, use 'Date & Time'/'Gregorian'/'Quarters' values.
// In `en-US` locale:
import buildLocalizeFn from '../../../_lib/buildLocalizeFn/index.js'
var quarterValues = {
narrow: ['1', '2', '3', '4'],
abbreviated: ['Q1', 'Q2', 'Q3', 'Q4'],
wide: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter']
}
var localize = {
// ...
quarter: buildLocalizeFn({
values: quarterValues,
defaultWidth: 'wide',
argumentCallback: function (quarter) {
return Number(quarter) - 1
}
}),
// ...
}
export default localize
Note the usage of argumentCallback
here. It converts the value passed into localize.quarter
function
(one of 1, 2, 3 or 4) into the index of the values array inside quarterValues
(one of 0, 1, 2 or 3).
localize.month
Localizes a month. Takes numbers between 0 (for January) and 11 (for December).
width
could be either 'narrow', 'abbreviated' or 'wide'.
From CLDR chart, use 'Date & Time'/'Gregorian'/'Months' values.
// In `en-US` locale:
import buildLocalizeFn from '../../../_lib/buildLocalizeFn/index.js'
var monthValues = {
narrow: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
abbreviated: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
wide: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
}
var localize = {
// ...
month: buildLocalizeFn({
values: monthValues,
defaultWidth: 'wide'
}),
// ...
}
export default localize
NOTE: in English, the names of days of the week and months are capitalized. Check if the same is true for the language you're working on. Generally, formatted dates should look like they are in the middle of a sentence, e.g. in Spanish language the weekdays and months should be in the lowercase:
// In `es` locale:
var monthValues = {
narrow: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
abbreviated: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.', 'sep.', 'oct.', 'nov.', 'dic.'],
wide: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre']
}
monthValues.narrow
are usually capitalized in every language. Check the CLDR chart for your language.
localize.day
Localizes a week day. Takes numbers between 0 (for Sunday) and 6 (for Saturday).
width
could be either 'narrow', 'short', 'abbreviated' or 'wide'.
From CLDR chart, use 'Date & Time'/'Gregorian'/'Days' values.
// In `en-US` locale:
import buildLocalizeFn from '../../../_lib/buildLocalizeFn/index.js'
var dayValues = {
narrow: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
short: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
abbreviated: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
wide: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
}
var localize = {
// ...
day: buildLocalizeFn({
values: dayValues,
defaultWidth: 'wide'
}),
// ...
}
export default localize
NOTE: the rules of capitalization from localize.month
are also true for localize.day
.
localize.dayPeriod
Localizes a certain day period.
Could take of these strings as the argument: 'am', 'pm', 'midnight', 'noon', 'morning', 'afternoon', 'evening', 'night'.
width
could be either 'narrow', 'abbreviated' or 'wide'.
From CLDR chart, use 'Date & Time'/'Gregorian'/'Day periods' values.
// In `en-US` locale:
import buildLocalizeFn from '../../../_lib/buildLocalizeFn/index.js'
var dayPeriodValues = {
narrow: {
am: 'a',
pm: 'p',
midnight: 'mi',
noon: 'n',
morning: 'in the morning',
afternoon: 'in the afternoon',
evening: 'in the evening',
night: 'at night'
},
abbreviated: {
am: 'AM',
pm: 'PM',
midnight: 'midnight',
noon: 'noon',
morning: 'in the morning',
afternoon: 'in the afternoon',
evening: 'in the evening',
night: 'at night'
},
wide: {
am: 'a.m.',
pm: 'p.m.',
midnight: 'midnight',
noon: 'noon',
morning: 'in the morning',
afternoon: 'in the afternoon',
evening: 'in the evening',
night: 'at night'
}
}
var localize = {
// ...
dayPeriod: buildLocalizeFn({
values: dayPeriodValues,
defaultWidth: 'wide'
})
}
export default localize
formatLong
Put this object in _lib/formatLong/index.js
inside your locale directory.
Locale date formats written in format
token string format.
See the list of tokens: https://date-fns.org/docs/format
Use https://en.wikipedia.org/wiki/Date_format_by_country and CLDR chart as the reference.
formatLong.dateFormats
Use 'Date & Time'/'Gregorian'/'Formats - Standard - Date Formats' values from the CLDR chart as a reference.
// In `en-US` locale
import buildFormatLongFn from '../../../_lib/buildFormatLongFn/index.js'
var dateFormats = {
full: 'EEEE, MMMM do, y',
long: 'MMMM do, y',
medium: 'MMM d, y',
short: 'MM/dd/yyyy'
}
var formatLong = {
date: buildFormatLongFn({
formats: dateFormats,
defaultWidth: 'full'
}),
// ...
}
export default formatLong
dateFormats.long
usually contains the longest form of writing the year, the month, and the day of the month.
Use ordinal day of the month ('do' token) where applicable (date-fns, unlike CLDR supports ordinal numbers).
dateFormats.full
contains the same but with the day of the week.
dateFormats.medium
contains the same values as dateFormats.long
, but with short form of month and non-ordinal day.
dateFormats.short
usually contains strictly numerical form of the date.
Pay attention to the order of units (big-, little- or middle-endian)
formatLong.timeFormats
Use 'Date & Time'/'Gregorian'/'Formats - Standard - Time Formats' values from the CLDR chart as a reference.
Use some variation of 'h:mm aa' for 12-hour clock locales or 'H:mm' for 24-hour clock locales. Use the local time separator.
// In `en-US` locale
import buildFormatLongFn from '../../../_lib/buildFormatLongFn/index.js'
var timeFormats = {
full: 'h:mm:ss a zzzz',
long: 'h:mm:ss a z',
medium: 'h:mm:ss a',
short: 'h:mm a'
}
var formatLong = {
// ...
time: buildFormatLongFn({
formats: timeFormats,
defaultWidth: 'full'
}),
// ...
}
export default formatLong
formatLong.dateTimeFormats
Use 'Date & Time'/'Gregorian'/'Formats - Standard - Date & Time Combination Formats' values from the CLDR chart.
// In `en-US` locale
import buildFormatLongFn from '../../../_lib/buildFormatLongFn/index.js'
var dateTimeFormats = {
full: "{{date}} 'at' {{time}}",
long: "{{date}} 'at' {{time}}",
medium: '{{date}}, {{time}}',
short: '{{date}}, {{time}}'
}
var formatLong = {
// ...
dateTime: buildFormatLongFn({
formats: dateTimeFormats,
defaultWidth: 'full'
})
}
export default formatLong
'{{date}}' and '{{time}}' from the strings will be replaced with the date and time respectively.
formatRelative
Put this function in _lib/formatRelative/index.js
inside your locale directory.
Relative date formats written in format
token string format.
See the list of tokens: https://date-fns.org/docs/format.
Has to process lastWeek
, yesterday
, today
, tomorrow
, nextWeek
and other
tokens.
// In `en-US` locale
var formatRelativeLocale = {
lastWeek: "'last' eeee 'at' p",
yesterday: "'yesterday at' p",
today: "'today at' p",
tomorrow: "'tomorrow at' p",
nextWeek: "eeee 'at' p",
other: 'P'
}
export default function formatRelative (token, date, baseDate, options) {
return formatRelativeLocale[token]
}
You can use date
and baseDate
supplied to the function for the difficult situations
(e.g. grammatical genders and cases of the days of the week)
Both date
and baseDate
are converted to UTC timezone, which means
that you should use UTC methods to take the date values (i.e. date.getUTCDay()
instead of date.getDay()
).
You can use UTC functions from src/_lib
in date-fns root directory if they are available.
Don't forget to pass options
object to them!
Example is below. Note the different grammatical case for weekdays (accusative instead of nominative)
and declension of word "прошлый" which depends on the grammatical gender of the weekday:
// In `ru` locale
import isSameUTCWeek from '../../../../_lib/isSameUTCWeek/index.js'
var accusativeWeekdays = ['воскресенье', 'понедельник', 'вторник', 'среду', 'четверг', 'пятницу', 'субботу']
function lastWeek (day) {
var weekday = accusativeWeekdays[day]
switch (day) {
case 0:
return "'в прошлое " + weekday + " в' p"
case 1:
case 2:
case 4:
return "'в прошлый " + weekday + " в' p"
case 3:
case 5:
case 6:
return "'в прошлую " + weekday + " в' p"
}
}
function thisWeek (day) {
// ...
}
function nextWeek (day) {
// ...
}
var formatRelativeLocale = {
lastWeek: function (date, baseDate, options) {
var day = date.getUTCDay()
if (isSameUTCWeek(date, baseDate, options)) {
return thisWeek(day)
} else {
return lastWeek(day)
}
},
yesterday: "'вчера в' p",
today: "'сегодня в' p",
tomorrow: "'завтра в' p",
nextWeek: function (date, baseDate, options) {
var day = date.getUTCDay()
if (isSameUTCWeek(date, baseDate, options)) {
return thisWeek(day)
} else {
return nextWeek(day)
}
},
other: 'P'
}
export default function formatRelative (token, date, baseDate, options) {
var format = formatRelativeLocale[token]
if (typeof format === 'function') {
return format(date, baseDate, options)
}
return format
}
match
Put this object in _lib/match/index.js
inside your locale directory.
Contains the functions used by parse
to parse a localized value:
// In `en-US` locale:
import buildMatchPatternFn from '../../../_lib/buildMatchPatternFn/index.js'
import buildMatchFn from '../../../_lib/buildMatchFn/index.js'
var matchOrdinalNumberPattern = /^(\d+)(th|st|nd|rd)?/i
var parseOrdinalNumberPattern = /\d+/i
var matchEraPatterns = {
narrow: /^(b|a)/i,
abbreviated: /^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,
wide: /^(before christ|before common era|anno domini|common era)/i
}
var parseEraPatterns = {
any: [/^b/i, /^(a|c)/i]
}
var matchQuarterPatterns = {
narrow: /^[1234]/i,
abbreviated: /^q[1234]/i,
wide: /^[1234](th|st|nd|rd)? quarter/i
}
var parseQuarterPatterns = {
any: [/1/i, /2/i, /3/i, /4/i]
}
var matchMonthPatterns = {
narrow: /^[jfmasond]/i,
abbreviated: /^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,
wide: /^(january|february|march|april|may|june|july|august|september|october|november|december)/i
}
var parseMonthPatterns = {
narrow: [/^j/i, /^f/i, /^m/i, /^a/i, /^m/i, /^j/i, /^j/i, /^a/i, /^s/i, /^o/i, /^n/i, /^d/i],
any: [/^ja/i, /^f/i, /^mar/i, /^ap/i, /^may/i, /^jun/i, /^jul/i, /^au/i, /^s/i, /^o/i, /^n/i, /^d/i]
}
var matchDayPatterns = {
narrow: /^[smtwf]/i,
short: /^(su|mo|tu|we|th|fr|sa)/i,
abbreviated: /^(sun|mon|tue|wed|thu|fri|sat)/i,
wide: /^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i
}
var parseDayPatterns = {
narrow: [/^s/i, /^m/i, /^t/i, /^w/i, /^t/i, /^f/i, /^s/i],
any: [/^su/i, /^m/i, /^tu/i, /^w/i, /^th/i, /^f/i, /^sa/i]
}
var matchDayPeriodPatterns = {
narrow: /^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,
any: /^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i
}
var parseDayPeriodPatterns = {
any: {
am: /^a/i,
pm: /^p/i,
midnight: /^mi/i,
noon: /^no/i,
morning: /morning/i,
afternoon: /afternoon/i,
evening: /evening/i,
night: /night/i
}
}
var match = {
ordinalNumber: buildMatchPatternFn({
matchPattern: matchOrdinalNumberPattern,
parsePattern: parseOrdinalNumberPattern,
valueCallback: function (value) {
return parseInt(value, 10)
}
}),
era: buildMatchFn({
matchPatterns: matchEraPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseEraPatterns,
defaultParseWidth: 'any'
}),
quarter: buildMatchFn({
matchPatterns: matchQuarterPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseQuarterPatterns,
defaultParseWidth: 'any',
valueCallback: function (index) {
return index + 1
}
}),
month: buildMatchFn({
matchPatterns: matchMonthPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseMonthPatterns,
defaultParseWidth: 'any'
}),
day: buildMatchFn({
matchPatterns: matchDayPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseDayPatterns,
defaultParseWidth: 'any'
}),
dayPeriod: buildMatchFn({
matchPatterns: matchDayPeriodPatterns,
defaultMatchWidth: 'any',
parsePatterns: parseDayPeriodPatterns,
defaultParseWidth: 'any'
})
}
export default match
These functions mirror those in localize
.
For matchPatterns
the patterns should match the whole meaningful word for the parsed value
(which will be cut from the string in the process of parsing).
parsePatterns
contains patterns to detect one of the values from the result of matchPatterns
Note that the patterns for parsePatterns
don't necessary contain the whole word:
// In `en-US` locale:
var parseDayPatterns = {
narrow: [/^s/i, /^m/i, /^t/i, /^w/i, /^t/i, /^f/i, /^s/i],
any: [/^su/i, /^m/i, /^tu/i, /^w/i, /^th/i, /^f/i, /^sa/i]
}
but only the bare minimum to parse the value.
Also note that all patterns have "case-insensitive" flags to match as much arbitrary user input as possible. For the same reason, try to match any variation of diacritical marks:
// In `eo` locale:
var matchDayPatterns = {
narrow: /^[dlmĵjvs]/i,
short: /^(di|lu|ma|me|(ĵ|jx|jh|j)a|ve|sa)/i,
abbreviated: /^(dim|lun|mar|mer|(ĵ|jx|jh|j)a(ŭ|ux|uh|u)|ven|sab)/i,
wide: /^(diman(ĉ|cx|ch|c)o|lundo|mardo|merkredo|(ĵ|jx|jh|j)a(ŭ|ux|uh|u)do|vendredo|sabato)/i
}
var parseDayPatterns = {
narrow: [/^d/i, /^l/i, /^m/i, /^m/i, /^(j|ĵ)/i, /^v/i, /^s/i],
any: [/^d/i, /^l/i, /^ma/i, /^me/i, /^(j|ĵ)/i, /^v/i, /^s/i]
}
Here, for the word "dimanĉo" the functions will match also "dimancxo", "dimancho" and even grammatically incorrect "dimanco".
Try to match any possible way of writing the word. Don't forget the grammatical cases:
// In `ru` locale:
var matchMonthPatterns = {
narrow: /^[яфмаисонд]/i,
abbreviated: /^(янв|фев|март?|апр|ма[йя]|июн[ья]?|июл[ья]?|авг|сент?|окт|нояб?|дек)/i,
wide: /^(январ[ья]|феврал[ья]|марта?|апрел[ья]|ма[йя]|июн[ья]|июл[ья]|августа?|сентябр[ья]|октябр[ья]|октябр[ья]|ноябр[ья]|декабр[ья])/i
}
and variations of short weekdays and months:
// In `ru` locale:
var matchDayPatterns = {
narrow: /^[впсч]/i,
short: /^(вс|во|пн|по|вт|ср|чт|че|пт|пя|сб|су)\.?/i,
abbreviated: /^(вск|вос|пнд|пон|втр|вто|срд|сре|чтв|чет|птн|пят|суб).?/i,
wide: /^(воскресень[ея]|понедельника?|вторника?|сред[аы]|четверга?|пятниц[аы]|суббот[аы])/i
}
(here, the abbreviated
pattern will match both вск
and вос
as the short of воскресенье
{Sunday})
In match.ordinalNumber
match ordinal numbers as well as non-ordinal numbers:
// In `en-US` locale:
var matchOrdinalNumberPattern = /^(\d+)(th|st|nd|rd)?/i
Don't forget the grammatical genders:
// In `ru` locale:
var matchOrdinalNumberPattern = /^(\d+)(-?(е|я|й|ое|ье|ая|ья|ый|ой|ий|ый))?/i
formatDistance
formatDistance
property of locale is a function which takes three arguments:
token passed by date-fns' formatDistance
function (e.g. 'lessThanXMinutes'),
a number of units to be displayed by the function
(e.g. locale.formatDistance('lessThanXMinutes', 5)
would display localized 'less than 5 minutes')
and object with options.
Your best guess is to copy formatDistance
property from another locale and change the values.
Tests
To test locales we use snapshots. See en-US
snapshot for an example.
To generate snapshots, run yarn locale-snapshots
. The snapshot for the locale
you're working on will appear in the root locale directory (e.g. src/locales/ru/snapshot.md
).
Once you are done with the locale, generate the snapshot and review the output values.
Creating a locale with the same language as another locale
Import the locale properties already implemented for the language, but replace unique properties.
// Same as en-US
import formatDistance from '../en-US/_lib/formatDistance/index.js'
import formatRelative from '../en-US/_lib/formatRelative/index.js'
import localize from '../en-US/_lib/localize/index.js'
import match from '../en-US/_lib/match/index.js'
// Unique for en-GB
import formatLong from './_lib/formatLong/index.js'
/**
* @type {Locale}
* @category Locales
* @summary English locale (United Kingdom).
* @language English
* @iso-639-2 eng
* @author John Doe [@example]{@link https://github.com/example}
*/
var locale = {
formatDistance: formatDistance,
formatLong: formatLong,
formatRelative: formatRelative,
localize: localize,
match: match,
// Unique for en-GB
options: {
weekStartsOn: 1,
firstWeekContainsDate: 4
}
}
export default locale