diff --git a/date_repeat/date_repeat.module b/date_repeat/date_repeat.module
index d6cb25b..29e1bc3 100644
--- a/date_repeat/date_repeat.module
+++ b/date_repeat/date_repeat.module
@@ -42,9 +42,15 @@ function date_repeat_menu() {
 
 function date_repeat_theme() {
   return array(
-    'date_repeat' => array('arguments' => array('element' => NULL)),
-    'date_repeat_current_exceptions' => array('arguments' => array('element' => NULL)),
-    'date_repeat_current_additions' => array('arguments' => array('element' => NULL)),
+    'date_repeat' => array(
+      'arguments' => array('element' => NULL)
+    ),
+    'date_repeat_current_exceptions' => array(
+      'arguments' => array('element' => NULL)
+    ),
+    'date_repeat_current_additions' => array(
+      'arguments' => array('element' => NULL)
+    ),
   );
 }
 
@@ -75,9 +81,9 @@ function INTERVAL_options() {
 /**
  * Helper function for FREQ options.
  *
- * Translated and untranslated arrays of the iCal day of week names.
- * We need the untranslated values for date_modify(), translated
- * values when displayed to user.
+ * Translated and untranslated arrays of the iCal day of week names. We need the
+ * untranslated values for date_modify(), translated values when displayed to
+ * user.
  */
 function date_repeat_dow_day_options($translated = TRUE) {
   return array(
@@ -127,8 +133,8 @@ function date_repeat_dow_options() {
 /**
  * Translate a day of week position to the iCal day name.
  *
- * Used with date_format($date, 'w') or get_variable('date_first_day'),
- * which return 0 for Sunday, 1 for Monday, etc.
+ * Used with date_format($date, 'w') or get_variable('date_first_day'), which
+ * return 0 for Sunday, 1 for Monday, etc.
  *
  * dow 2 becomes 'TU', dow 3 becomes 'WE', and so on.
  */
@@ -138,8 +144,8 @@ function date_repeat_dow2day($dow) {
 }
 
 /**
- * Shift the array of iCal day names into the right order
- * for a specific week start day.
+ * Shift the array of iCal day names into the right order for a specific week
+ * start day.
  */
 function date_repeat_days_ordered($week_start_day) {
   $days = array_flip(array_keys(date_repeat_dow_day_options(FALSE)));
@@ -168,6 +174,9 @@ function date_repeat_rrule_description($rrule, $format = 'D M d Y') {
   require_once('./'. drupal_get_path('module', 'date_api') .'/date_api_ical.inc');
   require_once('./'. drupal_get_path('module', 'date_repeat') .'/date_repeat_calc.inc');
 
+  module_load_include('inc', 'date_api', 'date_api_ical');
+  module_load_include('inc', 'date_repeat', 'date_repeat_calc');
+
   // Make sure there will be an empty description for any unused parts.
   $description = array(
     '!interval' => '',
@@ -184,36 +193,74 @@ function date_repeat_rrule_description($rrule, $format = 'D M d Y') {
   $exceptions = $parts[1];
   $rrule = $parts[0];
   $interval = INTERVAL_options();
-  switch ($rrule['FREQ']) {
-    case 'WEEKLY':
-      $description['!interval'] = format_plural($rrule['INTERVAL'], 'every week', 'every @count weeks') .' ';
-      break;
-    case 'MONTHLY':
-      $description['!interval'] = format_plural($rrule['INTERVAL'], 'every month', 'every @count months') .' ';
-      break;
-    case 'YEARLY':
-      $description['!interval'] = format_plural($rrule['INTERVAL'], 'every year', 'every @count years') .' ';
-      break;
-    default:
-      $description['!interval'] = format_plural($rrule['INTERVAL'], 'every day', 'every @count days') .' ';
-      break;
+
+  if ($rrule['INTERVAL'] < 1) {
+    $rrule['INTERVAL'] = 1;
   }
 
+  if ((empty($rrule['BYDAY']) && empty($rrule['BYMONTHDAY']) && empty($rrule['BYMONTH']) || $rrule['FREQ'] == 'DAILY' || $rrule['FREQ'] == 'WEEKLY') || $rrule['INTERVAL'] > 1) {
+    switch ($rrule['FREQ']) {
+      case 'WEEKLY':
+        $description['!interval'] = format_plural($rrule['INTERVAL'], 'every week', 'every @count weeks') .' ';
+        break;
+      case 'MONTHLY':
+        $description['!interval'] = format_plural($rrule['INTERVAL'], 'every month', 'every @count months') .' ';
+        break;
+      case 'YEARLY':
+        $description['!interval'] = format_plural($rrule['INTERVAL'], 'every year', 'every @count years') .' ';
+        break;
+      default:
+        $description['!interval'] = format_plural($rrule['INTERVAL'], 'every day', 'every @count days') .' ';
+        break;
+    }
+  }
+
+  $days = date_repeat_dow_day_options();
+  $counts = date_repeat_dow_count_options();
+
+  // Sort the by-day results if any into two categories, those occurring weekly,
+  // and those occurring on the nth ordinal per month, grouped by ordinal
+  $ordinalResults = array();
+  $weeklyResults = array();
   if (!empty($rrule['BYDAY'])) {
-    $days = date_repeat_dow_day_options();
-    $counts = date_repeat_dow_count_options();
-    $results = array();
     foreach ($rrule['BYDAY'] as $byday) {
       $day = drupal_substr($byday, -2);
-      $count = intval(str_replace(' '. $day, '', $byday));
-      if ($count = intval(str_replace(' ' . $day, '', $byday))) {
-        $results[] = trim(t('!repeats_every_interval on the !date_order !day_of_week', array('!repeats_every_interval ' => '', '!date_order' => strtolower($counts[drupal_substr($byday, 0, 2)]), '!day_of_week' => $days[$day])));
+      $strCount = drupal_substr($byday, 0, 2);
+      if ($count = intval($strCount)) {
+        $instance = t($days[$day]);
+        if (empty($ordinalResults[$count])) {
+          $ordinalResults[$count] = array();
+        }
+        $ordinalResults[$count][] = $instance;
       }
       else {
-        $results[] = trim(t('!repeats_every_interval every !day_of_week', array('!repeats_every_interval ' => '', '!day_of_week' => $days[$day])));
+        $weeklyResults[] = t($days[$day]);
       }
     }
-    $description['!byday'] = implode(' '. t('and') .' ', $results);
+
+    $byDayResults = array();
+    if (!empty($weeklyResults)) {
+      $byDayResults[] = t('on') .' '. t(implodeGrammar($weeklyResults));
+    }
+    if (!empty($ordinalResults)) {
+      $resultsByOrdinal = array();
+      // TODO: Put this instances in the correct sequence. Currently they are
+      // 'fifth from last' to 'last', followed by 'first' to 'fifth'. They
+      // should probably be in order from earliest to latest so that 'first'
+      // comes before 'last'.
+      for ($i = -5; $i <= 5; $i++) {
+        if (!empty($ordinalResults[''. $i])) {
+          $ordinal = $i < 0 ? $i : ($i > 0 ? '+'. $i : '');
+          $resultsByOrdinal[] = t('the') .' '. drupal_strtolower(t($counts[$ordinal])) .' '. implodeGrammar($ordinalResults[$i]);
+        }
+      }
+      $byDayResults[] = t('on') .' '. t(implodeGrammar($resultsByOrdinal)) .' '. t('of the month');
+    }
+    $description['!byday'] = implodeGrammar($byDayResults);
+  }
+
+  if (!empty($rrule['COUNT'])) {
+    $description['!count'] = t('!count times', array('!count' => $rrule['COUNT']));
   }
   if (!empty($rrule['BYMONTH'])) {
     if (sizeof($rrule['BYMONTH']) < 12) {
@@ -222,31 +269,33 @@ function date_repeat_rrule_description($rrule, $format = 'D M d Y') {
       foreach ($rrule['BYMONTH'] as $month) {
         $results[] = $months[$month];
       }
-      if (!empty($rrule['BYMONTHDAY'])) {
-        $description['!bymonth'] = trim(t('!repeats_every_interval on the !month_days of !month_names', array('!repeats_every_interval ' => '', '!month_days' => implode(', ', $rrule['BYMONTHDAY']), '!month_names' => implode(', ', $results))));
+      $monthdays = $rrule['BYMONTHDAY'];
+      // Add ordinal suffix to each day
+      foreach ($monthdays as $id => $day) {
+        $monthdays[$id] = date_repeat_ordinal_suffix($day);
       }
-      else {
-        $description['!bymonth'] = trim(t('!repeats_every_interval on !month_names', array('!repeats_every_interval ' => '', '!month_names' => implode(', ', $results))));
+      if (!empty($monthdays)) {
+        if (empty($results)) {
+          $results[0] = "the month";
+        }
+        $description['!bymonth'] = t('on the !month_days of !month_names', array('!month_days' => implodeGrammar($monthdays), '!month_names' => implodeGrammar($results)));
+      }
+      elseif (!empty($rrule['BYMONTH'])) {
+        $description['!bymonth'] = t('during !month_names', array('!month_names' => implodeGrammar($results)));
       }
     }
   }
-  if ($rrule['INTERVAL'] < 1) {
-    $rrule['INTERVAL'] = 1;
-  }
-  if (!empty($rrule['COUNT'])) {
-    $description['!count'] = trim(t('!repeats_every_interval !count times', array('!repeats_every_interval ' => '', '!count' => $rrule['COUNT'])));
-  }
   if (!empty($rrule['UNTIL'])) {
     $until = date_ical_date($rrule['UNTIL'], 'UTC');
     date_timezone_set($until, date_default_timezone());
-    $description['!until'] = trim(t('!repeats_every_interval until !until_date', array('!repeats_every_interval ' => '', '!until_date' => date_format_date($until, 'custom', $format))));
+    $description['!until'] = t('until !until_date', array('!until_date' => date_format_date($until, 'custom', $format)));
   }
   if ($exceptions) {
     $values = array();
     foreach ($exceptions as $exception) {
       $values[] = date_format_date(date_ical_date($exception), 'custom', $format);
     }
-    $description['!except'] = trim(t('!repeats_every_interval except !except_dates', array('!repeats_every_interval ' => '', '!except_dates' => implode(', ', $values))));
+    $description['!except'] = t('except on !except_dates', array('!except_dates' => implodeGrammar($values)));
   }
   if ($additions) {
     $values = array();
@@ -257,9 +306,40 @@ function date_repeat_rrule_description($rrule, $format = 'D M d Y') {
   }
   if (!empty($rrule['WKST'])) {
     $day_names = date_repeat_dow_day_options();
-    $description['!week_starts_on'] = trim(t('!repeats_every_interval where the week start on !day_of_week', array('!repeats_every_interval ' => '', '!day_of_week' => $day_names[trim($rrule['WKST'])])));
+    $description['!week_starts_on'] = t('where the week starts on !day_of_week', array('!day_of_week' => $day_names[trim($rrule['WKST'])]));
+  }
+
+  $description = array_filter($description);
+  unset($description['!week_starts_on']); // Don't output this value
+
+  $output = implode(' ', $description);
+  $output = t('Repeats @repeat.', array('@repeat' => $output));
+
+  return $output;
+}
+
+/**
+ * Implodes an array of strings using punctuation and/or a conjunction,
+ * depending on the number of items in the array.
+ */
+function implodeGrammar($terms, $punctuation = ',', $conjunction = 'and') {
+  $conjunction = t($conjunction);
+  $count = count($terms);
+  if ($count == 1) {
+    return $terms[0];
   }
-  return t('Repeats !interval !bymonth !byday !count !until !except. !additional', $description);
+  elseif ($count == 2) {
+    return implode(' '. $conjunction .' ', $terms);
+  }
+  else {
+    $result = array();
+    for ($i = 0; $i < $count - 1; $i++) {
+      $result[] = $terms[$i];
+    }
+    $result[] = ' '. $conjunction .' '. $terms[$count - 1];
+    return implode($punctuation .' ', $result);
+  }
+  return '';
 }
 
 /**
@@ -293,7 +373,7 @@ function date_repeat_split_rrule($rrule) {
  * Analyze a RRULE and return dates that match it.
  */
 function date_repeat_calc($rrule, $start, $end, $exceptions = array(), $timezone = NULL, $additions = array()) {
-  require_once('./'. drupal_get_path('module', 'date_repeat') .'/date_repeat_calc.inc');
+  module_load_include('inc', 'date_repeat', 'date_repeat_calc');
   return _date_repeat_calc($rrule, $start, $end, $exceptions, $timezone, $additions);
 }
 
@@ -301,6 +381,22 @@ function date_repeat_calc($rrule, $start, $end, $exceptions = array(), $timezone
  * Generate the repeat rule setting form.
  */
 function date_repeat_rrule_process($element, $edit, $form_state, $form) {
-  require_once('./'. drupal_get_path('module', 'date_repeat') .'/date_repeat_form.inc');
+  module_load_include('inc', 'date_repeat', 'date_repeat_form');
   return _date_repeat_rrule_process($element, $edit, $form_state, $form);
 }
+
+/**
+ * Adds an ordinal suffix to a number
+ */
+function date_repeat_ordinal_suffix($number) {
+  switch ($number % 10) {
+    case 1:
+      return $number .'st';
+    case 2:
+      return $number .'nd';
+    case 3:
+      return $number .'rd';
+    default:
+      return $number .'th';
+  }
+}
