--- i18n.module	2009-02-06 14:02:56.000000000 +0300
+++ i18n.module.new	2009-02-07 13:31:34.000000000 +0300
@@ -28,12 +28,11 @@ function i18n_get_lang($setlanguage = NU
   //see if the language is already set.
   if ($setlanguage) {
     $i18n_language = $setlanguage;
-  } elseif ($i18n_language) {
-    return $i18n_language;
-  } else {
+  } elseif (!isset($i18n_language)) {
     _i18n_init();
-    return $i18n_language = _i18n_get_lang();
+    $i18n_language = _i18n_get_lang();
   }
+  return $i18n_language;
 }
 
 /**
@@ -41,9 +40,11 @@ function i18n_get_lang($setlanguage = NU
  */
 function _i18n_init(){
   global $i18n_langpath;
-  $path = _i18n_get_original_path();
-  $i18n_langpath = i18n_get_lang_prefix($path);
-}  
+  if (!isset($i18n_langpath)) {
+    $path = _i18n_get_original_path();
+    $i18n_langpath = i18n_get_lang_prefix($path);
+  }  
+}
 
 /**
  * Language block
@@ -94,11 +95,18 @@ function i18n_init(){
     } 
   } elseif ($lang == $path) { // When path is only language code
     $_GET['q'] = i18n_frontpage($lang);
+    if ($lang == i18n_default_language()) {
+      i18n_get_lang_prefix($path, TRUE);
+      _i18n_goto($path);
+    }
   }
   elseif ($i18n_langpath) {
     //search alias with and without lang and remove lang.
     $_GET['q'] = i18n_get_normal_path($path);
   }
+  if (!_i18n_add_lang_prefix($lang) && i18n_get_lang_prefix($path, TRUE)) {
+    _i18n_goto($path);
+  }
  
 }
 
@@ -306,7 +314,21 @@ function i18n_admin_settings() {
     '#maxlength' => 10,
     '#description' => t('Image size for language icons, in the form "width x height".'),
   );
-
+  // Language prefix
+  $form['prefix'] = array(
+  '#type' => 'fieldset',
+  '#title' => t('Language prefix'),
+  '#collapsible' => TRUE,
+  '#collapsed' => TRUE,
+  '#description' => t('Note: If you wish comparability with navigation mode (without language prefix), when module i18n is disabled, disable settings.'),
+  );
+  $form['prefix']['i18n_prefix_default'] = array(
+  '#type' => 'radios',
+  '#title' => t('Language prefix for default language'),
+  '#default_value' => variable_get('i18n_prefix_default', 0),
+  '#options' => array(t('Disabled'), t('Enabled' )),
+  '#description' => t("Add a language prefix to Drupal paths when the current language is the default language. Some established sites or single language sites with default language is not English may wish to disable language prefix of Drupal paths when enabling i18n module."),
+  );
   // Advanced options
   $form['advanced'] = array(
     '#type' => 'fieldset',
@@ -430,18 +452,22 @@ function i18n_languages($key = 'active')
  * Get language from browser settings, but only if it is a valid language
  */
 function i18n_get_browser_lang() {
-  $languages = i18n_supported_languages();
-  $exploded_server = explode(";", $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
-  $accept=explode(',', array_shift($exploded_server));
-  foreach ($accept as $lang) {
-    if(empty($lang)) {
-      continue;
-    } elseif (array_key_exists($lang, $languages)) {
-      return $lang;
-    } elseif (array_key_exists(substr($lang, 0, 2), $languages)) {
-      return substr($lang, 0, 2);
+  static $browser_lang;
+  if (!isset($browser_lang)) {
+    $languages = i18n_supported_languages();
+    $exploded_server = explode(";", $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
+    $accept = explode(',', array_shift($exploded_server));
+    $browser_lang = '';
+    foreach ($accept as $lang) {
+      if (($lang = @trim($lang)) &&
+          (array_key_exists(($lang = strtolower($lang)), $languages)
+          || array_key_exists(($lang = substr($lang, 0, 2)), $languages))) {
+        $browser_lang = $lang;
+        break;
+      }
     }
   }
+  return $browser_lang;
 }
 
 /**
@@ -455,12 +481,56 @@ function i18n_get_lang_prefix(&$path, $t
   $exploded_path = explode('/', $path);
   $maybelang = array_shift($exploded_path);
   $languages = i18n_languages();
-  if (array_key_exists($maybelang, $languages)){
-    if ($trim) {
-      $path = trim(substr($path, strlen($maybelang)),'/');
+  if (array_key_exists($maybelang, $languages)) {
+    $last_lang = '';
+    $exploded_path_exists = count($exploded_path);
+    foreach ($exploded_path as $k => $alt_lang) {
+    	if (!array_key_exists($alt_lang, $languages)) {
+      	break;
+      }
+      $last_lang = $alt_lang;
+    	unset($exploded_path[$k]);
     }
-    return $maybelang;
+
+    // Normal Case
+    // /uk => /uk
+    if (!$exploded_path) {
+      // Redirect for frontpage with many lang prefix
+      // /uk/en/fr/ru => /uk
+      if ($exploded_path_exists) {
+      	_i18n_goto($maybelang);
+      }
+      $path = $trim ? '' : $maybelang;
+    }
+
+    // Redirect for page with many lang prefix
+    // 1. Translation if is node or taxonomy
+    //    /uk/ru/en/bla_bla => /en/bla_bla => /uk/bla_bla
+    // 2. Or change lang
+    //    /uk/ru/en/bla_bla => /uk/bla_bla
+    elseif ($last_lang) {
+      $new_path           = join('/', $exploded_path);
+      $last_lang_new_path = $last_lang .'/'. $new_path;
+      if ($last_lang_new_path == ($new_path = drupal_get_normal_path($last_lang_new_path))) {
+        $new_path = drupal_get_normal_path($new_path);
+      }
+      if (module_exists('translation') && function_exists('translation_url')) {
+        $new_path = translation_url($new_path, $maybelang);
+      }
+      _i18n_goto($new_path);
+    }
+
+    // Normal Case:
+    // 1. Without lang prefix: /en/bla_bla => /bla_bla
+    elseif ($trim) {
+    	$path = substr($path, strlen($maybelang) + 1);
+    }
+    // 2. With lang prefix:    /en/bla_bla => /en/bla_bla
+    // else {}
+  } else {
+    $maybelang = ''; // NO Language code.
   }
+  return $maybelang;
 }
 
 /**
@@ -468,8 +538,15 @@ function i18n_get_lang_prefix(&$path, $t
  * This function will search for aliases like 'en/home', 'es/home'...
  */
 function i18n_frontpage($lang = NULL) {
-  $lang = $lang ? $lang : _i18n_get_lang();
-  return i18n_get_normal_path($lang.'/'.variable_get('site_frontpage','node'));
+  static $paths = array();
+  $lang = $lang ? strtolower(@trim($lang)) : _i18n_get_lang();
+  if (!isset($paths[$lang])) {
+    $path = _i18n_add_lang_prefix($lang)
+          ? $lang.'/'.variable_get('site_frontpage','node')
+          : variable_get('site_frontpage','node');
+    $paths[$lang] = i18n_get_normal_path($path);
+  }
+  return $paths[$lang];
 }
 
 /**
@@ -506,17 +583,15 @@ function i18n_get_normal_path($path) {
  */
 function i18n_path($path, $lang) {
   if (!$path || $path == i18n_frontpage($lang)) {
-    return $lang;
-  } elseif($alias = drupal_lookup_path('alias', $path)) {
-	  if($prefix = i18n_get_lang_prefix($alias)) {
-      // This alias will be valid only if it has the same language
-	    return ($prefix == $lang) ? $alias : $lang.'/'.$path;
-	  } else { // Alias without language prefix
-	    return $lang.'/'.$alias;
-	  }
-  } else { // Alias for language path will be searched later
-    return $lang.'/'.$path;  
-  } 
+    return _i18n_add_lang_prefix($lang) ? $lang : '';
+  }
+  if(($alias = drupal_lookup_path('alias', $path)) && (!($prefix = i18n_get_lang_prefix($alias, TRUE)) || ($prefix && $prefix == $lang))) {
+  	$path = $alias;
+  }
+  if (_i18n_add_lang_prefix($lang)) {
+  	$path = $lang .'/'. $path;
+  }
+  return $path;
 }
 
 /**
@@ -567,6 +642,7 @@ function i18n_get_links($path = '', $que
     $path = '';
   }
   $names = $names ? $names : i18n_languages('native');
+  $links = array();
   foreach (array_keys(i18n_supported_languages()) as $lang){
     $links[$lang]= theme('i18n_link', $names[$lang], i18n_path($path, $lang), $lang, $query);
   }
@@ -706,8 +782,8 @@ if (!function_exists('custom_url_rewrite
  * Rewrites path with current language and removes prefix if searching for source path
  */
 function i18n_url_rewrite($type, $path, $original){
-  if ($type == 'alias' && !strpos($path, '://') && !i18n_get_lang_prefix($path)){
-    return $path ? i18n_get_lang() . '/'. $path : i18n_get_lang();
+  if ($type == 'alias' && !strpos($path, '://') && !i18n_get_lang_prefix($path) && _i18n_add_lang_prefix(($cur_lang = i18n_get_lang()))) {
+    return $path ? $cur_lang .'/'. $path : $cur_lang;
   } elseif ($type == 'source') {
     if ($path == $original) {
       return i18n_get_normal_path($path);
@@ -1205,5 +1281,28 @@ function _i18n_set_db_prefix($lang) {
  * Cannot use $_GET["q"] cause it may have been already changed
  */
 function _i18n_get_original_path() {
-  return isset($_REQUEST["q"]) ? trim($_REQUEST["q"],"/") : '';
+  static $path;
+  if (!isset($path)) {
+    $path = isset($_REQUEST["q"]) ? trim($_REQUEST["q"],"/") : '';
+  }
+  return $path;
+}
+
+/**
+ * Case when add language prefix for Drupal path.
+ *
+ * @param string $lang
+ *  Language.
+ *
+ * @return bool
+ *  TRUE when need add language prefix for language, or FALSE.
+ */
+function _i18n_add_lang_prefix($lang){
+  static $languages = array();
+  if (!isset($languages[$lang])) {
+    $default = i18n_default_language();
+    $current = i18n_get_lang();
+    $languages[$lang] = (!(!variable_get('i18n_prefix_default', 0) && $lang == $default)) || ($current != $default);
+  }
+  return $languages[$lang];
 }
