Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial version of Latin locale #966

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions src/locale/la.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Latin [la]
import dayjs from 'dayjs'

const monthFormat = 'ianuarii_februarii_martii_aprilis_maii_iunii_iulii_augusti_septembris_octobris_novembris_decembris'.split('_')
const monthStandalone = 'ianuarius_februarius_martius_aprilis_maius_iunius_iulius_augustus_september_october_november_december'.split('_')
const MONTHS_IN_FORMAT = /D[oD.ᵒ]?(\[[^[\]]*\]|\s)+MMMM?|MMMM?(\[[^[\]]*\]|\s)+D[oD.ᵒ]?/
const months = (dayjsInstance, format) => {
if (MONTHS_IN_FORMAT.test(format)) {
return monthFormat[dayjsInstance.month()]
}
return monthStandalone[dayjsInstance.month()]
}
months.s = monthStandalone
months.f = monthFormat

// src: https://stackoverflow.com/a/9083076
function romanise(num) {
const key = [
'', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM',
'', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC',
'', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'
]
const digits = String(+num).split('')
let roman = ''
let i = 3
while (i > 0) {
i -= 1
roman = (key[+digits.pop() + (i * 10)] || '') + roman
}
return Array(+digits.join('') + 1).join('M') + roman
}

const locale = {
name: 'la',
weekdays: 'dominica_feria secunda_feria tertia_feria quarta_feria quinta_feria sexta_sabbato'.split('_'),
weekdaysShort: 'dominica_feria II_feria III_feria IV_feria V_feria VI_sabbato'.split('_'),
weekdaysMin: 'dom._II_III_IV_V_VI_sab.'.split('_'),
months,
monthsShort: 'ian._feb._mar._apr._mai._iun._iul._aug._sep._oct._nov._dec.'.split('_'),
weekStart: 0,
yearStart: 4,
ordinal: n => romanise(n),
// The relative time variables are in nominative case only
relativeTime: {
future: 'ad %s',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Yes, I'm lazy to install the library, understand it and try myself.)
@tukusejssirs would you please post one (preferably non-trivial) example for both relative time in future and in the past?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can see the output in the locale test (L64-80), in the T constant (it is a multi-dimensional array consisting of [number, 'English word', 'number Latin word']; I think it is quite readable 😉).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it isn't readable. It's code, DRY as a desert.

Copy link
Contributor Author

@tukusejssirs tukusejssirs Oct 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, here’s a simple ‘conversion‘ table:

English Latin
a few seconds paucæ secundæ
a minute minuta
2-∞ minutes 2-∞ minutæ
an hour hora
2-∞ hours 2-∞ horæ
a day dies
2-∞ days 2-∞ dies
a month mensis
2-∞ months 2-∞ menses
a year annus
2-∞ years 2-∞ anni

Update: I have updated the table to better reflect that the plural forms are used for any number from 2-∞ interval.

Copy link
Contributor Author

@tukusejssirs tukusejssirs Oct 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just pinging you, @igneus. When you find some time, please check the table above if it is sufficiently readable for you. All other issues you raised were fixed in the latest commit.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I'll manage to communicate what I really wanted to see, so I cloned your repo and checked out the latin branch with hope that I will be able to play with the code myself, but it turns out that my NodeJS skills don't suffice to load the package from development sources.

I ran npm run-script build, managed to load dayjs.min.js in the interactive console (var dayjs = require('dayjs.min.js');), but attempts to load locales fail, probably due to my lack of understanding of some basic NodeJS concepts.

2020-10-21-201523_1366x768_scrot

Since I personally don't care much about dayjs' Latin locale, I probably just give up and 🙈

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I'll manage to communicate what I really wanted to see

I’m sorry I didn’t understand you. Anyway, I still think that you proofed everything in the Latin locale except for those string in the ‘conversion’ table.

Anyway, in the Czech locale, they use different inflection of those strings when they are used in the past (e.g. a few seconds ago) or future tense (in a few seconds). If any of the strings from relativeTime should be in different grammar case in the past and future tenses, we would need to update it accordingly.

I cloned your repo and checked out the latin branch with hope that I will be able to play with the code myself, but it turns out that my NodeJS skills don't suffice to load the package from development sources.

All you should need to do after cloning the repo is as follows:

# Install the dependencies
npm install

# Build `dayjs`
# Note: This is same as running `npm run-script build`
npm run build

# Run the `la.test.js` test
# Note: Run the following command from repo root or modify both relative paths
node node_modules/jest/bin/jest.js test/locale/la.test.js --coverage=false

I think the easiest way to test things without any deeper knowledge of Node.js, it to modify the test/locale/la.test.js to include console.log() command(s), where you put the output of whatever you want to see.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I personally don't care much about dayjs' Latin locale, I probably just give up and see_no_evil

Pinging @igneus. Are you determined to give up on this review? As I understand it, you have not reviewed only one part, the relativeTime.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping, @igneus. No answer from you for more than a month. I presume you are occupied with some other stuff, however, I’d be very happy if you at least say something. 😉 Thanks in advance with all your help! 😃

past: 'abhinc %s',
s: 'paucæ secundæ',
m: 'minuta',
mm: '%d minutæ',
h: 'hora',
hh: '%d horæ',
d: 'dies',
dd: '%d dies',
M: 'mensis',
MM: '%d menses',
y: 'annus',
yy: '%d anni'
},
formats: {
LT: 'HH:mm',
LTS: 'HH:mm:ss',
L: 'D. MM. YYYY',
LL: 'D MMMM YYYY',
LLL: 'D MMMM YYYY, HH:mm',
LLLL: 'dddd, D MMMM YYYY, HH:mm'
}
}

dayjs.locale(locale, null, true)

export default locale
172 changes: 172 additions & 0 deletions test/locale/la.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import MockDate from 'mockdate'
import dayjs from '../../src'
import advancedFormat from '../../src/plugin/advancedFormat'
import localizedFormat from '../../src/plugin/localizedFormat'
import relativeTime from '../../src/plugin/relativeTime'
import '../../src/locale/la'

dayjs.extend(advancedFormat)
dayjs.extend(localizedFormat)
dayjs.extend(relativeTime)
dayjs.locale('la')

beforeEach(() => {
MockDate.set(new Date())
})

afterEach(() => {
MockDate.reset()
})

describe('Latin: Test output of month names:', () => {
const T = [
[1, 'ianuarius', 'ianuarii', 'ian.'],
[2, 'februarius', 'februarii', 'feb.'],
[3, 'martius', 'martii', 'mar.'],
[4, 'aprilis', 'aprilis', 'apr.'],
[5, 'maius', 'maii', 'mai.'],
[6, 'iunius', 'iunii', 'iun.'],
[7, 'iulius', 'iulii', 'iul.'],
[8, 'augustus', 'augusti', 'aug.'],
[9, 'september', 'septembris', 'sep.'],
[10, 'october', 'octobris', 'oct.'],
[11, 'november', 'novembris', 'nov.'],
[12, 'december', 'decembris', 'dec.']
]

it('in genitive case if day of month is output', () => {
T.forEach((t) => {
const dayjsDay = dayjs(['2020-', t[0], '-01'].join('')).locale('la').format('D MMMM')
const expected = ['1 ', t[2]].join('')
expect(dayjsDay).toBe(expected)
})
})

it('in nominative if day of month is not output', () => {
T.forEach((t) => {
const dayjsDay = dayjs(['2020-', t[0], '-01'].join('')).locale('la').format('MMMM')
const expected = t[1]
expect(dayjsDay).toBe(expected)
})
})

it('also as a shortcut', () => {
T.forEach((t) => {
const dayjsDay = dayjs(['2020-', t[0], '-01'].join('')).locale('la').format('MMM')
const expected = t[3]
expect(dayjsDay).toBe(expected)
})
})
})

it('Latin: Test relative time', () => {
const T = [
[44.4, 'second', 'paucæ secundæ'], // a few seconds
[89.5, 'second', 'minuta'], // a minute
[2, 'minute', '2 minutæ'], // 2 minutes
[43, 'minute', '43 minutæ'], // 43 minutes
[45, 'minute', 'hora'], // an hour
[3, 'hour', '3 horæ'], // 3 hours
[21, 'hour', '21 horæ'], // 21 hours
[1, 'day', 'dies'], // a day
[3, 'day', '3 dies'], // 3 day
[25, 'day', '25 dies'], // 25 days
[1, 'month', 'mensis'], // a month
[2, 'month', '2 menses'], // 2 month
[10, 'month', '10 menses'], // 10 month
[1, 'year', 'annus'], // a year
[2, 'year', '2 anni'], // 2 year
[5, 'year', '5 anni'], // 5 year
[18, 'month', '2 anni'] // 2 years
]

T.forEach((t) => {
// dayjs.locale('la')
const dayjsDay = dayjs()
const dayjsCompare = dayjs().add(t[0], t[1])
const expectedFrom = ['abhinc ', t[2]].join('')
const expectedTo = ['ad ', t[2]].join('')
const expectedFromTrue = t[2]

expect(dayjsDay.from(dayjsCompare)).toBe(expectedFrom)
expect(dayjsDay.to(dayjsCompare)).toBe(expectedTo)
expect(dayjsDay.from(dayjsCompare, true)).toBe(expectedFromTrue)
})
})

it('Latin: Test ordinal numbers in day of months', () => {
const T = [
[1, 'I'],
[2, 'II'],
[3, 'III'],
[4, 'IV'],
[5, 'V'],
[6, 'VI'],
[7, 'VII'],
[8, 'VIII'],
[9, 'IX'],
[10, 'X'],
[20, 'XX'],
[30, 'XXX'],
[31, 'XXXI']
]

T.forEach((t) => {
const dayjsDay = dayjs(['2020-01-', t[0]].join('')).locale('la').format('Do')
const expected = t[1]
expect(dayjsDay).toBe(expected)
})
})

describe('Latin: Test weeday names:', () => {
const T = [
['2020-01-05', 'dominica', 'dominica', 'dom.'],
['2020-01-06', 'feria secunda', 'feria II', 'II'],
['2020-01-07', 'feria tertia', 'feria III', 'III'],
['2020-01-01', 'feria quarta', 'feria IV', 'IV'],
['2020-01-02', 'feria quinta', 'feria V', 'V'],
['2020-01-03', 'feria sexta', 'feria VI', 'VI'],
['2020-01-04', 'sabbato', 'sabbato', 'sab.']
]

it('full weekday names', () => {
T.forEach((t) => {
const dayjsDay = dayjs(t[0]).format('dddd')
const expected = t[1]
expect(dayjsDay).toBe(expected)
})
})

it('short weekday names', () => {
T.forEach((t) => {
const dayjsDay = dayjs(t[0]).format('ddd')
const expected = t[2]
expect(dayjsDay).toBe(expected)
})
})

it('minimal weekday names', () => {
T.forEach((t) => {
const dayjsDay = dayjs(t[0]).format('dd')
const expected = t[3]
expect(dayjsDay).toBe(expected)
})
})
})

it('minimal weekday names', () => {
const T = [
['LT', '15:15'],
['LTS', '15:15:32'],
['L', '1. 01. 2020'],
['LL', '1 ianuarii 2020'],
['LLL', '1 ianuarii 2020, 15:15'],
['LLLL', 'feria quarta, 1 ianuarii 2020, 15:15']
]

T.forEach((t) => {
const dayjsDay = dayjs('2020-01-01 15:15:32').format(t[0])
const expected = t[1]
expect(dayjsDay).toBe(expected)
})
})