Index: pathauto.inc
===================================================================
--- pathauto.inc	(revision 6339)
+++ pathauto.inc	(working copy)
@@ -128,87 +128,82 @@
  *   The cleaned string.
  */
 function pathauto_cleanstring($string, $clean_slash = TRUE) {
-  // Default words to ignore
-  $ignore_words = array(
-    'a', 'an', 'as', 'at', 'before', 'but', 'by', 'for', 'from', 'is', 'in',
-    'into', 'like', 'of', 'off', 'on', 'onto', 'per', 'since', 'than', 'the',
-    'this', 'that', 'to', 'up', 'via', 'with',
-  );
+  static $strings = array();
+  $array_key = $string . (int)$clean_slash;
+  if (!isset($strings[$array_key])) {
+    // Default words to ignore
+    $ignore_words = array(
+      'a', 'an', 'as', 'at', 'before', 'but', 'by', 'for', 'from', 'is', 'in',
+      'into', 'like', 'of', 'off', 'on', 'onto', 'per', 'since', 'than', 'the',
+      'this', 'that', 'to', 'up', 'via', 'with',
+    );
 
-  // Replace or drop punctuation based on user settings
-  $separator = variable_get('pathauto_separator', '-');
-  $output = $string;
-  $punctuation = pathauto_punctuation_chars();
-  foreach ($punctuation as $name => $details) {
-    $action = variable_get('pathauto_punctuation_'. $name, 0);
-    // 2 is the action for "do nothing" with the punctuation
-    if ($action != 2) {
-      // Slightly tricky inline if which either replaces with the separator or nothing
-      $output = str_replace($details['value'], ($action ? $separator : ''), $output);
+    // Replace or drop punctuation based on user settings
+    $separator = variable_get('pathauto_separator', '-');
+    $output = $string;
+    $punctuation = pathauto_punctuation_chars();
+    foreach ($punctuation as $name => $details) {
+      $action = variable_get('pathauto_punctuation_'. $name, 0);
+      // 2 is the action for "do nothing" with the punctuation
+      if ($action != 2) {
+        // Slightly tricky inline if which either replaces with the separator or nothing
+        $output = str_replace($details['value'], ($action ? $separator : ''), $output);
+      }
     }
-  }
 
-  // If something is already urlsafe then don't remove slashes
-  if ($clean_slash) {
-    $output = str_replace('/', '', $output);
-  }
+    // If something is already urlsafe then don't remove slashes
+    if ($clean_slash) {
+      $output = str_replace('/', '', $output);
+    }
 
-  // Optionally remove accents and transliterate
-  if (variable_get('pathauto_transliterate', FALSE)) {
-    static $i18n_loaded = false;
-    static $translations = array();
+    // Optionally remove accents and transliterate
+    if (variable_get('pathauto_transliterate', FALSE)) {
+      $output = iconv("UTF-8", "ISO-8859-1//IGNORE//TRANSLIT", $output);
+    }
 
-    if (!$i18n_loaded) {
-      $path = drupal_get_path('module', 'pathauto');
-      if (is_file($path .'/i18n-ascii.txt')) {
-        $translations = parse_ini_file($path .'/i18n-ascii.txt');
-      }
-      $i18n_loaded = true;
+    // Reduce to the subset of ASCII96 letters and numbers
+    if (variable_get('pathauto_reduce_ascii', FALSE)) {
+      $pattern = '/[^a-zA-Z0-9\/]+/ ';
+      $output = preg_replace($pattern, $separator, $output);
     }
 
-    $output = strtr($output, $translations);
-  }
+    // Get rid of words that are on the ignore list
+    $ignore_re = '\b'. preg_replace('/,/', '\b|\b', variable_get('pathauto_ignore_words', $ignore_words)) .'\b';
 
-  // Reduce to the subset of ASCII96 letters and numbers
-  if (variable_get('pathauto_reduce_ascii', FALSE)) {
-    $pattern = '/[^a-zA-Z0-9\/]+/ ';
-    $output = preg_replace($pattern, $separator, $output);
-  }
+    if (function_exists('mb_eregi_replace')) {
+      $output = mb_eregi_replace($ignore_re, '', $output);
+    }
+    else {
+      $output = preg_replace("/$ignore_re/i", '', $output);
+    }
 
-  // Get rid of words that are on the ignore list
-  $ignore_re = '\b'. preg_replace('/,/', '\b|\b', variable_get('pathauto_ignore_words', $ignore_words)) .'\b';
+    // Always replace whitespace with the separator.
+    $output = preg_replace('/\s+/', $separator, $output);
 
-  if (function_exists('mb_eregi_replace')) {
-    $output = mb_eregi_replace($ignore_re, '', $output);
-  }
-  else {
-    $output = preg_replace("/$ignore_re/i", '', $output);
-  }
+    // In preparation for pattern matching,
+    // escape the separator if and only if it is not alphanumeric.
+    if (isset($separator)) {
+      if (preg_match('/^[^'. PREG_CLASS_ALNUM .']+$/uD', $separator)) {
+        $seppattern = $separator;
+      }
+      else {
+        $seppattern = '\\'. $separator;
+      }
+      // Trim any leading or trailing separators (note the need to
+      $output = preg_replace("/^$seppattern+|$seppattern+$/", '', $output);
 
-  // Always replace whitespace with the separator.
-  $output = preg_replace('/\s+/', $separator, $output);
-
-  // In preparation for pattern matching,
-  // escape the separator if and only if it is not alphanumeric.
-  if (isset($separator)) {
-    if (preg_match('/^[^'. PREG_CLASS_ALNUM .']+$/uD', $separator)) {
-      $seppattern = $separator;
+      // Replace multiple separators with a single one
+      $output = preg_replace("/$seppattern+/", "$separator", $output);
     }
-    else {
-      $seppattern = '\\'. $separator;
-    }
-    // Trim any leading or trailing separators (note the need to
-    $output = preg_replace("/^$seppattern+|$seppattern+$/", '', $output);
 
-    // Replace multiple separators with a single one
-    $output = preg_replace("/$seppattern+/", "$separator", $output);
+    // Enforce the maximum component length
+    $maxlength = min(variable_get('pathauto_max_component_length', 100), 128);
+    $output = drupal_substr($output, 0, $maxlength);
+
+    $strings[$array_key] = $output;
   }
 
-  // Enforce the maximum component length
-  $maxlength = min(variable_get('pathauto_max_component_length', 100), 128);
-  $output = drupal_substr($output, 0, $maxlength);
-
-  return $output;
+  return $strings[$array_key];
 }
 
 /**
@@ -446,16 +441,21 @@
  *   An array of the cleaned tokens.
  */
 function pathauto_clean_token_values($full) {
-  foreach ($full->values as $key => $value) {
-    // If it's a "path" or "url friendly" token don't remove the "/" character
-    if (drupal_substr($full->tokens[$key], -4, 4) === 'path' || drupal_substr($full->tokens[$key], -8, 8) === 'path-raw' || drupal_substr($full->tokens[$key], -5, 5) === 'alias') {
-      $full->values[$key] = pathauto_cleanstring($value, FALSE);
+  static $values = array();
+  $array_key = md5(json_encode($full));
+  if (!isset($values[$array_key])) {
+    foreach ($full->values as $key => $value) {
+      // If it's a "path" or "url friendly" token don't remove the "/" character
+      if (drupal_substr($full->tokens[$key], -4, 4) === 'path' || drupal_substr($full->tokens[$key], -8, 8) === 'path-raw' || drupal_substr($full->tokens[$key], -5, 5) === 'alias') {
+        $full->values[$key] = pathauto_cleanstring($value, FALSE);
+      }
+      else {
+        $full->values[$key] = pathauto_cleanstring($value);
+      }
     }
-    else {
-      $full->values[$key] = pathauto_cleanstring($value);
-    }
+    $values[$array_key] = $full->values;
   }
-  return $full->values;
+  return $values[$array_key];
 }
 
 /**
