From 21b96b44656a4bb024d12ee34f80df15e7a05f94 Mon Sep 17 00:00:00 2001 From: SebastianKrupinski Date: Fri, 13 Dec 2024 18:18:54 -0500 Subject: [PATCH] fix: change translation logic to handle plurals better Signed-off-by: SebastianKrupinski --- apps/dav/lib/CalDAV/Schedule/IMipService.php | 260 ++++++++- .../unit/CalDAV/Schedule/IMipServiceTest.php | 550 ++++++++++++++++-- 2 files changed, 730 insertions(+), 80 deletions(-) diff --git a/apps/dav/lib/CalDAV/Schedule/IMipService.php b/apps/dav/lib/CalDAV/Schedule/IMipService.php index e0d51edc17734..9f1f0e7f48061 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipService.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipService.php @@ -202,15 +202,95 @@ public function generateWhenStringSingular(EventReader $er): string { // TRANSLATORS // Indicates when a calendar event will happen, shown on invitation emails // Output produced in order: - // In a day/week/month/year on July 1, 2024 for the entire day - // In a day/week/month/year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto) - // In 2 days/weeks/months/years on July 1, 2024 for the entire day - // In 2 days/weeks/months/years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto) - return match ([($occurring[0] > 1), !empty($endTime)]) { - [false, false] => $this->l10n->t('In a %1$s on %2$s for the entire day', [$occurring[1], $startDate]), - [false, true] => $this->l10n->t('In a %1$s on %2$s between %3$s - %4$s', [$occurring[1], $startDate, $startTime, $endTime]), - [true, false] => $this->l10n->t('In %1$s %2$s on %3$s for the entire day', [$occurring[0], $occurring[1], $startDate]), - [true, true] => $this->l10n->t('In %1$s %2$s on %3$s between %4$s - %5$s', [$occurring[0], $occurring[1], $startDate, $startTime, $endTime]), + // In a minute/hour/day/week/month/year on July 1, 2024 for the entire day + // In a minute/hour/day/week/month/year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto) + // In 2 minutes/hours/days/weeks/months/years on July 1, 2024 for the entire day + // In 2 minutes/hours/days/weeks/months/years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto) + return match ([$occurring['scale'], !empty($endTime)]) { + ['past', false] => $this->l10n->n( + 'In the past on %1$s for the entire day', + '', + $occurring['interval'], + [$startDate] + ), + ['minute', false] => $this->l10n->n( + 'In a minute on %1$s for the entire day', + 'In %n minutes on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['hour', false] => $this->l10n->n( + 'In a hour on %1$s for the entire day', + 'In %n hours on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['day', false] => $this->l10n->n( + 'In a day on %1$s for the entire day', + 'In %n days on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['week', false] => $this->l10n->n( + 'In a week on %1$s for the entire day', + 'In %n weeks on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['month', false] => $this->l10n->n( + 'In a month on %1$s for the entire day', + 'In %n months on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['year', false] => $this->l10n->n( + 'In a year on %1$s for the entire day', + 'In %n years on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['past', true] => $this->l10n->n( + 'In the past on %1$s between %2$s - %3$s', + '', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['minute', true] => $this->l10n->n( + 'In a minute on %1$s between %2$s - %3$s', + 'In %n minutes on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['hour', true] => $this->l10n->n( + 'In a hour on %1$s between %2$s - %3$s', + 'In %n hours on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['day', true] => $this->l10n->n( + 'In a day on %1$s between %2$s - %3$s', + 'In %n days on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['week', true] => $this->l10n->n( + 'In a week on %1$s between %2$s - %3$s', + 'In %n weeks on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['month', true] => $this->l10n->n( + 'In a month on %1$s between %2$s - %3$s', + 'In %n months on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['year', true] => $this->l10n->n( + 'In a year on %1$s between %2$s - %3$s', + 'In %n years on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), default => $this->l10n->t('Could not generate when statement') }; } @@ -545,19 +625,139 @@ public function generateOccurringString(EventReader $er): string { // TRANSLATORS // Indicates when a calendar event will happen, shown on invitation emails // Output produced in order: - // In a day/week/month/year on July 1, 2024 - // In a day/week/month/year on July 1, 2024 then on July 3, 2024 - // In a day/week/month/year on July 1, 2024 then on July 3, 2024 and July 5, 2024 - // In 2 days/weeks/months/years on July 1, 2024 - // In 2 days/weeks/months/years on July 1, 2024 then on July 3, 2024 - // In 2 days/weeks/months/years on July 1, 2024 then on July 3, 2024 and July 5, 2024 - return match ([($occurrenceIn[0] > 1), !empty($occurrence2), !empty($occurrence3)]) { - [false, false, false] => $this->l10n->t('In a %1$s on %2$s', [$occurrenceIn[1], $occurrence]), - [false, true, false] => $this->l10n->t('In a %1$s on %2$s then on %3$s', [$occurrenceIn[1], $occurrence, $occurrence2]), - [false, true, true] => $this->l10n->t('In a %1$s on %2$s then on %3$s and %4$s', [$occurrenceIn[1], $occurrence, $occurrence2, $occurrence3]), - [true, false, false] => $this->l10n->t('In %1$s %2$s on %3$s', [$occurrenceIn[0], $occurrenceIn[1], $occurrence]), - [true, true, false] => $this->l10n->t('In %1$s %2$s on %3$s then on %4$s', [$occurrenceIn[0], $occurrenceIn[1], $occurrence, $occurrence2]), - [true, true, true] => $this->l10n->t('In %1$s %2$s on %3$s then on %4$s and %5$s', [$occurrenceIn[0], $occurrenceIn[1], $occurrence, $occurrence2, $occurrence3]), + // In a minute/hour/day/week/month/year on July 1, 2024 + // In a minute/hour/day/week/month/year on July 1, 2024 then on July 3, 2024 + // In a minute/hour/day/week/month/year on July 1, 2024 then on July 3, 2024 and July 5, 2024 + // In 2 minutes/hours/days/weeks/months/years on July 1, 2024 + // In 2 minutes/hours/days/weeks/months/years on July 1, 2024 then on July 3, 2024 + // In 2 minutes/hours/days/weeks/months/years on July 1, 2024 then on July 3, 2024 and July 5, 2024 + return match ([$occurrenceIn['scale'], !empty($occurrence2), !empty($occurrence3)]) { + ['past', false, false] => $this->l10n->n( + 'In the past on %1$s', + '', + $occurrenceIn['interval'], + [$occurrence] + ), + ['minute', false, false] => $this->l10n->n( + 'In a minute on %1$s', + 'In %n minutes on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['hour', false, false] => $this->l10n->n( + 'In a hour on %1$s', + 'In %n hours on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['day', false, false] => $this->l10n->n( + 'In a day on %1$s', + 'In %n days on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['week', false, false] => $this->l10n->n( + 'In a week on %1$s', + 'In %n weeks on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['month', false, false] => $this->l10n->n( + 'In a month on %1$s', + 'In %n months on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['year', false, false] => $this->l10n->n( + 'In a year on %1$s', + 'In %n years on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['past', true, false] => $this->l10n->n( + 'In the past on %1$s then on %2$s', + '', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['minute', true, false] => $this->l10n->n( + 'In a minute on %1$s then on %2$s', + 'In %n minutes on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['hour', true, false] => $this->l10n->n( + 'In a hour on %1$s then on %2$s', + 'In %n hours on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['day', true, false] => $this->l10n->n( + 'In a day on %1$s then on %2$s', + 'In %n days on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['week', true, false] => $this->l10n->n( + 'In a week on %1$s then on %2$s', + 'In %n weeks on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['month', true, false] => $this->l10n->n( + 'In a month on %1$s then on %2$s', + 'In %n months on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['year', true, false] => $this->l10n->n( + 'In a year on %1$s then on %2$s', + 'In %n years on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['past', true, true] => $this->l10n->n( + 'In the past on %1$s then on %2$s and %3$s', + '', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['minute', true, true] => $this->l10n->n( + 'In a minute on %1$s then on %2$s and %3$s', + 'In %n minutes on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['hour', true, true] => $this->l10n->n( + 'In a hour on %1$s then on %2$s and %3$s', + 'In %n hours on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['day', true, true] => $this->l10n->n( + 'In a day on %1$s then on %2$s and %3$s', + 'In %n days on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['week', true, true] => $this->l10n->n( + 'In a week on %1$s then on %2$s and %3$s', + 'In %n weeks on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['month', true, true] => $this->l10n->n( + 'In a month on %1$s then on %2$s and %3$s', + 'In %n months on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['year', true, true] => $this->l10n->n( + 'In a year on %1$s then on %2$s and %3$s', + 'In %n years on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), default => $this->l10n->t('Could not generate next recurrence statement') }; @@ -965,30 +1165,30 @@ public function isRoomOrResource(Property $attendee): bool { public function minimizeInterval(\DateInterval $dateInterval): array { // evaluate if time interval is in the past if ($dateInterval->invert == 1) { - return [1, 'the past']; + return ['interval' => 1, 'scale' => 'past']; } // evaluate interval parts and return smallest time period if ($dateInterval->y > 0) { $interval = $dateInterval->y; - $scale = ($dateInterval->y > 1) ? 'years' : 'year'; + $scale = 'year'; } elseif ($dateInterval->m > 0) { $interval = $dateInterval->m; - $scale = ($dateInterval->m > 1) ? 'months' : 'month'; + $scale = 'month'; } elseif ($dateInterval->d >= 7) { $interval = (int)($dateInterval->d / 7); - $scale = ((int)($dateInterval->d / 7) > 1) ? 'weeks' : 'week'; + $scale = 'week'; } elseif ($dateInterval->d > 0) { $interval = $dateInterval->d; - $scale = ($dateInterval->d > 1) ? 'days' : 'day'; + $scale = 'day'; } elseif ($dateInterval->h > 0) { $interval = $dateInterval->h; - $scale = ($dateInterval->h > 1) ? 'hours' : 'hour'; + $scale = 'hour'; } else { $interval = $dateInterval->i; - $scale = 'minutes'; + $scale = 'minute'; } - return [$interval, $scale]; + return ['interval' => $interval, 'scale' => $scale]; } /** diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php index f1c003625b2df..b85967abb44d4 100644 --- a/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php +++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php @@ -1,4 +1,5 @@ l10n->method('t')->willReturnMap([ - ['In a %1$s on %2$s between %3$s - %4$s', ['day', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'] + $this->l10n->method('n')->willReturnMap([ + [ + 'In a day on %1$s between %2$s - %3$s', + 'In %n days on %1$s between %2$s - %3$s', + 1, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ] ]); // construct time factory return(s) $this->timeFactory->method('getDateTime')->willReturnCallback( @@ -222,8 +229,14 @@ function ($v1, $v2, $v3) { }; } ); - $this->l10n->method('t')->willReturnMap([ - ['In a %1$s on %2$s between %3$s - %4$s', ['day', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'] + $this->l10n->method('n')->willReturnMap([ + [ + 'In a day on %1$s between %2$s - %3$s', + 'In %n days on %1$s between %2$s - %3$s', + 1, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ] ]); // construct time factory return(s) $this->timeFactory->method('getDateTime')->willReturnCallback( @@ -348,45 +361,330 @@ function ($v1, $v2, $v3) { }; } ); - $this->l10n->method('t')->willReturnMap([ - ['In a %1$s on %2$s for the entire day', ['day', 'July 1, 2024'], 'In a day on July 1, 2024 for the entire day'], - ['In a %1$s on %2$s between %3$s - %4$s', ['day', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], - ['In %1$s %2$s on %3$s for the entire day', [2, 'days', 'July 1, 2024'], 'In 2 days on July 1, 2024 for the entire day'], - ['In %1$s %2$s on %3$s between %4$s - %5$s', [2, 'days', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In 2 days on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], - ['In a %1$s on %2$s for the entire day', ['week', 'July 1, 2024'], 'In a week on July 1, 2024 for the entire day'], - ['In a %1$s on %2$s between %3$s - %4$s', ['week', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a week on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], - ['In %1$s %2$s on %3$s for the entire day', [2, 'weeks', 'July 1, 2024'], 'In 2 weeks on July 1, 2024 for the entire day'], - ['In %1$s %2$s on %3$s between %4$s - %5$s', [2, 'weeks', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In 2 weeks on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], - ['In a %1$s on %2$s for the entire day', ['month', 'July 1, 2024'], 'In a month on July 1, 2024 for the entire day'], - ['In a %1$s on %2$s between %3$s - %4$s', ['month', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a month on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], - ['In %1$s %2$s on %3$s for the entire day', [2, 'months', 'July 1, 2024'], 'In 2 months on July 1, 2024 for the entire day'], - ['In %1$s %2$s on %3$s between %4$s - %5$s', [2, 'months', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In 2 months on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], - ['In a %1$s on %2$s for the entire day', ['year', 'July 1, 2024'], 'In a year on July 1, 2024 for the entire day'], - ['In a %1$s on %2$s between %3$s - %4$s', ['year', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], - ['In %1$s %2$s on %3$s for the entire day', [2, 'years', 'July 1, 2024'], 'In 2 years on July 1, 2024 for the entire day'], - ['In %1$s %2$s on %3$s between %4$s - %5$s', [2, 'years', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In 2 years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'] + $this->l10n->method('n')->willReturnMap([ + // singular entire day + [ + 'In the past on %1$s for the entire day', + '', + 1, + ['July 1, 2024'], + 'In the past on July 1, 2024 for the entire day' + ], + [ + 'In a minute on %1$s for the entire day', + 'In %n minutes on %1$s for the entire day', + 1, + ['July 1, 2024'], + 'In a minute on July 1, 2024 for the entire day' + ], + [ + 'In a hour on %1$s for the entire day', + 'In %n hours on %1$s for the entire day', + 1, + ['July 1, 2024'], + 'In a hour on July 1, 2024 for the entire day' + ], + [ + 'In a day on %1$s for the entire day', + 'In %n days on %1$s for the entire day', + 1, + ['July 1, 2024'], + 'In a day on July 1, 2024 for the entire day' + ], + [ + 'In a week on %1$s for the entire day', + 'In %n weeks on %1$s for the entire day', + 1, + ['July 1, 2024'], + 'In a week on July 1, 2024 for the entire day' + ], + [ + 'In a month on %1$s for the entire day', + 'In %n months on %1$s for the entire day', + 1, + ['July 1, 2024'], + 'In a month on July 1, 2024 for the entire day' + ], + [ + 'In a year on %1$s for the entire day', + 'In %n years on %1$s for the entire day', + 1, + ['July 1, 2024'], + 'In a year on July 1, 2024 for the entire day' + ], + // plural entire day + [ + 'In a minute on %1$s for the entire day', + 'In %n minutes on %1$s for the entire day', + 2, + ['July 1, 2024'], + 'In 2 minutes on July 1, 2024 for the entire day' + ], + [ + 'In a hour on %1$s for the entire day', + 'In %n hours on %1$s for the entire day', + 2, + ['July 1, 2024'], + 'In 2 hours on July 1, 2024 for the entire day' + ], + [ + 'In a day on %1$s for the entire day', + 'In %n days on %1$s for the entire day', + 2, + ['July 1, 2024'], + 'In 2 days on July 1, 2024 for the entire day' + ], + [ + 'In a week on %1$s for the entire day', + 'In %n weeks on %1$s for the entire day', + 2, + ['July 1, 2024'], + 'In 2 weeks on July 1, 2024 for the entire day' + ], + [ + 'In a month on %1$s for the entire day', + 'In %n months on %1$s for the entire day', + 2, + ['July 1, 2024'], + 'In 2 months on July 1, 2024 for the entire day' + ], + [ + 'In a year on %1$s for the entire day', + 'In %n years on %1$s for the entire day', + 2, + ['July 1, 2024'], + 'In 2 years on July 1, 2024 for the entire day' + ], + // singular partial day + [ + 'In the past on %1$s between %2$s - %3$s', + '', + 1, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In the past on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a minute on %1$s between %2$s - %3$s', + 'In %n minutes on %1$s between %2$s - %3$s', + 1, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In a minute on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a hour on %1$s between %2$s - %3$s', + 'In %n hours on %1$s between %2$s - %3$s', + 1, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In a hour on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a day on %1$s between %2$s - %3$s', + 'In %n days on %1$s between %2$s - %3$s', + 1, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a week on %1$s between %2$s - %3$s', + 'In %n weeks on %1$s between %2$s - %3$s', + 1, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In a week on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a month on %1$s between %2$s - %3$s', + 'In %n months on %1$s between %2$s - %3$s', + 1, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In a month on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a year on %1$s between %2$s - %3$s', + 'In %n years on %1$s between %2$s - %3$s', + 1, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In a year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + // plural partial day + [ + 'In a minute on %1$s between %2$s - %3$s', + 'In %n minutes on %1$s between %2$s - %3$s', + 2, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In 2 minutes on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a hour on %1$s between %2$s - %3$s', + 'In %n hours on %1$s between %2$s - %3$s', + 2, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In 2 hours on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a day on %1$s between %2$s - %3$s', + 'In %n days on %1$s between %2$s - %3$s', + 2, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In 2 days on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a week on %1$s between %2$s - %3$s', + 'In %n weeks on %1$s between %2$s - %3$s', + 2, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In 2 weeks on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a month on %1$s between %2$s - %3$s', + 'In %n months on %1$s between %2$s - %3$s', + 2, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In 2 months on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], + [ + 'In a year on %1$s between %2$s - %3$s', + 'In %n years on %1$s between %2$s - %3$s', + 2, + ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], + 'In 2 years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)' + ], ]); // construct time factory return(s) $this->timeFactory->method('getDateTime')->willReturnOnConsecutiveCalls( + // past interval test dates + (new \DateTime('20240702T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240703T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240702T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240703T170000', (new \DateTimeZone('America/Toronto')))), + // minute interval test dates + (new \DateTime('20240701T075900', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240630T235900', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240701T075800', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240630T235800', (new \DateTimeZone('America/Toronto')))), + // hour interval test dates + (new \DateTime('20240701T070000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240630T230000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240701T060000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240630T220000', (new \DateTimeZone('America/Toronto')))), + // day interval test dates (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))), + // week interval test dates (new \DateTime('20240621T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20240621T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20240614T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20240614T170000', (new \DateTimeZone('America/Toronto')))), + // month interval test dates (new \DateTime('20240530T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20240530T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20240430T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20240430T170000', (new \DateTimeZone('America/Toronto')))), + // year interval test dates (new \DateTime('20230630T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20230630T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20220630T170000', (new \DateTimeZone('America/Toronto')))), (new \DateTime('20220630T170000', (new \DateTimeZone('America/Toronto')))) ); + /** test partial day event in 1 day in the past*/ + $vCalendar = clone $this->vCalendar1a; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In the past on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 1 day in the past*/ + $vCalendar = clone $this->vCalendar2; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In the past on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event in 2 days in the past*/ + $vCalendar = clone $this->vCalendar1a; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In the past on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 2 days in the past*/ + $vCalendar = clone $this->vCalendar2; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In the past on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event in 1 minute*/ + $vCalendar = clone $this->vCalendar1a; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In a minute on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 1 minute*/ + $vCalendar = clone $this->vCalendar2; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In a minute on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event in 2 minutes*/ + $vCalendar = clone $this->vCalendar1a; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In 2 minutes on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 2 minutes*/ + $vCalendar = clone $this->vCalendar2; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In 2 minutes on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event in 1 hour*/ + $vCalendar = clone $this->vCalendar1a; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In a hour on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 1 hour*/ + $vCalendar = clone $this->vCalendar2; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In a hour on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event in 2 hours*/ + $vCalendar = clone $this->vCalendar1a; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In 2 hours on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 2 hours*/ + $vCalendar = clone $this->vCalendar2; + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + $this->assertEquals( + 'In 2 hours on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + /** test patrial day event in 1 day*/ $vCalendar = clone $this->vCalendar1a; // construct event reader @@ -1260,15 +1558,53 @@ function ($v1, $v2, $v3) { }; } ); - $this->l10n->method('t')->willReturnMap([ - ['In a %1$s on %2$s', ['day', 'July 1, 2024'], 'In a day on July 1, 2024'], - ['In a %1$s on %2$s then on %3$s', ['day', 'July 1, 2024', 'July 3, 2024'], 'In a day on July 1, 2024 then on July 3, 2024'], - ['In a %1$s on %2$s then on %3$s and %4$s', ['day', 'July 1, 2024', 'July 3, 2024', 'July 5, 2024'], 'In a day on July 1, 2024 then on July 3, 2024 and July 5, 2024'], - ['In %1$s %2$s on %3$s', [2, 'days', 'July 1, 2024'], 'In 2 days on July 1, 2024'], - ['In %1$s %2$s on %3$s then on %4$s', [2, 'days', 'July 1, 2024', 'July 3, 2024'], 'In 2 days on July 1, 2024 then on July 3, 2024'], - ['In %1$s %2$s on %3$s then on %4$s and %5$s', [2, 'days', 'July 1, 2024', 'July 3, 2024', 'July 5, 2024'], 'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024'], + $this->l10n->method('n')->willReturnMap([ + // singular + [ + 'In a day on %1$s', + 'In %n days on %1$s', + 1, + ['July 1, 2024'], + 'In a day on July 1, 2024' + ], + [ + 'In a day on %1$s then on %2$s', + 'In %n days on %1$s then on %2$s', + 1, + ['July 1, 2024', 'July 3, 2024'], + 'In a day on July 1, 2024 then on July 3, 2024' + ], + [ + 'In a day on %1$s then on %2$s and %3$s', + 'In %n days on %1$s then on %2$s and %3$s', + 1, + ['July 1, 2024', 'July 3, 2024', 'July 5, 2024'], + 'In a day on July 1, 2024 then on July 3, 2024 and July 5, 2024' + ], + // plural + [ + 'In a day on %1$s', + 'In %n days on %1$s', + 2, + ['July 1, 2024'], + 'In 2 days on July 1, 2024' + ], + [ + 'In a day on %1$s then on %2$s', + 'In %n days on %1$s then on %2$s', + 2, + ['July 1, 2024', 'July 3, 2024'], + 'In 2 days on July 1, 2024 then on July 3, 2024' + ], + [ + 'In a day on %1$s then on %2$s and %3$s', + 'In %n days on %1$s then on %2$s and %3$s', + 2, + ['July 1, 2024', 'July 3, 2024', 'July 5, 2024'], + 'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024' + ], ]); - + // construct time factory return(s) $this->timeFactory->method('getDateTime')->willReturnOnConsecutiveCalls( (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), @@ -1364,13 +1700,51 @@ function ($v1, $v2, $v3) { }; } ); - $this->l10n->method('t')->willReturnMap([ - ['In a %1$s on %2$s', ['day', 'July 1, 2024'], 'In a day on July 1, 2024'], - ['In a %1$s on %2$s then on %3$s', ['day', 'July 1, 2024', 'July 3, 2024'], 'In a day on July 1, 2024 then on July 3, 2024'], - ['In a %1$s on %2$s then on %3$s and %4$s', ['day', 'July 1, 2024', 'July 3, 2024', 'July 5, 2024'], 'In a day on July 1, 2024 then on July 3, 2024 and July 5, 2024'], - ['In %1$s %2$s on %3$s', [2, 'days', 'July 1, 2024'], 'In 2 days on July 1, 2024'], - ['In %1$s %2$s on %3$s then on %4$s', [2, 'days', 'July 1, 2024', 'July 3, 2024'], 'In 2 days on July 1, 2024 then on July 3, 2024'], - ['In %1$s %2$s on %3$s then on %4$s and %5$s', [2, 'days', 'July 1, 2024', 'July 3, 2024', 'July 5, 2024'], 'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024'], + $this->l10n->method('n')->willReturnMap([ + // singular + [ + 'In a day on %1$s', + 'In %n days on %1$s', + 1, + ['July 1, 2024'], + 'In a day on July 1, 2024' + ], + [ + 'In a day on %1$s then on %2$s', + 'In %n days on %1$s then on %2$s', + 1, + ['July 1, 2024', 'July 3, 2024'], + 'In a day on July 1, 2024 then on July 3, 2024' + ], + [ + 'In a day on %1$s then on %2$s and %3$s', + 'In %n days on %1$s then on %2$s and %3$s', + 1, + ['July 1, 2024', 'July 3, 2024', 'July 5, 2024'], + 'In a day on July 1, 2024 then on July 3, 2024 and July 5, 2024' + ], + // plural + [ + 'In a day on %1$s', + 'In %n days on %1$s', + 2, + ['July 1, 2024'], + 'In 2 days on July 1, 2024' + ], + [ + 'In a day on %1$s then on %2$s', + 'In %n days on %1$s then on %2$s', + 2, + ['July 1, 2024', 'July 3, 2024'], + 'In 2 days on July 1, 2024 then on July 3, 2024' + ], + [ + 'In a day on %1$s then on %2$s and %3$s', + 'In %n days on %1$s then on %2$s and %3$s', + 2, + ['July 1, 2024', 'July 3, 2024', 'July 5, 2024'], + 'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024' + ], ]); // construct time factory return(s) @@ -1477,13 +1851,51 @@ function ($v1, $v2, $v3) { }; } ); - $this->l10n->method('t')->willReturnMap([ - ['In a %1$s on %2$s', ['day', 'July 1, 2024'], 'In a day on July 1, 2024'], - ['In a %1$s on %2$s then on %3$s', ['day', 'July 1, 2024', 'July 5, 2024'], 'In a day on July 1, 2024 then on July 5, 2024'], - ['In a %1$s on %2$s then on %3$s and %4$s', ['day', 'July 1, 2024', 'July 5, 2024', 'July 7, 2024'], 'In a day on July 1, 2024 then on July 5, 2024 and July 7, 2024'], - ['In %1$s %2$s on %3$s', [2, 'days', 'July 1, 2024'], 'In 2 days on July 1, 2024'], - ['In %1$s %2$s on %3$s then on %4$s', [2, 'days', 'July 1, 2024', 'July 5, 2024'], 'In 2 days on July 1, 2024 then on July 5, 2024'], - ['In %1$s %2$s on %3$s then on %4$s and %5$s', [2, 'days', 'July 1, 2024', 'July 5, 2024', 'July 7, 2024'], 'In 2 days on July 1, 2024 then on July 5, 2024 and July 7, 2024'], + $this->l10n->method('n')->willReturnMap([ + // singular + [ + 'In a day on %1$s', + 'In %n days on %1$s', + 1, + ['July 1, 2024'], + 'In a day on July 1, 2024' + ], + [ + 'In a day on %1$s then on %2$s', + 'In %n days on %1$s then on %2$s', + 1, + ['July 1, 2024', 'July 5, 2024'], + 'In a day on July 1, 2024 then on July 5, 2024' + ], + [ + 'In a day on %1$s then on %2$s and %3$s', + 'In %n days on %1$s then on %2$s and %3$s', + 1, + ['July 1, 2024', 'July 5, 2024', 'July 7, 2024'], + 'In a day on July 1, 2024 then on July 5, 2024 and July 7, 2024' + ], + // plural + [ + 'In a day on %1$s', + 'In %n days on %1$s', + 2, + ['July 1, 2024'], + 'In 2 days on July 1, 2024' + ], + [ + 'In a day on %1$s then on %2$s', + 'In %n days on %1$s then on %2$s', + 2, + ['July 1, 2024', 'July 5, 2024'], + 'In 2 days on July 1, 2024 then on July 5, 2024' + ], + [ + 'In a day on %1$s then on %2$s and %3$s', + 'In %n days on %1$s then on %2$s and %3$s', + 2, + ['July 1, 2024', 'July 5, 2024', 'July 7, 2024'], + 'In 2 days on July 1, 2024 then on July 5, 2024 and July 7, 2024' + ], ]); // construct time factory return(s) @@ -1623,13 +2035,51 @@ function ($v1, $v2, $v3) { }; } ); - $this->l10n->method('t')->willReturnMap([ - ['In a %1$s on %2$s', ['day', 'July 1, 2024'], 'In a day on July 1, 2024'], - ['In a %1$s on %2$s then on %3$s', ['day', 'July 1, 2024', 'July 5, 2024'], 'In a day on July 1, 2024 then on July 5, 2024'], - ['In a %1$s on %2$s then on %3$s and %4$s', ['day', 'July 1, 2024', 'July 5, 2024', 'July 9, 2024'], 'In a day on July 1, 2024 then on July 5, 2024 and July 9, 2024'], - ['In %1$s %2$s on %3$s', [2, 'days', 'July 1, 2024'], 'In 2 days on July 1, 2024'], - ['In %1$s %2$s on %3$s then on %4$s', [2, 'days', 'July 1, 2024', 'July 5, 2024'], 'In 2 days on July 1, 2024 then on July 5, 2024'], - ['In %1$s %2$s on %3$s then on %4$s and %5$s', [2, 'days', 'July 1, 2024', 'July 5, 2024', 'July 9, 2024'], 'In 2 days on July 1, 2024 then on July 5, 2024 and July 9, 2024'], + $this->l10n->method('n')->willReturnMap([ + // singular + [ + 'In a day on %1$s', + 'In %n days on %1$s', + 1, + ['July 1, 2024'], + 'In a day on July 1, 2024' + ], + [ + 'In a day on %1$s then on %2$s', + 'In %n days on %1$s then on %2$s', + 1, + ['July 1, 2024', 'July 5, 2024'], + 'In a day on July 1, 2024 then on July 5, 2024' + ], + [ + 'In a day on %1$s then on %2$s and %3$s', + 'In %n days on %1$s then on %2$s and %3$s', + 1, + ['July 1, 2024', 'July 5, 2024', 'July 9, 2024'], + 'In a day on July 1, 2024 then on July 5, 2024 and July 9, 2024' + ], + // plural + [ + 'In a day on %1$s', + 'In %n days on %1$s', + 2, + ['July 1, 2024'], + 'In 2 days on July 1, 2024' + ], + [ + 'In a day on %1$s then on %2$s', + 'In %n days on %1$s then on %2$s', + 2, + ['July 1, 2024', 'July 5, 2024'], + 'In 2 days on July 1, 2024 then on July 5, 2024' + ], + [ + 'In a day on %1$s then on %2$s and %3$s', + 'In %n days on %1$s then on %2$s and %3$s', + 2, + ['July 1, 2024', 'July 5, 2024', 'July 9, 2024'], + 'In 2 days on July 1, 2024 then on July 5, 2024 and July 9, 2024' + ], ]); // construct time factory return(s)