diff -rupN language_fallback-7.x-1.x-dev//language_fallback.admin.inc language_fallback-7.x-2.x-dev//language_fallback.admin.inc
--- language_fallback-7.x-1.x-dev//language_fallback.admin.inc	1970-01-01 00:00:00.000000000 +0000
+++ language_fallback-7.x-2.x-dev//language_fallback.admin.inc	2013-08-15 12:21:08.000000000 +0000
@@ -0,0 +1,306 @@
+<?php
+
+/**
+ * Implements hook_form_alter().
+ * 
+ * This is the place where user can set up language fallback for existing or new languages.
+ */
+function language_fallback_form_alter(&$form, &$form_state, $form_id) {
+	//if ($form_id == 'locale_languages_predefined_form' || $form_id == 'locale_languages_custom_form' || $form_id == 'locale_languages_edit_form') {
+
+	// There was a trouble making AJAX to work on "add language" form so it has been disabled.
+	if ($form_id == 'locale_languages_edit_form') {
+
+		$langcode = isset($form['langcode_view']) ? $form['langcode']['#value'] : NULL;
+		// Add select to create/edit form.
+		
+		$key = $form_id == 'locale_languages_predefined_form' ? 'language list' : 'custom language';
+		//$ajax_key = strtr($key, " ", "-");
+		$form['_key_'] = array('#value' => $key);
+		//$form[$key] = array('#type' => 'fieldset', '#title' => t('Language fallback'));
+		//$form[$key]['fallback'] = array('#tree' => true);
+		
+		$description = t('Please note that the default language can not be used inside fallback chain. If you do so, then all of the languages that follow it will be ignored.');
+		$description .= ' ';
+		$description .= t('For example if <strong>English</strong> is the default language then the chain <em>Polish => Russian => English => Italian => German</em> will be automatically changed to <em>Polish => Russian => English</em>.');
+		
+		$form[$key]['fallback'] = array(
+				'#type' => 'fieldset',
+				'#title' => t('Language fallback'),
+				'#tree' => true,
+				'#prefix' => '<div id="countries-fieldset-wrapper">',
+				'#suffix' => '</div>',
+				'#description' => $description
+		);
+
+		$countries = language_fallback_get_countries();
+
+		if (empty($form_state[$key]['fallback']['countries'])) {
+			$form_state[$key]['fallback']['countries'] = array(LANGUAGE_FALLBACK_ALL_COUNTRIES);
+			
+			if ($langcode) {
+			// Get all countries that we have a fallback for this language
+				$result = db_select('language_fallback', 'f')
+									->fields('f', array('country'))
+									->condition('language', $langcode, '=')
+									->condition('country', LANGUAGE_FALLBACK_ALL_COUNTRIES, '<>')
+									->execute();
+				while($c = $result->fetchField()){
+					$form_state[$key]['fallback']['countries'][] = $c;
+				}
+			}
+			
+		}
+		
+		foreach($form_state[$key]['fallback']['countries'] as $country){
+			language_fallback_get_fallback_form($form, $form_state, $key, $country, $countries[$country]);
+			
+			// Unset countries that are in use
+			unset($countries[$country]);
+		}
+		
+		if (count($countries) > 0) {
+			$form[$key]['fallback']['country'] = array(
+				'#type' => 'select',
+				'#options' => $countries
+			);
+			
+			$form[$key]['fallback']['add_country'] = array(
+				'#type' => 'submit',
+				'#value' => t('Add country specific fallback'),
+				'#submit' => array('language_fallback_country_add_another'),
+				'#ajax' => array(
+						'callback' => 'language_fallback_country_add_remove_ajax_callback',
+						'wrapper' => 'countries-fieldset-wrapper',
+				),
+			);
+		}
+
+		$form['#submit'][] = 'language_fallback_country_add_language_submit';
+		/**/
+	}
+}
+
+function language_fallback_get_fallback_form(&$form, &$form_state, $key, $ccode, $country){
+	$langcode = isset($form['langcode_view']) ? $form['langcode']['#value'] : NULL;
+	$default_lang = language_default();
+	$languages = language_list();
+	$options = locale_language_list();
+	
+	// Alter label of default language.
+	if (isset($options[$default_lang->language])) {
+		$options = array('' => t('Default language (@lang)', array('@lang' => $default_lang->name))) + $options;
+		unset($options[$default_lang->language]);
+	}
+	
+	// Add native name.
+	foreach ($options as $k => $option) {
+		if (!empty($languages[$k]->native)) {
+			$options[$k] .= " ({$languages[$k]->native})";
+		}
+	}
+	
+	$description = '';
+	if ($ccode == LANGUAGE_FALLBACK_ALL_COUNTRIES) {
+		$description = (!variable_get('language_fallback_country', false)
+					? t('Enable country specific fallback to create different fallbacks for each country.')
+					: t('This is default fallback chain for all countries. It will be used only if no country specific fallback is available.'));
+	}
+	$form[$key]['fallback'][$ccode] = array(
+			'#type' => 'fieldset',
+			'#title' => $country,
+			'#prefix' => '<div id="country-' . $ccode . '-fieldset-wrapper">', // This is unique to each country fallback chain
+			'#suffix' => '</div>',
+			'#description' => $description
+	);
+	
+	$chain = ($langcode ? language_fallback_get_chain($langcode, $ccode) : array());
+	
+	if (empty($form_state[$key]['fallback'][$ccode]['chain_length'])) {
+		$form_state[$key]['fallback'][$ccode]['chain_length'] = count($chain) + 1;
+	}
+	
+	for($i = 0; $i < $form_state[$key]['fallback'][$ccode]['chain_length']; $i++) {
+		$form[$key]['fallback'][$ccode][$i] = array(
+				'#type' => 'select',
+				'#options' => $options,
+				'#default_value' => ($i < count($chain) ? $chain[$i] : '')
+		);
+	}
+	
+	/**
+	 * WARNING!
+	 * Due to the nature of AJAX FAPI the submit button value MUST be unique!
+	 * See this: https://drupal.org/node/1342066
+	 * Or try this workaround: http://stackoverflow.com/a/6521617/899092\
+	 * 
+	 * This also applies the the "remove" button below.
+	 */
+	$form[$key]['fallback'][$ccode]['add'] = array(
+			'#type' => 'submit',
+			'#value' => t('Add another language for !country', array('!country' => $country)),
+			'#submit' => array('language_fallback_country_add_language_add_another'), // This is shared across all countries
+			'#ajax' => array(
+					'callback' => 'language_fallback_country_add_language_ajax_callback', // This is shared across all countries
+					'wrapper' => 'country-' . $ccode . '-fieldset-wrapper', // This is unique to each country fallback chain
+			),
+	);
+	
+	if ($ccode != LANGUAGE_FALLBACK_ALL_COUNTRIES) {
+		$form[$key]['fallback'][$ccode]['remove'] = array(
+			'#type' => 'submit',
+			'#value' => t('Remove fallback chain for !country', array('!country' => $country)),
+			'#submit' => array('language_fallback_country_remove_chain'), // This is shared across all countries
+			'#ajax' => array(
+					'callback' => 'language_fallback_country_add_remove_ajax_callback', // This is shared across all countries
+					'wrapper' => 'countries-fieldset-wrapper',
+			),
+		);
+	}
+}
+
+/**
+ * Ajax submit function for "Remove fallback chain for ..." button
+ * @param unknown $form
+ * @param unknown $form_state
+ */
+function language_fallback_country_remove_chain($form, &$form_state) {
+	
+	$key = $form['_key_']['#value'];
+
+	// Country to remove
+	$remove = $form_state['triggering_element']['#parents'][1];
+	if (($index = array_search($remove, $form_state[$key]['fallback']['countries'])) !== false) {
+		// Remove country
+	  unset($form_state[$key]['fallback']['countries'][$index]);
+	}
+	
+	$form_state['rebuild'] = TRUE;
+}
+
+/**
+ * Callback function for ajax calls that add country specific fallback fieldset.
+ * @param unknown $form
+ * @param unknown $form_state
+ */
+function language_fallback_country_add_remove_ajax_callback($form, $form_state) {
+
+	$key = $form['_key_']['#value'];
+	return $form[$key]['fallback'];
+}
+
+/**
+ * Ajax submit function for "Add country specific fallback" button.
+ * @param unknown $form
+ * @param unknown $form_state
+ */
+function language_fallback_country_add_another($form, &$form_state) {
+	
+	$key = $form['_key_']['#value'];
+	$form_state[$key]['fallback']['countries'][] = $form_state['values']['fallback']['country'];
+	
+	$form_state['rebuild'] = TRUE;
+}
+
+/**
+ * Callback function for ajax calls that add language select element to the country fieldset.
+ * @param unknown $form
+ * @param unknown $form_state
+ */
+function language_fallback_country_add_language_ajax_callback($form, $form_state) {
+	//dpm($form_state, 'ajax callback');
+	
+	$key = $form['_key_']['#value'];
+	
+	/**
+	 * See language_fallback_country_add_language_add_another() function
+	 * for explanation of the followin line:
+	 */
+	$country = $form_state['triggering_element']['#parents'][1];
+	
+	return $form[$key]['fallback'][$country];
+}
+
+/**
+ * Ajax submit function for "Add another language to ..." button.
+ * @param unknown $form
+ * @param unknown $form_state
+ */
+function language_fallback_country_add_language_add_another($form, &$form_state) {
+	//dpm($form_state, 'ajax submit');
+	
+	$key = $form['_key_']['#value'];
+	
+	/**
+	 * The element that triggered this callback is "described" here:
+	 * $form_state['triggering_element'].
+	 * We know that this is an array that looks like this:
+	 * array(
+	 *  0 => 'fallback',
+	 *  1 => [COUNTRY],
+	 *  2 => 'add'
+	 * );
+	 * So we need the '1' index to know wchich country needs another select element.
+	 */
+	$country = $form_state['triggering_element']['#parents'][1];
+	$form_state[$key]['fallback'][$country]['chain_length']++;
+	
+	$form_state['rebuild'] = TRUE;
+}
+
+function language_fallback_country_add_language_submit($form, &$form_state) {
+	$key = $form['_key_']['#value'];
+	$fallbacks = $form_state['values']['fallback'];
+	$language = $form_state['values']['langcode'];
+	
+	//dpm($form_state);
+	
+	// Delete old entries. New entries will be added only if needed.
+	db_delete('language_fallback')->condition('language', $language, '=')->execute();
+	variable_del('locale_custom_strings_' . $language);
+	$set_variable = false;
+	
+	foreach($fallbacks as $country => $fallback) {
+		// Omit unwanted values.
+		if (!is_array($fallback))
+			continue;
+		
+		// Fix fallback array
+		$fixed = array();
+		foreach($fallback as $id => $lang) {
+			/* Default language is empty. We don't need that.
+			 * We also assume that default language means end of fallback chain
+			 * so we skip all following languages.
+			 */
+			if (strlen($lang) == 0)
+				break;
+				
+			// The 'Add' and 'Remove' button is also here, so we omit that.
+			if (strval($id) == 'add' || strval($id) == 'remove')
+				continue;
+				
+			// Prevent deadlocks.
+			if ($lang == $language)
+				continue;
+				
+			// Ignore languages that are already added.
+			if (array_search($lang, $fixed) !== false)
+				continue;
+			
+			// Add language to the chain.
+			$fixed[] = $lang;
+		}
+
+		if (count($fixed) > 0) {
+			// This stores our settings
+			db_insert('language_fallback')->fields(array('language' => $language, 'country' => $country, 'chain' => implode('|', $fixed)))->execute();
+				
+			$set_variable = true;
+		}
+	}
+	
+	if ($set_variable) {
+		// This tells drupal to use our fallback mechanism for string translation
+		variable_set('locale_custom_strings_' . $language, new localeWithFallback($language));
+	}
+}
\ No newline at end of file
diff -rupN language_fallback-7.x-1.x-dev//language_fallback.block.inc language_fallback-7.x-2.x-dev//language_fallback.block.inc
--- language_fallback-7.x-1.x-dev//language_fallback.block.inc	1970-01-01 00:00:00.000000000 +0000
+++ language_fallback-7.x-2.x-dev//language_fallback.block.inc	2013-08-15 12:14:56.000000000 +0000
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * Implements hook_block_info().
+ */
+function language_fallback_block_info() {
+	$blocks['country_selection'] = array(
+		'info' => t('Country selection'),
+		'cache' => DRUPAL_NO_CACHE,
+	);
+	return $blocks;
+}
+
+/**
+ * Implements hook_block_view().
+ */
+function language_fallback_block_view($delta = '') {
+	switch ($delta) {
+		case 'country_selection':
+			$block['subject'] = t('Select country');
+			$block['content'] = drupal_get_form('language_fallback_country_select_block_form');
+			return $block;
+	}
+}
+
+/**
+ * Callback to generate form for country selection block.
+ * @param unknown $form_id
+ * @param unknown $form_state
+ * @return multitype:multitype:NULL  multitype:string NULL  multitype:string NULL unknown
+ */
+function language_fallback_country_select_block_form($form_id, $form_state) {
+	
+	/* There is no need for fancy AJAXification.
+	 * The page reload is needed anyway to view
+	 * content in another language.
+	 */
+	$form = array();
+	
+	$countries = language_fallback_get_countries();
+	
+	if (count($countries) < 2) {
+		$form[] = array('#markup' => t('Country selection is disabled'));
+	} else {
+		$form['country'] = array(
+				'#type' => 'select',
+				'#options' => $countries,
+				'#default_value' => language_fallback_get_country()
+		);
+		$form['submit'] = array(
+				'#type' => 'submit',
+				'#value' => t('Save')
+		);
+	}
+	
+	return $form;
+}
+
+function language_fallback_country_select_block_form_submit($form, $form_state) {
+	language_fallback_set_country($form_state['values']['country']);
+}
\ No newline at end of file
diff -rupN language_fallback-7.x-1.x-dev//language_fallback.fallback.inc language_fallback-7.x-2.x-dev//language_fallback.fallback.inc
--- language_fallback-7.x-1.x-dev//language_fallback.fallback.inc	2013-04-20 07:51:39.000000000 +0000
+++ language_fallback-7.x-2.x-dev//language_fallback.fallback.inc	2013-08-14 18:14:27.000000000 +0000
@@ -8,13 +8,12 @@ class localeWithFallback implements Arra
 
   private $langcode;
   private $cache = array();
-  private $fallback;
+  private $fallbacks;
 
-  public function __construct($langcode, $fallback = '') {
+  public function __construct($langcode) {
     $languages = language_list();
     $this->langcode = isset($languages[$langcode]) ? $langcode : language_default('language');
     $this->cache = array();
-    $this->fallback = isset($languages[$fallback]) ? $fallback : language_default('langauge');
   }
 
   public function offsetExists($offset) {
@@ -23,7 +22,16 @@ class localeWithFallback implements Arra
 
   public function &offsetGet($offset) {
     if (!isset($this->cache[$offset])) {
-      $this->cache[$offset] = new localeContextWithFallback($this->langcode, $this->fallback, $offset);
+    	/**
+    	 * Fallback chains are red and cached with the first call to offsetGet() function.
+    	 * This is on purpouse, to prevent chains to be stored in database when
+    	 * variable_set() function is called on language sttings form.
+    	 */
+    	if (!isset($this->fallbacks)) {
+    		$this->fallbacks = language_fallback_get_chain($this->langcode);
+    	}
+    	
+      $this->cache[$offset] = new localeContextWithFallback($this->langcode, $this->fallbacks, $offset);
     }
     return $this->cache[$offset];
   }
@@ -53,19 +61,19 @@ class localeContextWithFallback implemen
   private $context = '';
   private $fallback;
 
-  public function __construct($langcode, $fallback, $context) {
+  public function __construct($langcode, $fallbacks, $context) {
     $languages = language_list();
     $this->first_language = isset($languages[$langcode]) ? $langcode : language_default('language');
-    $this->second_language = isset($languages[$fallback]) ? $fallback : language_default('language');
+    $this->second_language = $fallbacks ? array_shift($fallbacks) : language_default('language');
     $this->context = $context;
-    $second_lang_obj = $languages[$this->second_language];
+    
     // If the fallback is the default language, we don't need a
     // localeContextWithFallback since the default language does not have a
     // fallback. Otherwise we use a localeContextWithFallback so we gradually
     // fall back to the default language (cascading fallbacks, see
     // http://drupal.org/node/1877880 for more info.
     if ($this->second_language != language_default('language')) {
-      $this->fallback = new localeContextWithFallback($this->second_language, isset($languages[$second_lang_obj->fallback]) ? $second_lang_obj->fallback : language_default('language'), $context);
+      $this->fallback = new localeContextWithFallback($this->second_language, $fallbacks, $context);
     }
   }
 
diff -rupN language_fallback-7.x-1.x-dev//language_fallback.info language_fallback-7.x-2.x-dev//language_fallback.info
--- language_fallback-7.x-1.x-dev//language_fallback.info	2013-04-20 13:11:06.000000000 +0000
+++ language_fallback-7.x-2.x-dev//language_fallback.info	2013-08-15 01:52:07.000000000 +0000
@@ -7,9 +7,4 @@ dependencies[] = locale
 
 files[] = language_fallback.fallback.inc
 
-; Information added by drupal.org packaging script on 2013-04-20
-version = "7.x-1.0+2-dev"
-core = "7.x"
-project = "language_fallback"
-datestamp = "1366463466"
-
+configure = admin/config/regional/language_fallback
\ No newline at end of file
diff -rupN language_fallback-7.x-1.x-dev//language_fallback.install language_fallback-7.x-2.x-dev//language_fallback.install
--- language_fallback-7.x-1.x-dev//language_fallback.install	2013-04-20 07:51:39.000000000 +0000
+++ language_fallback-7.x-2.x-dev//language_fallback.install	2013-08-15 10:08:47.000000000 +0000
@@ -1,49 +1,117 @@
-<?php
-
-/**
- * @file
- * Schema, update and install function for Language Fallback.
- */
-
-/**
- * Implements hook_schema_alter().
- */
-function language_fallback_schema_alter(&$schema) {
-  if (isset($schema['languages'])) {
-    $schema['languages']['fields']['fallback'] = array(
-      'type' => 'varchar',
-      'length' => 12,
-      'not null' => TRUE,
-      'default' => '',
-      'description' => "Language code, e.g. 'de' or 'en-US'.",
-    );
-  }
-}
-
-/**
- * Implements hook_install().
- */
-function language_fallback_install() {
-  // Add the field to the languages table so that the 'fallback' property is set
-  // on every object in the array returned by language_list().
-  db_add_field(
-    'languages',
-    'fallback',
-    array(
-      'type' => 'varchar',
-      'length' => 12,
-      'not null' => TRUE,
-      'default' => '',
-      'description' => "Language code, e.g. 'de' or 'en-US'.",
-    )
-  );
-  drupal_static_reset('language_list');
-}
-
-/**
- * Implements hook_uninstall().
- */
-function language_fallback_uninstall() {
-  db_drop_field('languages', 'fallback');
-  drupal_static_reset('language_list');
-}
+<?php
+
+/**
+ * @file
+ * Schema, update and install function for Language Fallback.
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function language_fallback_schema() {
+  $schema['language_fallback'] = array(
+    'description' => 'Contains fallback chains for languages',
+    'fields' => array(
+      'language' => array(
+        'description' => 'Lang code',
+        'type' => 'varchar',
+        'length' => 8,
+        'not null' => true,
+      ),
+    	'country' => array(
+      	'description' => 'Visitor country code or "all" for all countries',
+    		'type' => 'varchar',
+    		'length' => 3,
+    		'not null' => true,
+    		'default' => 'all'
+      ),
+    	'chain' => array(
+      	'description' => 'Fallback chain ("|" delimiter)',
+    		'type' => 'varchar',
+    		'length' => 255,
+    		'not null' => true,
+      ),
+    ),
+    'primary key' => array('language', 'country'),
+  );
+  return $schema;
+}
+
+/**
+ * Implements hook_disable()
+ *
+ * WARNING!
+ * It is mandatory to remove all "locale_custom_strings_ID" variables!
+ * After this module is disabled the class localeWithFallback is no longer
+ * available but these variables hold reference to it.
+ */
+function language_fallback_disable(){
+	/**
+	 * We do not know all our variable names because they are created dynamically.
+	 * So to remove unwanted variables we first need to know their names.
+	 *
+	 * Our variables are "locale_custom_strings_ID"
+	 * and their values contain "localeWithFallback" stirng.
+	 *
+	 * So the trick is to read all variable names from "variable" table
+	 * that met the criteria above.
+	 */
+	
+	$result = db_update("variable")
+						->expression('name', "CONCAT('_', name)")
+						->condition('name', 'locale_custom_string_%', 'LIKE')
+						->condition('value', '%localeWithFallback%', 'LIKE')
+						->execute();
+}
+
+/**
+ * Implements hook_enable()
+ * 
+ * Revert back "locale_custom_strings_ID" variable names.
+ * See language_fallback_disable() for details.
+ */
+function language_fallback_enable(){
+	$result = db_update("variable")
+						->expression('name', "REPLACE(name, '_locale_custom_strings_', 'locale_custom_strings_')")
+						->condition('name', '_locale_custom_string_%', 'LIKE')
+						->condition('value', '%localeWithFallback%', 'LIKE')
+						->execute();
+}
+
+/**
+ * Implements hook_uninstall()
+ * 
+ * WARNING!
+ * It is mandatory to remove all "locale_custom_strings_ID" variables!
+ * After this module is disabled the class localeWithFallback is no longer
+ * available but these variables hold reference to it.
+ */
+function language_fallback_uninstall(){
+	
+	/**
+	 * We do not know all our variable names because they are created dynamically.
+	 * So to remove unwanted variables we first need to know their names.
+	 * 
+	 * Our variables are "locale_custom_strings_ID" but they were renamed on
+	 * hook_disable to "_locale_custom_strings_ID".
+	 * and their values contain "localeWithFallback" stirng.
+	 * 
+	 * So the trick is to read all variable names from "variable" table
+	 * that met the criteria above.
+	 */
+	$result = db_select("variable", "v")
+						->fields('v', array('name'))
+						->condition('name', '_locale_custom_string_%', 'LIKE')
+						->condition('value', '%localeWithFallback%', 'LIKE')
+						->execute();
+	
+	while($name = $result->fetchField()){
+		variable_del($name);
+	}
+	
+	/**
+	 * WARNING!
+	 * This is also very important as variables are cached!
+	 */
+	cache_clear_all('variables', 'cache_bootstrap');
+}
\ No newline at end of file
diff -rupN language_fallback-7.x-1.x-dev//language_fallback.module language_fallback-7.x-2.x-dev//language_fallback.module
--- language_fallback-7.x-1.x-dev//language_fallback.module	2013-04-20 07:51:39.000000000 +0000
+++ language_fallback-7.x-2.x-dev//language_fallback.module	2013-08-15 11:52:00.000000000 +0000
@@ -1,65 +1,156 @@
 <?php
 
+define('LANGUAGE_FALLBACK_ALL_COUNTRIES', 'all');
+
+/**
+ * Administration forms are moved the separate file for better readability.
+ * The same goes for blocks.
+ */
+module_load_include('inc', 'language_fallback', 'language_fallback.admin');
+module_load_include('inc', 'language_fallback', 'language_fallback.block');
+
+/**
+ * Implements hook_menu().
+ */
+function language_fallback_menu() {
+	$items = array();
+
+	$items['admin/config/regional/language_fallback'] = array(
+			'title' => 'Language fallback',
+			'description' => 'Configuration for Language fallback module',
+			'page callback' => 'drupal_get_form',
+			'page arguments' => array('language_fallback_settings_form'),
+			'access arguments' => array('access administration pages'),
+			'type' => MENU_NORMAL_ITEM,
+			'file' => 'language_fallback.settings.inc'
+	);
+
+	return $items;
+}
+
+/**
+ * Implements Drupal hook_language_fallback_candidates_alter().
+ * 
+ * This function provides fallback features for entities.
+ * 
+ * @param $fallback_candidates: An array of language codes whose order will determine the language fallback order.
+ */
+function language_fallback_language_fallback_candidates_alter(array &$fallback_candidates) {
+	
+	// Check if entity fallback is enabled
+	if (!variable_get('language_fallback_entity', false))
+		return;
+	
+	global $language;
+	
+	if (LANGUAGE_NONE == $language->language)
+		return;  // There is no fallback for "Undeterminated" language.
+	
+	// Get fallback chain for current language
+	$fallbacks = language_fallback_get_chain($language->language);
+	
+	if (count($fallbacks) > 0) {
+		$fallback_candidates = $fallbacks;
+	}
+}
+
 /**
- * @file
- * Hook implementations for the Language Fallback module.
+ * Get fallback chain for specified language.
+ * If you want to hook up to language fallback module - this is the place to start.
+ * 
+ * @param string $lang: Language code for which fallback chain is needed.
+ * @param string $country: Country code for which fallback chain is needed.
+ * @return array of languages. An empty array is returned if no fallback is defined.
  */
+function language_fallback_get_chain($lang, $country = false){
+	$chains = &drupal_static(__FUNCTION__);
+	
+	if (!isset($chains))
+		$chains = array();
+	
+	if ($country === false)
+		$country = language_fallback_get_country();
+	
+	// Check cache - maybe the chain was already loaded
+	if (!isset($chains[$lang][$country])) {
+		
+		$chain = db_select('language_fallback', 'f')
+							->fields('f', array('chain'))
+							->condition('language', $lang, '=')
+							->condition('country', $country, '=')
+							->execute()
+							->fetchField();
+		
+		if ($chain) {
+			// We have a fallback chain for this country
+			$chains[$lang][$country] = explode("|", $chain); // for better readability fallback chains are stored in a string separated with "|" character.
+		}
+		else if ($country == LANGUAGE_FALLBACK_ALL_COUNTRIES) {
+			// We don't have a fallback chain for all countries
+			$chains[$lang][$country] = array();
+		}
+		else {
+			// We dno't have fallback so we try default fallback for all countries
+			// WARNING! Recurency!
+			$chains[$lang][$country] = language_fallback_get_chain($lang, LANGUAGE_FALLBACK_ALL_COUNTRIES);
+		} 
+	}
+
+	return $chains[$lang][$country];
+}
 
 /**
- * Implements hook_form_alter().
+ * Get country code for fallback check.
+ * 
+ * @return string Either country code for fallback chain lookup or empty string if no country is specified for current visitor.
  */
-function language_fallback_form_alter(&$form, &$form_state, $form_id) {
-  if ($form_id == 'locale_languages_predefined_form' || $form_id == 'locale_languages_custom_form' || $form_id == 'locale_languages_edit_form') {
-    // Store language for edit form or FALSE on create forms.
-    $editmode = isset($form['langcode_view']) ? $form['langcode']['#value'] : FALSE;
-    $default_lang = language_default();
-    $languages = language_list();
-    $options = locale_language_list();
-
-    // Alter label of default language.
-    if (isset($options[$default_lang->language])) {
-      $options = array('' => t('Default language (@lang)', array('@lang' => $default_lang->name))) + $options;
-      unset($options[$default_lang->language]);
-    }
-
-    // Add native name.
-    foreach ($options as $key => $option) {
-      if (!empty($languages[$key]->native)) {
-        $options[$key] .= " ({$languages[$key]->native})";
-      }
-    }
-
-    // Add select to create/edit form.
-    $key = $form_id == 'locale_languages_predefined_form' ? 'language list' : 'custom language';
-    $form[$key]['fallback'] = array(
-      '#type' => 'select',
-      '#title' => t('Language fallback'),
-      '#default_value' => '',
-      '#options' => $options,
-      '#description' => t('This language will be used as a fallback for text that has no translation in the selected language.'),
-    );
-    $form['#submit'][] = 'language_fallback_add_language_submit';
-
-    // Remove current language in edit mode, set default.
-    if ($editmode) {
-      unset($form[$key]['fallback']['#options'][$editmode]);
-      $form[$key]['fallback']['#default_value'] = $languages[$editmode]->fallback;
-    }
-  }
+function language_fallback_get_country(){
+	
+	// Check if country specific fallback is enabled
+	if (variable_get('language_fallback_country', false)){
+		
+		// Check if country is stored in a session variable
+		if (isset($_SESSION['language_fallback_country'])) {
+			return $_SESSION['language_fallback_country'];
+		}	else if (function_exists('smart_ip_get_location')) {
+			
+			// Use smart IP to get user location
+			$country = smart_ip_get_location(ip_address());
+			if ($country !== false)
+				$_SESSION['language_fallback_country'] = strtoupper($country['country_code']);
+			else
+				$_SESSION['language_fallback_country'] = LANGUAGE_FALLBACK_ALL_COUNTRIES;
+		} else
+			$_SESSION['language_fallback_country'] = LANGUAGE_FALLBACK_ALL_COUNTRIES;
+	}
+	
+	return $_SESSION['language_fallback_country'];
 }
 
 /**
- * Form submit callback.
+ * Set country code for current user.
+ * @param string $country
  */
-function language_fallback_add_language_submit($form, &$form_state) {
-  db_update('languages')
-    ->fields(array('fallback' => $form_state['values']['fallback']))
-    ->condition('language', $form_state['values']['langcode'])
-    ->execute();
-  if (!empty($form_state['values']['fallback'])) {
-    variable_set('locale_custom_strings_' . $form_state['values']['langcode'], new localeWithFallback($form_state['values']['langcode'], $form_state['values']['fallback']));
-  }
-  else {
-    variable_del('locale_custom_strings_' . $form_state['values']['langcode']);
-  }
+function language_fallback_set_country($country = false){
+	if ($country)
+		$country = LANGUAGE_FALLBACK_ALL_COUNTRIES;
+	
+	$_SESSION['language_fallback_country'] = $country;
 }
+
+/**
+ * Get list of countries for country specific fallback.
+ * @return array with country names keyed by country code.
+ */
+function language_fallback_get_countries(){
+	$ret = array(
+			LANGUAGE_FALLBACK_ALL_COUNTRIES => t('All countries')
+	);
+
+	if (variable_get('language_fallback_country', false)){
+
+		$ret += country_get_list();
+	}
+
+	return $ret;
+}
\ No newline at end of file
diff -rupN language_fallback-7.x-1.x-dev//language_fallback.settings.inc language_fallback-7.x-2.x-dev//language_fallback.settings.inc
--- language_fallback-7.x-1.x-dev//language_fallback.settings.inc	1970-01-01 00:00:00.000000000 +0000
+++ language_fallback-7.x-2.x-dev//language_fallback.settings.inc	2013-08-15 11:57:55.000000000 +0000
@@ -0,0 +1,20 @@
+<?php
+
+function language_fallback_settings_form($form, &$form_state) {
+	
+	$form['language_fallback_entity'] = array(
+		'#type' => 'checkbox',
+		'#title' => t('Enable entity translation fallback.'),
+		'#description' => t('Entity translation module must be enabled for this feature to work.'),
+		'#default_value' => variable_get('language_fallback_entity', false)
+	);
+	
+	$form['language_fallback_country'] = array(
+		'#type' => 'checkbox',
+		'#title' => t('Enable country specific fallback.'),
+		'#description' => t('This feature allows you to create different fallbacks according to the user country. It is recommended to install Smart IP module to automatically map user IP to country. Otherwise users will have to use country selection block provided by this module.'),
+		'#default_value' => variable_get('language_fallback_country', false)
+	);
+	
+	return system_settings_form($form);
+}
\ No newline at end of file
