diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 697dce28a6c6afe3f7e76f3a20ebaf1a9e90c7a5..d32d94748989984e4118f8f7719fe0da6da1cb35 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -23,6 +23,13 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
             </intent-filter>
+        </activity>
+
+        <activity android:name="InputLanguageSelection"
+                android:label="@string/language_selection_title">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+            </intent-filter>
         </activity>    
     </application>
 </manifest>
diff --git a/res/drawable-hdpi/sym_keyboard_globe.png b/res/drawable-hdpi/sym_keyboard_globe.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa747642d9d91642bf56f769150e095fa372b542
Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_globe.png differ
diff --git a/res/values/keycodes.xml b/res/values/keycodes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e46e4bc369db768c3b7e994fe47942fa9125f673
--- /dev/null
+++ b/res/values/keycodes.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <!-- Keycode for F1 (function) key. This one switches between language switch & comma/.com -->
+    <integer name="key_f1">-102</integer>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 753d0dc9e213ab52e7bc76f090860b4510ad4787..3b3965e09f957ba96547582495fbda712eaa3c6a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -208,4 +208,7 @@
     <string name="popular_domain_3">".gov"</string>
     <!-- popular web domains for the locale - item 4, displayed in the popup -->
     <string name="popular_domain_4">".edu"</string>
+    
+    <!-- Title for input language selection screen -->
+    <string name="language_selection_title">Select input languages</string>
 </resources>
diff --git a/res/xml-de/kbd_qwerty.xml b/res/xml-de/kbd_qwerty.xml
index 56113e217c17abcfdfb8fd9c3985afc63f551bc0..2da609ca82a379472894adccb9c38ad627c383f0 100755
--- a/res/xml-de/kbd_qwerty.xml
+++ b/res/xml-de/kbd_qwerty.xml
@@ -100,7 +100,8 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="," android:keyWidth="10%p" />
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="10%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
                 android:iconPreview="@drawable/sym_keyboard_feedback_space"
                 android:keyWidth="40%p" android:isRepeatable="true"/>
@@ -116,9 +117,7 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="@string/popular_domain_0"
-                android:keyOutputText="@string/popular_domain_0"
-                android:popupKeyboard="@xml/popup_domains"
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
                 android:keyWidth="15%p"/>
         <Key android:keyLabel="/" android:keyWidth="15%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
@@ -136,11 +135,9 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="\@" android:keyWidth="15%p"/>
-        <Key android:keyLabel="@string/popular_domain_0"
-                android:keyOutputText="@string/popular_domain_0"
-                android:popupKeyboard="@xml/popup_domains"
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
                 android:keyWidth="15%p"/>
+        <Key android:keyLabel="\@" android:keyWidth="15%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" 
                 android:iconPreview="@drawable/sym_keyboard_feedback_space"
                 android:keyWidth="15%p" android:isRepeatable="true"/>
@@ -156,7 +153,8 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="," android:keyWidth="10%p"/>
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="10%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
                 android:iconPreview="@drawable/sym_keyboard_feedback_space"
                 android:keyWidth="40%p" android:isRepeatable="true"/>
diff --git a/res/xml-fr/kbd_qwerty.xml b/res/xml-fr/kbd_qwerty.xml
index d47042ea70dbf3dc6b1f43470efe811b737c4b19..7c1b24bada7bc839bcd4d3ebc6c63136ab9fe88e 100644
--- a/res/xml-fr/kbd_qwerty.xml
+++ b/res/xml-fr/kbd_qwerty.xml
@@ -102,7 +102,8 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters=""
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="," android:keyWidth="10%p" />
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="10%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" 
                 android:iconPreview="@drawable/sym_keyboard_feedback_space"
                 android:keyWidth="40%p" android:isRepeatable="true"/>
@@ -118,9 +119,7 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters=""
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="@string/popular_domain_0"
-                android:keyOutputText="@string/popular_domain_0"
-                android:popupKeyboard="@xml/popup_domains"
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
                 android:keyWidth="15%p"/>
         <Key android:keyLabel="/" android:keyWidth="15%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" 
@@ -138,11 +137,9 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters=""
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="\@" android:keyWidth="15%p"/>
-        <Key android:keyLabel="@string/popular_domain_0"
-                android:keyOutputText="@string/popular_domain_0"
-                android:popupKeyboard="@xml/popup_domains"
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
                 android:keyWidth="15%p"/>
+        <Key android:keyLabel="\@" android:keyWidth="15%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" 
                 android:iconPreview="@drawable/sym_keyboard_feedback_space"
                 android:keyWidth="15%p" android:isRepeatable="true"/>
@@ -158,7 +155,8 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters=""
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="," android:keyWidth="10%p"/>
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="10%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
                 android:iconPreview="@drawable/sym_keyboard_feedback_space"
                 android:keyWidth="40%p" android:isRepeatable="true"/>
diff --git a/res/xml-ru/kbd_qwerty.xml b/res/xml-ru/kbd_qwerty.xml
new file mode 100755
index 0000000000000000000000000000000000000000..c0afbd7b779a11457e8ee655fbb6dc8df805a3f5
--- /dev/null
+++ b/res/xml-ru/kbd_qwerty.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+    android:keyWidth="9.09%p"
+    android:horizontalGap="0px"
+    android:verticalGap="0px"
+    android:keyHeight="@dimen/key_height"
+    >
+
+    <Row>
+        <Key android:keyLabel="й"
+                android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="ц"/>
+        <Key android:keyLabel="у"/>
+        <Key android:keyLabel="к"/>
+        <Key android:keyLabel="е"/>
+        <Key android:keyLabel="н"/>
+        <Key android:keyLabel="г"/>
+        <Key android:keyLabel="ш"/>
+        <Key android:keyLabel="щ"/>
+        <Key android:keyLabel="з"/>
+        <Key android:keyLabel="Ñ…"
+                android:keyEdgeFlags="right"/>
+    </Row>
+    
+    <Row>
+        <Key android:keyLabel="Ñ„"
+                android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="Ñ‹"/>
+        <Key android:keyLabel="в"/>
+        <Key android:keyLabel="а"/>
+        <Key android:keyLabel="п"/>
+        <Key android:keyLabel="Ñ€"/>
+        <Key android:keyLabel="о"/>
+        <Key android:keyLabel="л"/>
+        <Key android:keyLabel="д"/>
+        <Key android:keyLabel="ж"/>
+        <Key android:keyLabel="э"
+                android:keyEdgeFlags="right"/>
+    </Row>
+    
+    <Row android:keyWidth="8.5%p">
+        <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift" 
+                android:keyWidth="11.75%p" android:isModifier="true"
+                android:iconPreview="@drawable/sym_keyboard_feedback_shift"
+                android:isSticky="true" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="я"/>
+        <Key android:keyLabel="ч"/>
+        <Key android:keyLabel="с"/>
+        <Key android:keyLabel="м"/>
+        <Key android:keyLabel="и"/>
+        <Key android:keyLabel="Ñ‚"/>
+        <Key android:keyLabel="ь"/>
+        <Key android:keyLabel="б"/>
+        <Key android:keyLabel="ÑŽ"/>
+        <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
+                android:keyWidth="11.75%p" android:keyEdgeFlags="right"
+                android:iconPreview="@drawable/sym_keyboard_feedback_delete"
+                android:isRepeatable="true"/>
+    </Row>
+
+    <Row android:keyboardMode="@+id/mode_normal" android:rowEdgeFlags="bottom">
+        <Key android:codes="-2" android:keyLabel="@string/label_symbol_key" 
+                android:popupKeyboard="@xml/kbd_popup_template"
+                android:popupCharacters="_"
+                android:keyWidth="20%p" android:keyEdgeFlags="left"/>
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="10%p"/>
+        <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
+                android:iconPreview="@drawable/sym_keyboard_feedback_space"
+                android:keyWidth="40%p" android:isRepeatable="true"/>
+        <Key android:codes="46" android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation" 
+                android:keyWidth="10%p"/>
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+                android:iconPreview="@drawable/sym_keyboard_feedback_return"
+                android:keyWidth="20%p" android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:keyboardMode="@+id/mode_url" android:rowEdgeFlags="bottom">
+        <Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
+                android:popupKeyboard="@xml/kbd_popup_template"
+                android:popupCharacters="_"
+                android:keyWidth="20%p" android:keyEdgeFlags="left"/>
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="15%p"/>
+        <Key android:keyLabel="/" android:keyWidth="15%p"/>
+        <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
+                android:iconPreview="@drawable/sym_keyboard_feedback_space"
+                android:keyWidth="15%p" android:isRepeatable="true"/>
+        <Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
+                android:keyWidth="15%p"/>
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+                android:iconPreview="@drawable/sym_keyboard_feedback_return"
+                android:keyWidth="20%p" android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:keyboardMode="@+id/mode_email" android:rowEdgeFlags="bottom">
+        <Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
+                android:popupKeyboard="@xml/kbd_popup_template"
+                android:popupCharacters="_"
+                android:keyWidth="20%p" android:keyEdgeFlags="left"/>
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="15%p"/>
+        <Key android:keyLabel="\@" android:keyWidth="15%p"/>
+        <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
+                android:iconPreview="@drawable/sym_keyboard_feedback_space"
+                android:keyWidth="15%p" android:isRepeatable="true"/>
+        <Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
+                android:keyWidth="15%p"/>
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+                android:iconPreview="@drawable/sym_keyboard_feedback_return"
+                android:keyWidth="20%p" android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:keyboardMode="@+id/mode_im" android:rowEdgeFlags="bottom">
+        <Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
+                android:popupKeyboard="@xml/kbd_popup_template"
+                android:popupCharacters="_"
+                android:keyWidth="20%p" android:keyEdgeFlags="left"/>
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="10%p"/>
+        <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
+                android:iconPreview="@drawable/sym_keyboard_feedback_space"
+                android:keyWidth="40%p" android:isRepeatable="true"/>
+        <Key android:codes="46" android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation" 
+                android:keyWidth="10%p"/>
+        <Key android:keyLabel=":-)" android:keyOutputText=":-) "
+                android:popupKeyboard="@xml/popup_smileys"
+                android:keyWidth="20%p" android:keyEdgeFlags="right"/>
+    </Row>
+</Keyboard>
+    
diff --git a/res/xml/kbd_qwerty.xml b/res/xml/kbd_qwerty.xml
index 0493b99328d394a873476caf10725addd226a5f8..d914f46d28d28bdf834fb27bc34d89f0ec07ffc2 100755
--- a/res/xml/kbd_qwerty.xml
+++ b/res/xml/kbd_qwerty.xml
@@ -114,7 +114,8 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="," android:keyWidth="10%p" />
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="10%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
                 android:iconPreview="@drawable/sym_keyboard_feedback_space"
                 android:keyWidth="40%p" android:isRepeatable="true"/>
@@ -130,10 +131,12 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="@string/popular_domain_0"
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="15%p"/>
+        <!--Key android:keyLabel="@string/popular_domain_0"
                 android:keyOutputText="@string/popular_domain_0"
                 android:popupKeyboard="@xml/popup_domains"
-                android:keyWidth="15%p"/>
+                android:keyWidth="15%p"/-->
         <Key android:keyLabel="/" android:keyWidth="15%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
                 android:iconPreview="@drawable/sym_keyboard_feedback_space"
@@ -150,11 +153,13 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="15%p"/>
         <Key android:keyLabel="\@" android:keyWidth="15%p"/>
-        <Key android:keyLabel="@string/popular_domain_0"
+        <!--Key android:keyLabel="@string/popular_domain_0"
                 android:keyOutputText="@string/popular_domain_0"
                 android:popupKeyboard="@xml/popup_domains"
-                android:keyWidth="15%p"/>
+                android:keyWidth="15%p"/-->
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
                 android:iconPreview="@drawable/sym_keyboard_feedback_space"
                 android:keyWidth="15%p" android:isRepeatable="true"/>
@@ -170,7 +175,8 @@
                 android:popupKeyboard="@xml/kbd_popup_template"
                 android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="," android:keyWidth="10%p"/>
+        <Key android:codes="@integer/key_f1" android:keyIcon="@drawable/sym_keyboard_globe"
+                android:keyWidth="10%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
                 android:iconPreview="@drawable/sym_keyboard_feedback_space"
                 android:keyWidth="40%p" android:isRepeatable="true"/>
@@ -181,4 +187,4 @@
                 android:keyWidth="20%p" android:keyEdgeFlags="right"/>
     </Row>
 </Keyboard>
-    
+
diff --git a/res/xml/kbd_symbols.xml b/res/xml/kbd_symbols.xml
index b1b75c620ebe25dbb8e5e5c79e02dfc9115c5f0a..5a30c7b8f5290b57b5680f0c46fdecc550821272 100755
--- a/res/xml/kbd_symbols.xml
+++ b/res/xml/kbd_symbols.xml
@@ -120,7 +120,7 @@
                 android:iconPreview="@drawable/sym_keyboard_feedback_delete"
                 android:isRepeatable="true"/>
     </Row>
-    
+
     <Row  android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_alpha_key"
                 android:popupKeyboard="@xml/kbd_popup_template"
diff --git a/res/xml/language_prefs.xml b/res/xml/language_prefs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b7a4c07db608684de7295b1cbb6618727a0a8736
--- /dev/null
+++ b/res/xml/language_prefs.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        android:title="@string/language_selection_title">
+</PreferenceScreen>
diff --git a/res/xml/prefs.xml b/res/xml/prefs.xml
index 2fc82aadbe3b74e5f98ac5dc8c2f7e47ed08a66e..d5075c53a9da862705d38cdfd833688200caa674 100644
--- a/res/xml/prefs.xml
+++ b/res/xml/prefs.xml
@@ -37,6 +37,14 @@
             android:defaultValue="true"
             />
 
+    <PreferenceScreen
+            android:title="@string/language_selection_title">
+        <intent
+                android:action="android.intent.action.MAIN"
+                android:targetPackage="com.android.inputmethod.latin"
+                android:targetClass="com.android.inputmethod.latin.InputLanguageSelection" />
+    </PreferenceScreen>
+
     <PreferenceCategory
             android:title="@string/prediction_category"
             android:key="prediction_settings">
diff --git a/src/com/android/inputmethod/latin/BinaryDictionary.java b/src/com/android/inputmethod/latin/BinaryDictionary.java
index 14c543514c28a1203fb3c8cd2d65dd9be1f099f0..36991845c66ef00bb5d58bf59acf426236d21d47 100644
--- a/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -125,8 +125,10 @@ public class BinaryDictionary extends Dictionary {
         return isValidWordNative(mNativeDict, chars, chars.length);
     }
 
+    @Override
     public synchronized void close() {
         if (mNativeDict != 0) {
+            System.err.println("Closing BinaryDictionary");
             closeNative(mNativeDict);
             mNativeDict = 0;
         }
diff --git a/src/com/android/inputmethod/latin/Dictionary.java b/src/com/android/inputmethod/latin/Dictionary.java
index fdf34264aa95bade0648754c7ffb0d5c77c6963b..6c1c856e77b2f4efbc1c6d0416e226ad6681bd12 100644
--- a/src/com/android/inputmethod/latin/Dictionary.java
+++ b/src/com/android/inputmethod/latin/Dictionary.java
@@ -86,4 +86,9 @@ abstract public class Dictionary {
         return true;
     }
 
+    /**
+     * Override to clean up any resources.
+     */
+    public void close() {
+    }
 }
diff --git a/src/com/android/inputmethod/latin/InputLanguageSelection.java b/src/com/android/inputmethod/latin/InputLanguageSelection.java
new file mode 100644
index 0000000000000000000000000000000000000000..5bd1391c32dd594482647c0f906ef6151756259a
--- /dev/null
+++ b/src/com/android/inputmethod/latin/InputLanguageSelection.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2008-2009 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceManager;
+import android.util.Log;
+
+public class InputLanguageSelection extends PreferenceActivity {
+
+    private String mSelectedLanguages;
+    private ArrayList<Loc> mAvailableLanguages = new ArrayList<Loc>();
+
+    private static class Loc implements Comparable {
+        static Collator sCollator = Collator.getInstance();
+
+        String label;
+        Locale locale;
+
+        public Loc(String label, Locale locale) {
+            this.label = label;
+            this.locale = locale;
+        }
+
+        @Override
+        public String toString() {
+            return this.label;
+        }
+
+        public int compareTo(Object o) {
+            return sCollator.compare(this.label, ((Loc) o).label);
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        addPreferencesFromResource(R.xml.language_prefs);
+        // Get the settings preferences
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
+        mSelectedLanguages = sp.getString(LatinIME.PREF_SELECTED_LANGUAGES, "");
+        String[] languageList = mSelectedLanguages.split(",");
+        mAvailableLanguages = getUniqueLocales();
+        PreferenceGroup parent = getPreferenceScreen();
+        for (int i = 0; i < mAvailableLanguages.size(); i++) {
+            CheckBoxPreference pref = new CheckBoxPreference(this);
+            Locale locale = mAvailableLanguages.get(i).locale;
+            pref.setTitle(locale.getDisplayName(locale));
+            boolean checked = isLocaleIn(locale, languageList);
+            pref.setChecked(checked);
+            parent.addPreference(pref);
+        }
+    }
+
+    private boolean isLocaleIn(Locale locale, String[] list) {
+        String lang = get5Code(locale);
+        for (int i = 0; i < list.length; i++) {
+            if (lang.equalsIgnoreCase(list[i])) return true;
+        }
+        // If it matches the current locale
+        Locale displayLocale = getResources().getConfiguration().locale;
+        if (lang.equalsIgnoreCase(get5Code(displayLocale))) {
+            return true;
+        }
+        return false;
+    }
+
+    private String get5Code(Locale locale) {
+        return locale.getLanguage() + "_" + locale.getCountry();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        // Save the selected languages
+        String checkedLanguages = "";
+        PreferenceGroup parent = getPreferenceScreen();
+        int count = parent.getPreferenceCount();
+        for (int i = 0; i < count; i++) {
+            CheckBoxPreference pref = (CheckBoxPreference) parent.getPreference(i);
+            if (pref.isChecked()) {
+                Locale locale = mAvailableLanguages.get(i).locale;
+                checkedLanguages += get5Code(locale) + ",";
+            }
+        }
+        if (checkedLanguages.length() < 1) checkedLanguages = null; // Save null
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
+        Editor editor = sp.edit();
+        editor.putString(LatinIME.PREF_SELECTED_LANGUAGES, checkedLanguages);
+        editor.commit();
+    }
+
+    ArrayList<Loc> getUniqueLocales() {
+        String[] locales = getAssets().getLocales();
+        Arrays.sort(locales);
+        ArrayList<Loc> uniqueLocales = new ArrayList<Loc>();
+
+        final int origSize = locales.length;
+        Loc[] preprocess = new Loc[origSize];
+        int finalSize = 0;
+        for (int i = 0 ; i < origSize; i++ ) {
+            String s = locales[i];
+            int len = s.length();
+            if (len == 5) {
+                String language = s.substring(0, 2);
+                String country = s.substring(3, 5);
+                Locale l = new Locale(language, country);
+
+                if (finalSize == 0) {
+                    preprocess[finalSize++] =
+                            new Loc(toTitleCase(l.getDisplayName(l)), l);
+                } else {
+                    // check previous entry:
+                    //  same lang and a country -> upgrade to full name and
+                    //    insert ours with full name
+                    //  diff lang -> insert ours with lang-only name
+                    if (preprocess[finalSize-1].locale.getLanguage().equals(
+                            language)) {
+                        preprocess[finalSize-1].label = toTitleCase(
+                                preprocess[finalSize-1].locale.getDisplayName());
+                        preprocess[finalSize++] =
+                                new Loc(toTitleCase(l.getDisplayName()), l);
+                    } else {
+                        String displayName;
+                        if (s.equals("zz_ZZ")) {
+                        } else {
+                            displayName = toTitleCase(l.getDisplayName(l));
+                            preprocess[finalSize++] = new Loc(displayName, l);
+                        }
+                    }
+                }
+            }
+        }
+        for (int i = 0; i < finalSize ; i++) {
+            uniqueLocales.add(preprocess[i]);
+        }
+        return uniqueLocales;
+    }
+
+    private static String toTitleCase(String s) {
+        if (s.length() == 0) {
+            return s;
+        }
+
+        return Character.toUpperCase(s.charAt(0)) + s.substring(1);
+    }
+
+}
diff --git a/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/src/com/android/inputmethod/latin/KeyboardSwitcher.java
index c7f90946dcbde974e2e3f3afef637c43246af872..03b008e3419a6dabe49479344191f6995525d9d0 100644
--- a/src/com/android/inputmethod/latin/KeyboardSwitcher.java
+++ b/src/com/android/inputmethod/latin/KeyboardSwitcher.java
@@ -17,8 +17,14 @@
 package com.android.inputmethod.latin;
 
 import java.util.HashMap;
+import java.util.Locale;
 import java.util.Map;
 
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.inputmethodservice.InputMethodService;
+
 public class KeyboardSwitcher {
 
     public static final int MODE_TEXT = 1;
@@ -42,7 +48,8 @@ public class KeyboardSwitcher {
     private static final int SYMBOLS_MODE_STATE_SYMBOL = 2;
 
     LatinKeyboardView mInputView;
-    LatinIME mContext;
+    Context mContext;
+    InputMethodService mInputMethodService;
     
     private KeyboardId mSymbolsId;
     private KeyboardId mSymbolsShiftedId;
@@ -58,12 +65,26 @@ public class KeyboardSwitcher {
     private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
 
     private int mLastDisplayWidth;
+    private Locale mInputLocale;
+    private boolean mEnableMultipleLanguages;
 
-    KeyboardSwitcher(LatinIME context) {
+    KeyboardSwitcher(Context context, InputMethodService ims) {
         mContext = context;
         mKeyboards = new HashMap<KeyboardId, LatinKeyboard>();
         mSymbolsId = new KeyboardId(R.xml.kbd_symbols);
         mSymbolsShiftedId = new KeyboardId(R.xml.kbd_symbols_shift);
+        mInputMethodService = ims;
+    }
+
+    /**
+     * Sets the input locale, when there are multiple locales for input.
+     * If no locale switching is required, then the locale should be set to null.
+     * @param locale the current input locale, or null for default locale with no locale 
+     * button.
+     */
+    void setInputLocale(Locale locale, boolean enableMultipleLanguages) {
+        mInputLocale = locale;
+        mEnableMultipleLanguages = enableMultipleLanguages;
     }
 
     void setInputView(LatinKeyboardView inputView) {
@@ -75,7 +96,7 @@ public class KeyboardSwitcher {
         // Configuration change is coming after the keyboard gets recreated. So don't rely on that.
         // If keyboards have already been made, check if we have a screen width change and 
         // create the keyboard layouts again at the correct orientation
-        int displayWidth = mContext.getMaxWidth();
+        int displayWidth = mInputMethodService.getMaxWidth();
         if (displayWidth == mLastDisplayWidth) return;
         mLastDisplayWidth = displayWidth;
         if (!forceCreate) mKeyboards.clear();
@@ -136,6 +157,11 @@ public class KeyboardSwitcher {
         }
 
         mCurrentId = id;
+        if (mEnableMultipleLanguages) {
+            keyboard.setLanguage(mInputLocale);
+        } else {
+            keyboard.setLanguage(null);
+        }
         mInputView.setKeyboard(keyboard);
         keyboard.setShifted(false);
         keyboard.setShiftLocked(keyboard.isShiftLocked());
@@ -145,6 +171,11 @@ public class KeyboardSwitcher {
 
     private LatinKeyboard getKeyboard(KeyboardId id) {
         if (!mKeyboards.containsKey(id)) {
+            Resources orig = mContext.getResources();
+            Configuration conf = orig.getConfiguration();
+            Locale saveLocale = conf.locale;
+            conf.locale = mInputLocale;
+            orig.updateConfiguration(conf, null);
             LatinKeyboard keyboard = new LatinKeyboard(
                 mContext, id.mXml, id.mMode);
             if (id.mMode == KEYBOARDMODE_NORMAL
@@ -158,6 +189,9 @@ public class KeyboardSwitcher {
                 keyboard.enableShiftLock();
             }
             mKeyboards.put(id, keyboard);
+
+            conf.locale = saveLocale;
+            orig.updateConfiguration(conf, null);
         }
         return mKeyboards.get(id);
     }
diff --git a/src/com/android/inputmethod/latin/LatinIME.java b/src/com/android/inputmethod/latin/LatinIME.java
index d72710e5bc8d38d456297fa213b3451353a1f3f2..1a08b2c0a58ff517e607677badcac6fd06f9a776 100644
--- a/src/com/android/inputmethod/latin/LatinIME.java
+++ b/src/com/android/inputmethod/latin/LatinIME.java
@@ -16,14 +16,24 @@
 
 package com.android.inputmethod.latin;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
 import android.app.AlertDialog;
+import android.backup.BackupManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.inputmethodservice.InputMethodService;
 import android.inputmethodservice.Keyboard;
 import android.inputmethodservice.KeyboardView;
@@ -49,16 +59,13 @@ import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * Input method implementation for Qwerty'ish keyboard.
  */
 public class LatinIME extends InputMethodService 
-        implements KeyboardView.OnKeyboardActionListener {
+        implements KeyboardView.OnKeyboardActionListener,
+                   SharedPreferences.OnSharedPreferenceChangeListener {
+
     static final boolean DEBUG = false;
     static final boolean TRACE = false;
     
@@ -68,6 +75,8 @@ public class LatinIME extends InputMethodService
     private static final String PREF_QUICK_FIXES = "quick_fixes";
     private static final String PREF_SHOW_SUGGESTIONS = "show_suggestions";
     private static final String PREF_AUTO_COMPLETE = "auto_complete";
+    public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
+    public static final String PREF_INPUT_LANGUAGE = "input_language";
 
     private static final int MSG_UPDATE_SUGGESTIONS = 0;
     private static final int MSG_START_TUTORIAL = 1;
@@ -105,7 +114,9 @@ public class LatinIME extends InputMethodService
     private UserDictionary mUserDictionary;
     private ContactsDictionary mContactsDictionary;
     private ExpandableDictionary mAutoDictionary;
-    
+
+    Resources mResources;
+
     private String mLocale;
 
     private StringBuilder mComposing = new StringBuilder();
@@ -144,7 +155,12 @@ public class LatinIME extends InputMethodService
 
     private String mWordSeparators;
     private String mSentenceSeparators;
-    
+    private int mCurrentInputLocale = 0;
+    private String mInputLanguage;
+    private String[] mSelectedLanguageArray;
+    private String mSelectedLanguagesList;
+    private boolean mRefreshKeyboardRequired;
+
     Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -173,32 +189,61 @@ public class LatinIME extends InputMethodService
     @Override public void onCreate() {
         super.onCreate();
         //setStatusIcon(R.drawable.ime_qwerty);
-        mKeyboardSwitcher = new KeyboardSwitcher(this);
-        final Configuration conf = getResources().getConfiguration();
-        initSuggest(conf.locale.toString());
+        mKeyboardSwitcher = new KeyboardSwitcher(this, this);
+        mResources = getResources();
+        final Configuration conf = mResources.getConfiguration();
+        mInputLanguage = getPersistedInputLanguage();
+        mSelectedLanguagesList = getSelectedInputLanguages();
+        boolean enableMultipleLanguages = mSelectedLanguagesList != null
+                && mSelectedLanguagesList.split(",").length > 1;
+        if (mInputLanguage == null) {
+            mInputLanguage = conf.locale.toString();
+        }
+        initSuggest(mInputLanguage);
+        mKeyboardSwitcher.setInputLocale(conf.locale, enableMultipleLanguages);
         mOrientation = conf.orientation;
 
-        mVibrateDuration = getResources().getInteger(R.integer.vibrate_duration_ms);
+        mVibrateDuration = mResources.getInteger(R.integer.vibrate_duration_ms);
 
         // register to receive ringer mode changes for silent mode
         IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
         registerReceiver(mReceiver, filter);
+        PreferenceManager.getDefaultSharedPreferences(this)
+                .registerOnSharedPreferenceChangeListener(this);
     }
-    
+
     private void initSuggest(String locale) {
         mLocale = locale;
+
+        Resources orig = getResources();
+        Configuration conf = orig.getConfiguration();
+        Locale saveLocale = conf.locale;
+        conf.locale = new Locale(locale);
+        orig.updateConfiguration(conf, orig.getDisplayMetrics());
+        if (mSuggest != null) {
+            mSuggest.close();
+        }
         mSuggest = new Suggest(this, R.raw.main);
         mSuggest.setCorrectionMode(mCorrectionMode);
         mUserDictionary = new UserDictionary(this);
-        mContactsDictionary = new ContactsDictionary(this);
-        mAutoDictionary = new AutoDictionary(this);
+        if (mContactsDictionary == null) {
+            mContactsDictionary = new ContactsDictionary(this);
+        }
+        // TODO: Save and restore the dictionary for the current input language.
+        if (mAutoDictionary == null) {
+            mAutoDictionary = new AutoDictionary(this);
+        }
         mSuggest.setUserDictionary(mUserDictionary);
         mSuggest.setContactsDictionary(mContactsDictionary);
         mSuggest.setAutoDictionary(mAutoDictionary);
-        mWordSeparators = getResources().getString(R.string.word_separators);
-        mSentenceSeparators = getResources().getString(R.string.sentence_separators);
+        
+        mWordSeparators = mResources.getString(R.string.word_separators);
+        mSentenceSeparators = mResources.getString(R.string.sentence_separators);
+
+        conf.locale = saveLocale;
+        orig.updateConfiguration(conf, orig.getDisplayMetrics());
     }
-    
+
     @Override public void onDestroy() {
         mUserDictionary.close();
         mContactsDictionary.close();
@@ -216,10 +261,7 @@ public class LatinIME extends InputMethodService
             commitTyped(getCurrentInputConnection());
             mOrientation = conf.orientation;
         }
-        if (mKeyboardSwitcher == null) {
-            mKeyboardSwitcher = new KeyboardSwitcher(this);
-        }
-        mKeyboardSwitcher.makeKeyboards(true);
+        reloadKeyboards();
         super.onConfigurationChanged(conf);
     }
 
@@ -253,6 +295,11 @@ public class LatinIME extends InputMethodService
             return;
         }
 
+        if (mRefreshKeyboardRequired) {
+            mRefreshKeyboardRequired = false;
+            toggleLanguage(true);
+        }
+
         mKeyboardSwitcher.makeKeyboards(false);
 
         TextEntryState.newSession(this);
@@ -499,6 +546,15 @@ public class LatinIME extends InputMethodService
         return super.onKeyUp(keyCode, event);
     }
 
+    private void reloadKeyboards() {
+        if (mKeyboardSwitcher == null) {
+            mKeyboardSwitcher = new KeyboardSwitcher(this, this);
+        }
+        mKeyboardSwitcher.setInputLocale(new Locale(mInputLanguage),
+                getSelectedInputLanguages() != null);
+        mKeyboardSwitcher.makeKeyboards(true);
+    }
+
     private void commitTyped(InputConnection inputConnection) {
         if (mPredicting) {
             mPredicting = false;
@@ -601,6 +657,9 @@ public class LatinIME extends InputMethodService
             case LatinKeyboardView.KEYCODE_OPTIONS:
                 showOptionsMenu();
                 break;
+            case LatinKeyboardView.KEYCODE_F1:
+                toggleLanguage(false);
+                break;
             case LatinKeyboardView.KEYCODE_SHIFT_LONGPRESS:
                 if (mCapsLock) {
                     handleShift();
@@ -674,7 +733,6 @@ public class LatinIME extends InputMethodService
 
     private void handleShift() {
         mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
-        Keyboard currentKeyboard = mInputView.getKeyboard();
         if (mKeyboardSwitcher.isAlphabetMode()) {
             // Alphabet keyboard
             checkToggleCapsLock();
@@ -966,9 +1024,32 @@ public class LatinIME extends InputMethodService
             }
         }
     }
-    
+
+    private void toggleLanguage(boolean reset) {
+        final String [] languages = mSelectedLanguageArray;
+        if (reset) mCurrentInputLocale = -1;
+        mCurrentInputLocale = (mCurrentInputLocale + 1)
+                % (languages != null ? languages.length : 1);
+        mInputLanguage = languages != null ? languages[mCurrentInputLocale] :
+                getResources().getConfiguration().locale.getLanguage();
+        int currentKeyboardMode = mKeyboardSwitcher.getKeyboardMode();
+        reloadKeyboards();
+        mKeyboardSwitcher.makeKeyboards(true);
+        mKeyboardSwitcher.setKeyboardMode(currentKeyboardMode, 0);
+        initSuggest(mInputLanguage);
+        persistInputLanguage(mInputLanguage);
+        updateShiftKeyState(getCurrentInputEditorInfo());
+    }
+
+    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+            String key) {
+        if (PREF_SELECTED_LANGUAGES.equals(key)) {
+            updateSelectedLanguages(sharedPreferences.getString(key, null));
+            mRefreshKeyboardRequired = true;
+        }
+    }
+
     public void swipeLeft() {
-        //handleBackspace();
     }
 
     public void swipeDown() {
@@ -1089,11 +1170,38 @@ public class LatinIME extends InputMethodService
         if (AutoText.getSize(mInputView) < 1) mQuickFixes = true;
         mShowSuggestions = sp.getBoolean(PREF_SHOW_SUGGESTIONS, true) & mQuickFixes;
         boolean autoComplete = sp.getBoolean(PREF_AUTO_COMPLETE,
-                getResources().getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions;
+                mResources.getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions;
         mAutoCorrectOn = mSuggest != null && (autoComplete || mQuickFixes);
         mCorrectionMode = autoComplete
                 ? Suggest.CORRECTION_FULL
                 : (mQuickFixes ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE);
+        String languageList = sp.getString(PREF_SELECTED_LANGUAGES, null);
+        updateSelectedLanguages(languageList);
+    }
+
+    private void updateSelectedLanguages(String languageList) {
+        if (languageList != null && languageList.length() > 1) {
+            mSelectedLanguageArray = languageList.split(",");
+        } else {
+            mSelectedLanguageArray = null;
+        }
+    }
+
+    private String getPersistedInputLanguage() {
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
+        return sp.getString(PREF_INPUT_LANGUAGE, null);
+    }
+
+    private void persistInputLanguage(String inputLanguage) {
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
+        Editor editor = sp.edit();
+        editor.putString(PREF_INPUT_LANGUAGE, inputLanguage);
+        editor.commit();
+    }
+
+    private String getSelectedInputLanguages() {
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
+        return sp.getString(PREF_SELECTED_LANGUAGES, null);
     }
 
     private void showOptionsMenu() {
@@ -1120,7 +1228,7 @@ public class LatinIME extends InputMethodService
                 }
             }
         });
-        builder.setTitle(getResources().getString(R.string.english_ime_name));
+        builder.setTitle(mResources.getString(R.string.english_ime_name));
         mOptionsDialog = builder.create();
         Window window = mOptionsDialog.getWindow();
         WindowManager.LayoutParams lp = window.getAttributes();
@@ -1139,7 +1247,7 @@ public class LatinIME extends InputMethodService
 
         updateShiftKeyState(getCurrentInputEditorInfo());
     }
-    
+
     @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
         super.dump(fd, fout, args);
         
diff --git a/src/com/android/inputmethod/latin/LatinKeyboard.java b/src/com/android/inputmethod/latin/LatinKeyboard.java
index e68e01dedf32acac19fbcd743013357506a82f14..05913122f02b3b6951fed0decbbccdd788457d3b 100644
--- a/src/com/android/inputmethod/latin/LatinKeyboard.java
+++ b/src/com/android/inputmethod/latin/LatinKeyboard.java
@@ -16,9 +16,17 @@
 
 package com.android.inputmethod.latin;
 
+import java.util.Locale;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.Paint.Align;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.inputmethodservice.Keyboard;
 import android.view.inputmethod.EditorInfo;
@@ -29,8 +37,14 @@ public class LatinKeyboard extends Keyboard {
     private Drawable mShiftLockPreviewIcon;
     private Drawable mOldShiftIcon;
     private Drawable mOldShiftPreviewIcon;
+    private Drawable mSpaceIcon;
     private Key mShiftKey;
     private Key mEnterKey;
+    private Key mF1Key;
+    private Key mSpaceKey;
+    private Locale mLocale;
+    private Resources mRes;
+    private int mMode;
 
     private int mExtensionResId; 
     
@@ -48,12 +62,15 @@ public class LatinKeyboard extends Keyboard {
 
     public LatinKeyboard(Context context, int xmlLayoutResId, int mode) {
         super(context, xmlLayoutResId, mode);
-        Resources res = context.getResources();
+        final Resources res = context.getResources();
+        mMode = mode;
+        mRes = res;
         mShiftLockIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked);
         mShiftLockPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_shift_locked);
         mShiftLockPreviewIcon.setBounds(0, 0, 
                 mShiftLockPreviewIcon.getIntrinsicWidth(),
                 mShiftLockPreviewIcon.getIntrinsicHeight());
+        mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space);
         sSpacebarVerticalCorrection = res.getDimensionPixelOffset(
                 R.dimen.spacebar_vertical_correction);
     }
@@ -67,12 +84,20 @@ public class LatinKeyboard extends Keyboard {
     protected Key createKeyFromXml(Resources res, Row parent, int x, int y, 
             XmlResourceParser parser) {
         Key key = new LatinKey(res, parent, x, y, parser);
-        if (key.codes[0] == 10) {
+        switch (key.codes[0]) {
+        case 10:
             mEnterKey = key;
+            break;
+        case LatinKeyboardView.KEYCODE_F1:
+            mF1Key = key;
+            break;
+        case 32:
+            mSpaceKey = key;
+            break;
         }
         return key;
     }
-    
+
     void setImeOptions(Resources res, int mode, int options) {
         if (mEnterKey != null) {
             // Reset some of the rarely used attributes.
@@ -183,7 +208,7 @@ public class LatinKeyboard extends Keyboard {
         }
         return shiftChanged;
     }
-    
+
     @Override
     public boolean isShifted() {
         if (mShiftKey != null) {
@@ -201,6 +226,62 @@ public class LatinKeyboard extends Keyboard {
         return mExtensionResId;
     }
 
+    private void setF1Key() {
+        if (mF1Key == null) return; // No function key on this keyboard
+        if (mLocale != null) {
+            // Create the graphic for spacebar
+            mF1Key.label = null;
+            mF1Key.icon = mRes.getDrawable(R.drawable.sym_keyboard_globe);
+            Bitmap buffer = Bitmap.createBitmap(mSpaceKey.width, mSpaceIcon.getIntrinsicHeight(),
+                    Bitmap.Config.ARGB_8888);
+            Canvas canvas = new Canvas(buffer);
+            canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
+            Paint paint = new Paint();
+            paint.setAntiAlias(true);
+            paint.setTextSize(22);
+            paint.setTextAlign(Align.CENTER);
+            // Draw a drop shadow for the text
+            paint.setShadowLayer(1f, 0, 0, 0xFF000000);
+            paint.setColor(0x80C0C0C0);
+            canvas.drawText(mLocale.getDisplayLanguage(mLocale),
+                    buffer.getWidth() / 2, - paint.ascent() + 2, paint);
+            int x = (buffer.getWidth() - mSpaceIcon.getIntrinsicWidth()) / 2;
+            int y = buffer.getHeight() - mSpaceIcon.getIntrinsicHeight();
+            mSpaceIcon.setBounds(x, y, 
+                    x + mSpaceIcon.getIntrinsicWidth(), y + mSpaceIcon.getIntrinsicHeight());
+            mSpaceIcon.draw(canvas);
+            mSpaceKey.icon = new BitmapDrawable(mRes, buffer);            
+        } else {
+            mSpaceKey.icon = mRes.getDrawable(R.drawable.sym_keyboard_space);
+            switch (mMode) {
+            case KeyboardSwitcher.KEYBOARDMODE_NORMAL:
+            case KeyboardSwitcher.KEYBOARDMODE_IM:
+                mF1Key.label = ",";
+                mF1Key.codes = new int[] { ',' };
+                mF1Key.icon = null;
+                mF1Key.iconPreview = null;
+                break;
+            case KeyboardSwitcher.KEYBOARDMODE_EMAIL:
+            case KeyboardSwitcher.KEYBOARDMODE_URL:
+                mF1Key.label = mRes.getString(R.string.popular_domain_0);
+                mF1Key.codes = new int[] { '.' };
+                mF1Key.text = mF1Key.label;
+                mF1Key.icon = null;
+                mF1Key.iconPreview = null;
+                mF1Key.popupResId = R.xml.popup_domains;
+                break;
+            }
+        }
+    }
+
+    public void setLanguage(Locale locale) {
+        if (mLocale != null && mLocale.equals(locale)) return;
+        mLocale = locale;
+        setF1Key();
+        if (mF1Key != null) {
+        }
+    }
+
     static class LatinKey extends Keyboard.Key {
         
         private boolean mShiftLockEnabled;
diff --git a/src/com/android/inputmethod/latin/LatinKeyboardView.java b/src/com/android/inputmethod/latin/LatinKeyboardView.java
index ecbd1adfb5166816eb325666dc5bef2c0da6dad9..163d824e004f288454bada07e54533dffc2e6ec4 100644
--- a/src/com/android/inputmethod/latin/LatinKeyboardView.java
+++ b/src/com/android/inputmethod/latin/LatinKeyboardView.java
@@ -35,6 +35,7 @@ public class LatinKeyboardView extends KeyboardView {
 
     static final int KEYCODE_OPTIONS = -100;
     static final int KEYCODE_SHIFT_LONGPRESS = -101;
+    static final int KEYCODE_F1 = -102;
 
     private Keyboard mPhoneKeyboard;
 
diff --git a/src/com/android/inputmethod/latin/Suggest.java b/src/com/android/inputmethod/latin/Suggest.java
index c025566b73416ffe0926b83c0267b02ada56cae6..cc9a39cb77ec91a215915da0353dcc75665baacc 100755
--- a/src/com/android/inputmethod/latin/Suggest.java
+++ b/src/com/android/inputmethod/latin/Suggest.java
@@ -336,4 +336,10 @@ public class Suggest implements Dictionary.WordCallback {
         }
         mSuggestions.clear();
     }
+
+    public void close() {
+        if (mMainDict != null) {
+            mMainDict.close();
+        }
+    }
 }