Merge "Implement IMM.switchToNextInputMethod() for ICS"
diff --git a/dictionaries/en_GB_wordlist.combined.gz b/dictionaries/en_GB_wordlist.combined.gz
index b3e5cfc..93c5f3d 100644
--- a/dictionaries/en_GB_wordlist.combined.gz
+++ b/dictionaries/en_GB_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/en_US_wordlist.combined.gz b/dictionaries/en_US_wordlist.combined.gz
index 67328d8..c2421dc 100644
--- a/dictionaries/en_US_wordlist.combined.gz
+++ b/dictionaries/en_US_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/en_wordlist.combined.gz b/dictionaries/en_wordlist.combined.gz
index 7fc6cff..3732993 100644
--- a/dictionaries/en_wordlist.combined.gz
+++ b/dictionaries/en_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/fr_wordlist.combined.gz b/dictionaries/fr_wordlist.combined.gz
index c7c6977..7de4625 100644
--- a/dictionaries/fr_wordlist.combined.gz
+++ b/dictionaries/fr_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/ru_wordlist.combined.gz b/dictionaries/ru_wordlist.combined.gz
index 4f92805..253c515 100644
--- a/dictionaries/ru_wordlist.combined.gz
+++ b/dictionaries/ru_wordlist.combined.gz
Binary files differ
diff --git a/java/res/color/setup_step_action_background.xml b/java/res/color/setup_step_action_background.xml
new file mode 100644
index 0000000..79120b4
--- /dev/null
+++ b/java/res/color/setup_step_action_background.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_focused="true"
+        android:color="@color/setup_text_action" />
+    <item
+        android:state_pressed="true"
+        android:color="@color/setup_text_action" />
+    <item
+        android:color="@color/setup_step_background" />
+</selector>
diff --git a/java/res/color/setup_step_action_color.xml b/java/res/color/setup_step_action_color.xml
new file mode 100644
index 0000000..c53e026
--- /dev/null
+++ b/java/res/color/setup_step_action_color.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_focused="true"
+        android:color="@color/setup_step_background" />
+    <item
+        android:state_pressed="true"
+        android:color="@color/setup_step_background" />
+    <item
+        android:color="@color/setup_text_action" />
+</selector>
diff --git a/java/res/drawable-hdpi/unbundled_check_01.png b/java/res/drawable-hdpi/unbundled_check_01.png
new file mode 100644
index 0000000..42cce2f
--- /dev/null
+++ b/java/res/drawable-hdpi/unbundled_check_01.png
Binary files differ
diff --git a/java/res/drawable-hdpi/unbundled_check_02.png b/java/res/drawable-hdpi/unbundled_check_02.png
new file mode 100644
index 0000000..dcd120e
--- /dev/null
+++ b/java/res/drawable-hdpi/unbundled_check_02.png
Binary files differ
diff --git a/java/res/drawable-hdpi/unbundled_earth_01.png b/java/res/drawable-hdpi/unbundled_earth_01.png
new file mode 100644
index 0000000..4a0f087
--- /dev/null
+++ b/java/res/drawable-hdpi/unbundled_earth_01.png
Binary files differ
diff --git a/java/res/drawable-hdpi/unbundled_earth_02.png b/java/res/drawable-hdpi/unbundled_earth_02.png
new file mode 100644
index 0000000..f4bd421
--- /dev/null
+++ b/java/res/drawable-hdpi/unbundled_earth_02.png
Binary files differ
diff --git a/java/res/drawable-hdpi/unbundled_key_01.png b/java/res/drawable-hdpi/unbundled_key_01.png
new file mode 100644
index 0000000..87c9e2c
--- /dev/null
+++ b/java/res/drawable-hdpi/unbundled_key_01.png
Binary files differ
diff --git a/java/res/drawable-hdpi/unbundled_key_02.png b/java/res/drawable-hdpi/unbundled_key_02.png
new file mode 100644
index 0000000..0747384
--- /dev/null
+++ b/java/res/drawable-hdpi/unbundled_key_02.png
Binary files differ
diff --git a/java/res/drawable-hdpi/unbundled_select_01.png b/java/res/drawable-hdpi/unbundled_select_01.png
new file mode 100644
index 0000000..bb3de2f
--- /dev/null
+++ b/java/res/drawable-hdpi/unbundled_select_01.png
Binary files differ
diff --git a/java/res/drawable-hdpi/unbundled_select_02.png b/java/res/drawable-hdpi/unbundled_select_02.png
new file mode 100644
index 0000000..e56fdab
--- /dev/null
+++ b/java/res/drawable-hdpi/unbundled_select_02.png
Binary files differ
diff --git a/java/res/drawable-mdpi/unbundled_check_01.png b/java/res/drawable-mdpi/unbundled_check_01.png
new file mode 100644
index 0000000..d0d02a3
--- /dev/null
+++ b/java/res/drawable-mdpi/unbundled_check_01.png
Binary files differ
diff --git a/java/res/drawable-mdpi/unbundled_check_02.png b/java/res/drawable-mdpi/unbundled_check_02.png
new file mode 100644
index 0000000..d34fa22
--- /dev/null
+++ b/java/res/drawable-mdpi/unbundled_check_02.png
Binary files differ
diff --git a/java/res/drawable-mdpi/unbundled_earth_01.png b/java/res/drawable-mdpi/unbundled_earth_01.png
new file mode 100644
index 0000000..ba60181
--- /dev/null
+++ b/java/res/drawable-mdpi/unbundled_earth_01.png
Binary files differ
diff --git a/java/res/drawable-mdpi/unbundled_earth_02.png b/java/res/drawable-mdpi/unbundled_earth_02.png
new file mode 100644
index 0000000..9c52638
--- /dev/null
+++ b/java/res/drawable-mdpi/unbundled_earth_02.png
Binary files differ
diff --git a/java/res/drawable-mdpi/unbundled_key_01.png b/java/res/drawable-mdpi/unbundled_key_01.png
new file mode 100644
index 0000000..8cd72db
--- /dev/null
+++ b/java/res/drawable-mdpi/unbundled_key_01.png
Binary files differ
diff --git a/java/res/drawable-mdpi/unbundled_key_02.png b/java/res/drawable-mdpi/unbundled_key_02.png
new file mode 100644
index 0000000..4ef6e0c
--- /dev/null
+++ b/java/res/drawable-mdpi/unbundled_key_02.png
Binary files differ
diff --git a/java/res/drawable-mdpi/unbundled_select_01.png b/java/res/drawable-mdpi/unbundled_select_01.png
new file mode 100644
index 0000000..9ab008a
--- /dev/null
+++ b/java/res/drawable-mdpi/unbundled_select_01.png
Binary files differ
diff --git a/java/res/drawable-mdpi/unbundled_select_02.png b/java/res/drawable-mdpi/unbundled_select_02.png
new file mode 100644
index 0000000..8af807b
--- /dev/null
+++ b/java/res/drawable-mdpi/unbundled_select_02.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/unbundled_check_01.png b/java/res/drawable-xhdpi/unbundled_check_01.png
new file mode 100644
index 0000000..1300a7f
--- /dev/null
+++ b/java/res/drawable-xhdpi/unbundled_check_01.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/unbundled_check_02.png b/java/res/drawable-xhdpi/unbundled_check_02.png
new file mode 100644
index 0000000..7151886
--- /dev/null
+++ b/java/res/drawable-xhdpi/unbundled_check_02.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/unbundled_earth_01.png b/java/res/drawable-xhdpi/unbundled_earth_01.png
new file mode 100644
index 0000000..24b6634
--- /dev/null
+++ b/java/res/drawable-xhdpi/unbundled_earth_01.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/unbundled_earth_02.png b/java/res/drawable-xhdpi/unbundled_earth_02.png
new file mode 100644
index 0000000..59aa031
--- /dev/null
+++ b/java/res/drawable-xhdpi/unbundled_earth_02.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/unbundled_key_01.png b/java/res/drawable-xhdpi/unbundled_key_01.png
new file mode 100644
index 0000000..c8b117b
--- /dev/null
+++ b/java/res/drawable-xhdpi/unbundled_key_01.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/unbundled_key_02.png b/java/res/drawable-xhdpi/unbundled_key_02.png
new file mode 100644
index 0000000..dc2da56
--- /dev/null
+++ b/java/res/drawable-xhdpi/unbundled_key_02.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/unbundled_select_01.png b/java/res/drawable-xhdpi/unbundled_select_01.png
new file mode 100644
index 0000000..baf1e55
--- /dev/null
+++ b/java/res/drawable-xhdpi/unbundled_select_01.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/unbundled_select_02.png b/java/res/drawable-xhdpi/unbundled_select_02.png
new file mode 100644
index 0000000..ad1058e
--- /dev/null
+++ b/java/res/drawable-xhdpi/unbundled_select_02.png
Binary files differ
diff --git a/java/res/drawable/ic_setup_finish.xml b/java/res/drawable/ic_setup_finish.xml
new file mode 100644
index 0000000..8ac8a86
--- /dev/null
+++ b/java/res/drawable/ic_setup_finish.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_focused="true"
+        android:drawable="@drawable/unbundled_check_01" />
+    <item
+        android:state_pressed="true"
+        android:drawable="@drawable/unbundled_check_01" />
+    <item
+        android:drawable="@drawable/unbundled_check_02" />
+</selector>
diff --git a/java/res/drawable/ic_setup_step1.xml b/java/res/drawable/ic_setup_step1.xml
new file mode 100644
index 0000000..e26afb3
--- /dev/null
+++ b/java/res/drawable/ic_setup_step1.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_focused="true"
+        android:drawable="@drawable/unbundled_key_01" />
+    <item
+        android:state_pressed="true"
+        android:drawable="@drawable/unbundled_key_01" />
+    <item
+        android:drawable="@drawable/unbundled_key_02" />
+</selector>
diff --git a/java/res/drawable/ic_setup_step2.xml b/java/res/drawable/ic_setup_step2.xml
new file mode 100644
index 0000000..46db293
--- /dev/null
+++ b/java/res/drawable/ic_setup_step2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_focused="true"
+        android:drawable="@drawable/unbundled_select_01" />
+    <item
+        android:state_pressed="true"
+        android:drawable="@drawable/unbundled_select_01" />
+    <item
+        android:drawable="@drawable/unbundled_select_02" />
+</selector>
diff --git a/java/res/drawable/ic_setup_step3.xml b/java/res/drawable/ic_setup_step3.xml
new file mode 100644
index 0000000..4ff9fd9
--- /dev/null
+++ b/java/res/drawable/ic_setup_step3.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_focused="true"
+        android:drawable="@drawable/unbundled_earth_01" />
+    <item
+        android:state_pressed="true"
+        android:drawable="@drawable/unbundled_earth_01" />
+    <item
+        android:drawable="@drawable/unbundled_earth_02" />
+</selector>
diff --git a/java/res/drawable/setup_step_action_background.xml b/java/res/drawable/setup_step_action_background.xml
new file mode 100644
index 0000000..25738e3
--- /dev/null
+++ b/java/res/drawable/setup_step_action_background.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_focused="true"
+        android:drawable="@color/setup_text_action" />
+    <item
+        android:state_pressed="true"
+        android:drawable="@color/setup_text_action" />
+    <item
+        android:drawable="@color/setup_step_background" />
+</selector>
diff --git a/java/res/layout-land/setup_steps_screen.xml b/java/res/layout-land/setup_steps_screen.xml
new file mode 100644
index 0000000..0b4a096
--- /dev/null
+++ b/java/res/layout-land/setup_steps_screen.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal"
+    android:baselineAligned="false">
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="@integer/setup_title_weight_in_screen"
+        android:orientation="vertical">
+        <include layout="@layout/setup_steps_title" />
+    </LinearLayout>
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="@integer/setup_body_weight_in_screen"
+        android:orientation="vertical">
+        <include layout="@layout/setup_steps_cards" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/java/res/layout-land/setup_welcome_screen.xml b/java/res/layout-land/setup_welcome_screen.xml
new file mode 100644
index 0000000..8b162e2
--- /dev/null
+++ b/java/res/layout-land/setup_welcome_screen.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal"
+    android:baselineAligned="false">
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="@integer/setup_title_weight_in_screen"
+        android:orientation="vertical">
+        <include layout="@layout/setup_welcome_title" />
+    </LinearLayout>
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="@integer/setup_body_weight_in_screen"
+        android:orientation="vertical">
+        <include layout="@layout/setup_welcome_video" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/java/res/layout/setup_start_indicator_label.xml b/java/res/layout/setup_start_indicator_label.xml
new file mode 100644
index 0000000..33854bb
--- /dev/null
+++ b/java/res/layout/setup_start_indicator_label.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <view class="com.android.inputmethod.latin.setup.SetupStartIndicatorView$LabelView"
+        android:id="@+id/setup_start_label"
+        android:text="@string/setup_start_action"
+        android:gravity="end|center_vertical"
+        android:layout_width="0dp"
+        android:layout_weight="1.0"
+        style="@style/setupStepActionLabelStyleCommon" />
+    <view class="com.android.inputmethod.latin.setup.SetupStartIndicatorView$IndicatorView"
+        android:id="@+id/setup_start_indicator"
+        style="@style/setupStepStartIndicatorStyle" />
+</merge>
diff --git a/java/res/layout/setup_step.xml b/java/res/layout/setup_step.xml
index 26d7fe7..c6462e9 100644
--- a/java/res/layout/setup_step.xml
+++ b/java/res/layout/setup_step.xml
@@ -25,34 +25,14 @@
     <TextView
         android:id="@+id/setup_step_title"
         style="@style/setupStepTitleStyle"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
         android:paddingTop="16dp"
-        android:paddingBottom="16dp"
-        android:paddingLeft="24dp"
-        android:paddingRight="24dp" />
+        android:paddingBottom="16dp" />
     <TextView
         android:id="@+id/setup_step_instruction"
         style="@style/setupStepInstructionStyle"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingBottom="16dp"
-        android:paddingLeft="24dp"
-        android:paddingRight="24dp" />
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="2dp" />
+        android:paddingBottom="16dp" />
     <TextView
         android:id="@+id/setup_step_action_label"
         style="@style/setupStepActionLabelStyle"
-        android:gravity="center_vertical"
-        android:drawablePadding="12dp"
-        android:layout_width="match_parent"
-        android:layout_height="48dp"
-        android:clickable="true"
-        android:focusable="true"
-        android:paddingLeft="12dp"
-        android:paddingStart="12dp"
-        android:paddingRight="24dp"
-        android:paddingEnd="24dp" />
+        android:layout_marginTop="2dp" />
 </LinearLayout>
diff --git a/java/res/layout/setup_steps_cards.xml b/java/res/layout/setup_steps_cards.xml
new file mode 100644
index 0000000..17207d3
--- /dev/null
+++ b/java/res/layout/setup_steps_cards.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <LinearLayout
+        android:id="@+id/setup_step_bullets"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:orientation="horizontal">
+        <TextView
+            android:id="@+id/setup_step1_bullet"
+            style="@style/setupStepBulletStyle"
+            android:text="@string/setup_step1_bullet" />
+        <TextView
+            android:id="@+id/setup_step2_bullet"
+            style="@style/setupStepBulletStyle"
+            android:text="@string/setup_step2_bullet" />
+        <TextView
+            android:id="@+id/setup_step3_bullet"
+            style="@style/setupStepBulletStyle"
+            android:text="@string/setup_step3_bullet" />
+    </LinearLayout>
+    <com.android.inputmethod.latin.setup.SetupStepIndicatorView
+        android:id="@+id/setup_step_indicator"
+        android:layout_width="match_parent"
+        android:layout_height="24dp" />
+    <FrameLayout
+        android:id="@+id/setup_steps_pane"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <include
+            android:id="@+id/setup_step1"
+            layout="@layout/setup_step" />
+        <include
+            android:id="@+id/setup_step2"
+            layout="@layout/setup_step" />
+        <include
+            android:id="@+id/setup_step3"
+            layout="@layout/setup_step" />
+    </FrameLayout>
+    <TextView
+        android:id="@+id/setup_finish"
+        android:text="@string/setup_finish_action"
+        style="@style/setupStepActionLabelStyle"
+        android:layout_marginTop="2dp" />
+</merge>
diff --git a/java/res/layout/setup_steps_screen.xml b/java/res/layout/setup_steps_screen.xml
new file mode 100644
index 0000000..1159c0a
--- /dev/null
+++ b/java/res/layout/setup_steps_screen.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <include layout="@layout/setup_steps_title" />
+    <include layout="@layout/setup_steps_cards" />
+</LinearLayout>
diff --git a/java/res/layout/setup_steps_title.xml b/java/res/layout/setup_steps_title.xml
new file mode 100644
index 0000000..e3694bf
--- /dev/null
+++ b/java/res/layout/setup_steps_title.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <TextView
+        android:id="@+id/setup_title"
+        style="@style/setupTitleStyle"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true" />
+</merge>
diff --git a/java/res/layout/setup_welcome_screen.xml b/java/res/layout/setup_welcome_screen.xml
new file mode 100644
index 0000000..44e98e2
--- /dev/null
+++ b/java/res/layout/setup_welcome_screen.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <include layout="@layout/setup_welcome_title" />
+    <include layout="@layout/setup_welcome_video" />
+</LinearLayout>
diff --git a/java/res/layout/setup_welcome_title.xml b/java/res/layout/setup_welcome_title.xml
new file mode 100644
index 0000000..6e6d781
--- /dev/null
+++ b/java/res/layout/setup_welcome_title.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <TextView
+        android:id="@+id/setup_welcome_title"
+        style="@style/setupTitleStyle"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true" />
+    <TextView
+        android:id="@+id/setup_welcome_description"
+        android:text="@string/setup_welcome_additional_description"
+        android:layout_marginTop="12dp"
+        style="@style/setupWelcomeDescritpionStyle" />
+</merge>
diff --git a/java/res/layout/setup_welcome_video.xml b/java/res/layout/setup_welcome_video.xml
new file mode 100644
index 0000000..3aa4f3c
--- /dev/null
+++ b/java/res/layout/setup_welcome_video.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <View
+            android:layout_weight="@integer/setup_welcome_video_left_padding_weight_in_screen"
+            android:layout_width="0dp"
+            android:layout_height="0dp" />
+        <VideoView
+            android:id="@+id/setup_welcome_video"
+            android:layout_weight="@integer/setup_welcome_video_weight_in_screen"
+            android:layout_marginTop="24dp"
+            android:layout_marginBottom="24dp"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content" />
+        <View
+            android:layout_weight="@integer/setup_welcome_video_right_padding_weight_in_screen"
+            android:layout_width="0dp"
+            android:layout_height="0dp" />
+    </LinearLayout>
+    <com.android.inputmethod.latin.setup.SetupStartIndicatorView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+</merge>
diff --git a/java/res/layout/setup_wizard.xml b/java/res/layout/setup_wizard.xml
index acbbe30..e766e4c 100644
--- a/java/res/layout/setup_wizard.xml
+++ b/java/res/layout/setup_wizard.xml
@@ -18,61 +18,18 @@
 */
 -->
 
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:fillViewport="true">
-    <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:background="@color/setup_background"
-        android:paddingLeft="@dimen/setup_horizontal_padding"
-        android:paddingRight="@dimen/setup_horizontal_padding"
-        android:paddingTop="16dp"
-        android:paddingBottom="16dp">
-        <TextView
-            android:id="@+id/setup_title"
-            style="@style/setupTitleStyle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentStart="true"
-            android:layout_alignParentTop="true" />
-        <LinearLayout
-            android:id="@+id/setup_step_bullets"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_below="@id/setup_title"
-            android:paddingTop="16dp"
-            android:orientation="horizontal">
-            <TextView
-                style="@style/setupStepBulletStyle"
-                android:text="@string/setup_step1_bullet" />
-            <TextView
-                style="@style/setupStepBulletStyle"
-                android:text="@string/setup_step2_bullet" />
-            <TextView
-                style="@style/setupStepBulletStyle"
-                android:text="@string/setup_step3_bullet" />
-        </LinearLayout>
-        <com.android.inputmethod.latin.setup.SetupStepIndicatorView
-            android:id="@+id/setup_step_indicator"
-            android:layout_width="match_parent"
-            android:layout_height="24dp"
-            android:layout_below="@id/setup_step_bullets" />
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_below="@id/setup_step_indicator">
-            <include
-                android:id="@+id/setup_step1"
-                layout="@layout/setup_step" />
-            <include
-                android:id="@+id/setup_step2"
-                layout="@layout/setup_step" />
-            <include
-                android:id="@+id/setup_step3"
-                layout="@layout/setup_step" />
-        </FrameLayout>
-    </RelativeLayout>
-</ScrollView>
+    android:background="@color/setup_background"
+    android:paddingLeft="@dimen/setup_horizontal_padding"
+    android:paddingRight="@dimen/setup_horizontal_padding"
+    android:paddingTop="16dp"
+    android:paddingBottom="16dp">
+    <include
+        android:id="@+id/setup_welcome_screen"
+        layout="@layout/setup_welcome_screen" />
+    <include
+        android:id="@+id/setup_steps_screen"
+        layout="@layout/setup_steps_screen" />
+</FrameLayout>
diff --git a/java/res/raw/main_en.dict b/java/res/raw/main_en.dict
index 526761c..086874d 100644
--- a/java/res/raw/main_en.dict
+++ b/java/res/raw/main_en.dict
Binary files differ
diff --git a/java/res/raw/main_fr.dict b/java/res/raw/main_fr.dict
index 7520898..9044c7e 100644
--- a/java/res/raw/main_fr.dict
+++ b/java/res/raw/main_fr.dict
Binary files differ
diff --git a/java/res/raw/main_ru.dict b/java/res/raw/main_ru.dict
index 216ff09..9fd6133 100644
--- a/java/res/raw/main_ru.dict
+++ b/java/res/raw/main_ru.dict
Binary files differ
diff --git a/java/res/raw/setup_welcome_video.mp4 b/java/res/raw/setup_welcome_video.mp4
new file mode 100644
index 0000000..09357d8
--- /dev/null
+++ b/java/res/raw/setup_welcome_video.mp4
Binary files differ
diff --git a/java/res/values-af/dictionary-pack.xml b/java/res/values-af/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-af/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-am/dictionary-pack.xml b/java/res/values-am/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-am/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index e42ed3f..03a8b93 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -162,7 +162,7 @@
     <string name="not_now" msgid="6172462888202790482">"አሁን አልፈልግም"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"ተመሳሳዩ የግብዓት ቅጥ አስቀድሞ አለ፦ <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"የተገልጋይነት ጥናት ሁነታ"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"የቁልፍ ረጅም ጭነት መዘግየት"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"የሰሌዳ ቁልፍ ጠቅታ በመጫን መዘግየት"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"የቁልፍ ጭነት ንዝረት ርዝመት"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"የቁልፍ ጭነት ድምጽ መጠን"</string>
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"ውጫዊ የመዝገበቃላት ፋይል አንብብ"</string>
diff --git a/java/res/values-ar/dictionary-pack.xml b/java/res/values-ar/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-ar/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-be/dictionary-pack.xml b/java/res/values-be/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-be/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-bg/dictionary-pack.xml b/java/res/values-bg/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-bg/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 74aa556..3a9b579 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -162,8 +162,8 @@
     <string name="not_now" msgid="6172462888202790482">"Не сега"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Същият стил на въвеждане вече съществува: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим за изучаване на използваемостта"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Забавяне при продълж. натискане на клавишите"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Продълж. на вибрир. при натискане на клавиш"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Забавяне при продълж. натискане"</string>
+    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Продълж. на вибриране при натискане"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Сила на звука при натиск. на клавиш"</string>
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Четене на файл за външен речник"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"В папката „Изтегляния“ няма файлове за речник"</string>
diff --git a/java/res/values-ca/dictionary-pack.xml b/java/res/values-ca/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-ca/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-cs/dictionary-pack.xml b/java/res/values-cs/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-cs/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-da/dictionary-pack.xml b/java/res/values-da/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-da/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-de/dictionary-pack.xml b/java/res/values-de/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-de/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-el/dictionary-pack.xml b/java/res/values-el/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-el/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-en-rGB/dictionary-pack.xml b/java/res/values-en-rGB/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-en-rGB/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-es-rUS/dictionary-pack.xml b/java/res/values-es-rUS/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-es-rUS/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-es/dictionary-pack.xml b/java/res/values-es/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-es/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 1c8b16b..2da24af 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -42,15 +42,15 @@
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tecla para cambiar de idioma"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Mostrar cuando haya varios idiomas de entrada habilitados"</string>
     <string name="sliding_key_input_preview" msgid="6604262359510068370">"Mostrar indicador deslizante"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Mostrar pista visual al deslizar desde Mayús o tecla de símbolos"</string>
-    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso al ampliar tecla"</string>
+    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Mostrar pista visual al deslizar desde la tecla Mayús o la tecla de símbolos"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso para ampliar tecla"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin retraso"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminado"</string>
     <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> ms"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir contactos"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizar nombres de contactos para sugerencias y correcciones"</string>
     <string name="use_double_space_period" msgid="8781529969425082860">"Punto y espacio"</string>
-    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Si tocas dos veces el espacio, se inserta un punto seguido de un espacio."</string>
+    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Si tocas dos veces el espacio, se inserta un punto seguido de un espacio"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Mayúsculas automáticas"</string>
     <string name="auto_cap_summary" msgid="7934452761022946874">"Poner la primera letra de cada palabra en mayúscula"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionarios complementarios"</string>
@@ -162,7 +162,7 @@
     <string name="not_now" msgid="6172462888202790482">"Ahora no"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ya existe el estilo de entrada <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo estudio de usabilidad"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Retraso pulsación prolongada"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Retraso de pulsación prolongada"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Duración vibración al pulsar"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volumen sonido al pulsar tecla"</string>
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Leer archivo de diccionario externo"</string>
diff --git a/java/res/values-et/dictionary-pack.xml b/java/res/values-et/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-et/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-fa/dictionary-pack.xml b/java/res/values-fa/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-fa/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index 48b9d9e..e7f5c96 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -139,7 +139,7 @@
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"برای ذخیره دوباره لمس کنید"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"دیکشنری موجود است"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"فعال کردن بازخورد کاربر"</string>
-    <string name="prefs_description_log" msgid="7525225584555429211">"با ارسال خودکار آمار کاربرد و گزارش‌های خرابی، به بهبود این ویرایشگر روش ورودی کمک کنید"</string>
+    <string name="prefs_description_log" msgid="7525225584555429211">"با ارسال خودکار آمار استفاده و گزارش‌های خرابی، به بهبود این ویرایشگر روش ورودی کمک کنید"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"طرح زمینه صفحه‌کلید"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"انگلیسی (بریتانیا)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"انگلیسی (امریکا)"</string>
@@ -166,8 +166,8 @@
     <string name="not_now" msgid="6172462888202790482">"اکنون خیر"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"سبک ورودی مشابهی در حال حاضر وجود دارد: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"حالت بررسی قابلیت استفاده"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"تأخیر فشردن طولانی مدت کلید"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"طول مدت لرزش فشردن کلید"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"تأخیر فشار طولانی کلید"</string>
+    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"طول مدت لرزش در اثر فشردن کلید"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"میزان صدای فشردن کلید"</string>
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"خواندن فایل فرهنگ لغت خارجی"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"فایل فرهنگ لغتی در پوشه دانلودها وجود ندارد"</string>
diff --git a/java/res/values-fi/dictionary-pack.xml b/java/res/values-fi/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-fi/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-fr/dictionary-pack.xml b/java/res/values-fr/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-fr/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-hi/dictionary-pack.xml b/java/res/values-hi/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-hi/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-hr/dictionary-pack.xml b/java/res/values-hr/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-hr/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-hu/dictionary-pack.xml b/java/res/values-hu/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-hu/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-in/dictionary-pack.xml b/java/res/values-in/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-in/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-is/dictionary-pack.xml b/java/res/values-is/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-is/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-it/dictionary-pack.xml b/java/res/values-it/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-it/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-iw/dictionary-pack.xml b/java/res/values-iw/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-iw/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-ja/dictionary-pack.xml b/java/res/values-ja/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-ja/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-ka/dictionary-pack.xml b/java/res/values-ka/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-ka/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-ko/dictionary-pack.xml b/java/res/values-ko/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-ko/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-lt/dictionary-pack.xml b/java/res/values-lt/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-lt/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-lv/dictionary-pack.xml b/java/res/values-lv/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-lv/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-mk/dictionary-pack.xml b/java/res/values-mk/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-mk/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-mn/dictionary-pack.xml b/java/res/values-mn/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-mn/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-ms/dictionary-pack.xml b/java/res/values-ms/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-ms/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-nb/dictionary-pack.xml b/java/res/values-nb/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-nb/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index fc40bd1..caa98cc 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -162,8 +162,8 @@
     <string name="not_now" msgid="6172462888202790482">"Ikke nå"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Inndatastilen finnes allerede: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Bruksstudiemodus"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Forsinkelser i lange tastetrykk"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Vibrasjonsvarighet ved tastetrykk"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Forsinkelse lange tastetrykk"</string>
+    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Vibrasjonstid ved tastetrykk"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Lydstyrke ved tastetrykk"</string>
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Bruk en ekstern ordlistefil"</string>
     <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Det ligger ingen ordboksfiler i Nedlastinger-mappen"</string>
diff --git a/java/res/values-nl/dictionary-pack.xml b/java/res/values-nl/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-nl/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-pl/dictionary-pack.xml b/java/res/values-pl/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-pl/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-pt-rPT/dictionary-pack.xml b/java/res/values-pt-rPT/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-pt-rPT/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-pt/dictionary-pack.xml b/java/res/values-pt/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-pt/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-rm/dictionary-pack.xml b/java/res/values-rm/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-rm/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-ro/dictionary-pack.xml b/java/res/values-ro/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-ro/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-ru/dictionary-pack.xml b/java/res/values-ru/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-ru/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-sk/dictionary-pack.xml b/java/res/values-sk/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-sk/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-sl/dictionary-pack.xml b/java/res/values-sl/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-sl/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-sr/dictionary-pack.xml b/java/res/values-sr/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-sr/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-sv/dictionary-pack.xml b/java/res/values-sv/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-sv/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-sw/dictionary-pack.xml b/java/res/values-sw/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-sw/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 708d7fd..8702601 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -162,7 +162,7 @@
     <string name="not_now" msgid="6172462888202790482">"Sio sasa"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Mfumo sawa wa maingizo tayari upo: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modi ya uchunguzi wa utumizi"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Uchelewaji wa kubonyeza kitufe kwa muda mrefu"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Ubofyaji kitufe kunakochelewa"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Bonyeza kitufe cha muda wa kutetema"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Bonyeza kitufe cha kiwango cha sauti"</string>
     <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Soma faili ya kamusi ya nje"</string>
diff --git a/java/res/values-sw600dp-land/setup-dimens.xml b/java/res/values-sw600dp-land/setup-dimens.xml
index 9aea214..e5051ea 100644
--- a/java/res/values-sw600dp-land/setup-dimens.xml
+++ b/java/res/values-sw600dp-land/setup-dimens.xml
@@ -16,5 +16,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <dimen name="setup_title_text_size">64sp</dimen>
+    <dimen name="setup_welcome_description_text_size">36sp</dimen>
     <dimen name="setup_horizontal_padding">96dp</dimen>
 </resources>
diff --git a/java/res/values-sw768dp-land/setup-dimens.xml b/java/res/values-sw768dp-land/setup-dimens.xml
index 0d2af17..34b7f42 100644
--- a/java/res/values-sw768dp-land/setup-dimens.xml
+++ b/java/res/values-sw768dp-land/setup-dimens.xml
@@ -16,5 +16,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <dimen name="setup_title_text_size">64sp</dimen>
+    <dimen name="setup_welcome_description_text_size">36sp</dimen>
     <dimen name="setup_horizontal_padding">192dp</dimen>
 </resources>
diff --git a/java/res/values-th/dictionary-pack.xml b/java/res/values-th/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-th/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-tl/dictionary-pack.xml b/java/res/values-tl/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-tl/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-tr/dictionary-pack.xml b/java/res/values-tr/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-tr/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index 053222c..a0a6a67 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -51,7 +51,7 @@
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Öneri ve düzeltmeler için Kişiler\'deki adları kullan"</string>
     <string name="use_double_space_period" msgid="8781529969425082860">"Çift boşlukla nokta ekleme"</string>
     <string name="use_double_space_period_summary" msgid="6532892187247952799">"Boşluk çubuğuna iki kez vurmak nokta ve ardından bir boşluk ekler"</string>
-    <string name="auto_cap" msgid="1719746674854628252">"Otomatik olarak büyük fark yap"</string>
+    <string name="auto_cap" msgid="1719746674854628252">"Otomatik olarak büyük harf yap"</string>
     <string name="auto_cap_summary" msgid="7934452761022946874">"Her cümlenin ilk kelimesini büyük harf yap"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Ek sözlükler"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Ana sözlük"</string>
diff --git a/java/res/values-uk/dictionary-pack.xml b/java/res/values-uk/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-uk/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-v17/setup-styles.xml b/java/res/values-v17/setup-styles.xml
new file mode 100644
index 0000000..8a9d664
--- /dev/null
+++ b/java/res/values-v17/setup-styles.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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 xmlns:android="http://schemas.android.com/apk/res/android">
+    <style name="setupTitleStyle" parent="setupTitleStyleCommon">
+        <item name="android:layout_alignParentStart">true</item>
+    </style>
+    <style name="setupStepActionLabelStyle" parent="setupStepActionLabelStyleCommon">
+        <item name="android:paddingStart">12dp</item>
+        <item name="android:paddingEnd">24dp</item>
+    </style>
+</resources>
diff --git a/java/res/values-vi/dictionary-pack.xml b/java/res/values-vi/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-vi/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-zh-rCN/dictionary-pack.xml b/java/res/values-zh-rCN/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-zh-rCN/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-zh-rTW/dictionary-pack.xml b/java/res/values-zh-rTW/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-zh-rTW/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values-zu/dictionary-pack.xml b/java/res/values-zu/dictionary-pack.xml
deleted file mode 100644
index f65d45b..0000000
--- a/java/res/values-zu/dictionary-pack.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2013, 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for dictionary_pack_settings_activity (664691545147898274) -->
-    <skip />
-    <!-- no translation found for authority (8773166495153016489) -->
-    <skip />
-    <string name="default_metadata_uri" msgid="6889596349847015153"></string>
-    <!-- no translation found for local_metadata_filename (4634356913689271331) -->
-    <skip />
-</resources>
diff --git a/java/res/values/dictionary-pack.xml b/java/res/values/dictionary-pack.xml
index 3fdc671..31834b5 100644
--- a/java/res/values/dictionary-pack.xml
+++ b/java/res/values/dictionary-pack.xml
@@ -20,8 +20,8 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="dictionary_pack_client_id" translatable="false">com.android.inputmethod.latin</string>
     <string name="dictionary_pack_metadata_uri" translatable="false"></string>
-    <string name="dictionary_pack_settings_activity">com.android.inputmethod.dictionarypack.DictionarySettingsActivity</string>
-    <string name="authority">com.android.inputmethod.dictionarypack.aosp</string>
-    <string name="default_metadata_uri"></string>
-    <string name="local_metadata_filename">metadata.json</string>
+    <string name="dictionary_pack_settings_activity" translatable="false">com.android.inputmethod.dictionarypack.DictionarySettingsActivity</string>
+    <string name="authority" translatable="false">com.android.inputmethod.dictionarypack.aosp</string>
+    <string name="default_metadata_uri" translatable="false"></string>
+    <string name="local_metadata_filename" translatable="false">metadata.json</string>
 </resources>
diff --git a/java/res/values/setup-dimens.xml b/java/res/values/setup-dimens.xml
index 007906d..1634777 100644
--- a/java/res/values/setup-dimens.xml
+++ b/java/res/values/setup-dimens.xml
@@ -16,5 +16,11 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <dimen name="setup_title_text_size">46sp</dimen>
+    <dimen name="setup_welcome_description_text_size">26sp</dimen>
     <dimen name="setup_horizontal_padding">16dp</dimen>
+    <integer name="setup_title_weight_in_screen">40</integer>
+    <integer name="setup_body_weight_in_screen">60</integer>
+    <integer name="setup_welcome_video_weight_in_screen">80</integer>
+    <integer name="setup_welcome_video_left_padding_weight_in_screen">10</integer>
+    <integer name="setup_welcome_video_right_padding_weight_in_screen">10</integer>
 </resources>
diff --git a/java/res/values/setup-styles-common.xml b/java/res/values/setup-styles-common.xml
new file mode 100644
index 0000000..e9c72eb
--- /dev/null
+++ b/java/res/values/setup-styles-common.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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 xmlns:android="http://schemas.android.com/apk/res/android">
+    <style name="setupTitleStyleCommon">
+        <item name="android:textColor">@color/setup_text_dark</item>
+        <item name="android:textSize">@dimen/setup_title_text_size</item>
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+    </style>
+    <style name="setupWelcomeDescritpionStyle" parent="setupTitleStyle">
+        <item name="android:textSize">@dimen/setup_welcome_description_text_size</item>
+    </style>
+    <style name="setupStepBulletStyle">
+        <item name="android:textColor">@color/setup_text_dark</item>
+        <item name="android:textSize">22sp</item>
+        <item name="android:layout_width">0dp</item>
+        <item name="android:layout_weight">1.0</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:gravity">center_horizontal</item>
+    </style>
+    <style name="setupStepBaseStyle">
+        <item name="android:textColor">@color/setup_text_dark</item>
+        <item name="android:background">@color/setup_step_background</item>
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:paddingLeft">24dp</item>
+        <item name="android:paddingRight">24dp</item>
+    </style>
+    <style name="setupStepTitleStyle" parent="setupStepBaseStyle">
+        <item name="android:textSize">22sp</item>
+    </style>
+    <style name="setupStepInstructionStyle" parent="setupStepBaseStyle">
+        <item name="android:textSize">14sp</item>
+    </style>
+    <style name="setupStepStartIndicatorStyle">
+        <item name="android:layout_width">24dp</item>
+        <item name="android:layout_height">48dp</item>
+    </style>
+    <style name="setupStepActionLabelStyleCommon" parent="setupStepBaseStyle">
+        <item name="android:textColor">@color/setup_step_action_color</item>
+        <item name="android:background">@drawable/setup_step_action_background</item>
+        <item name="android:layout_height">48dp</item>
+        <item name="android:paddingLeft">12dp</item>
+        <item name="android:textSize">18sp</item>
+        <item name="android:drawablePadding">12dp</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:clickable">true</item>
+        <item name="android:focusable">true</item>
+    </style>
+    <style name="setupStepStartActionLabelStyleCommon" parent="setupStepActionLabelStyleCommon">
+        <item name="android:paddingLeft">24dp</item>
+        <item name="android:paddingRight">24dp</item>
+    </style>
+</resources>
diff --git a/java/res/values/setup-styles.xml b/java/res/values/setup-styles.xml
index cfc689a..1ffe8ca 100644
--- a/java/res/values/setup-styles.xml
+++ b/java/res/values/setup-styles.xml
@@ -15,31 +15,6 @@
 -->
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
-    <style name="setupTitleStyle">
-        <item name="android:textColor">@color/setup_text_dark</item>
-        <item name="android:textSize">@dimen/setup_title_text_size</item>
-    </style>
-    <style name="setupStepBulletStyle">
-        <item name="android:textColor">@color/setup_text_dark</item>
-        <item name="android:textSize">22sp</item>
-        <item name="android:layout_width">0dp</item>
-        <item name="android:layout_weight">1.0</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:gravity">center_horizontal</item>
-    </style>
-    <style name="setupStepTitleStyle">
-        <item name="android:background">@color/setup_step_background</item>
-        <item name="android:textColor">@color/setup_text_dark</item>
-        <item name="android:textSize">22sp</item>
-    </style>
-    <style name="setupStepInstructionStyle">
-        <item name="android:background">@color/setup_step_background</item>
-        <item name="android:textColor">@color/setup_text_dark</item>
-        <item name="android:textSize">14sp</item>
-    </style>
-    <style name="setupStepActionLabelStyle">
-        <item name="android:background">@color/setup_step_background</item>
-        <item name="android:textColor">@color/setup_text_action</item>
-        <item name="android:textSize">18sp</item>
-    </style>
+    <style name="setupTitleStyle" parent="setupTitleStyleCommon" />
+    <style name="setupStepActionLabelStyle" parent="setupStepActionLabelStyleCommon" />
 </resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index f5e2441..10cfc78 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -442,33 +442,44 @@
     <!-- Title of the button to revert to the default value of the device in the settings dialog [CHAR LIMIT=15] -->
     <string name="button_default">Default</string>
 
-    <!-- TODO: Remove translatable="false" once wordings are finalized. -->
+    <!-- Title of the setup wizard welcome screen. [CHAR LIMT=40] -->
+    <string name="setup_welcome_title">"Welcome to <xliff:g id="application_name">%s</xliff:g>"</string>
+    <!-- Additional title of the setup wizard welcome screen, just below the setup_welcome_title. [CHAR_LIMIT=64] -->
+    <string name="setup_welcome_additional_description">with Gesture Typing</string>
+    <!-- The label of the button that starts the setup wizard. [CHAR_LIMIT=64] -->
+    <string name="setup_start_action">Get started</string>
+    <!-- The label of the button that navigates the user to the next step of the setup wizard. [CHAR_LIMIT=64] -->
+    <string name="setup_next_action">Next step</string>
     <!-- Title of the setup wizard. [CHAR LIMT=40] -->
-    <string name="setup_title" translatable="false">"Installing <xliff:g id="application_name">%s</xliff:g>"</string>
+    <string name="setup_steps_title">"Setting up <xliff:g id="application_name">%s</xliff:g>"</string>
     <!-- Ordinal number of the 1st step in the setup wizard. [CHAR LIMIT=5] -->
     <string name="setup_step1_bullet" translatable="false">1</string>
     <!-- Title of the 1st step in the setup wizard. [CHAR LIMIT=64] -->
-    <string name="setup_step1_title" translatable="false">"Enable <xliff:g id="application_name">%s</xliff:g> in settings."</string>
+    <string name="setup_step1_title">"Enable <xliff:g id="application_name">%s</xliff:g>"</string>
     <!-- Detailed instruction of the 1st step in the setup wizard. [CHAR LIMIT=80] -->
-    <string name="setup_step1_instruction" translatable="false">"For security, please check \"<xliff:g id="application_name">%s</xliff:g>\""</string>
+    <string name="setup_step1_instruction">"Please check \"<xliff:g id="application_name">%s</xliff:g>\" in your Language &amp; input settings. This will authorize it to run on your device."</string>
+    <!-- The label of the button that triggers the Language & input settings in order to enable the keyboard. [CHAR_LIMIT=64] -->
+    <string name="setup_step1_action">Enable in Settings</string>
     <!-- Ordinal number of the 2nd step in the setup wizard. [CHAR LIMIT=5] -->
     <string name="setup_step2_bullet" translatable="false">2</string>
     <!-- Title of the 2nd step in the setup wizard. [CHAR LIMIT=64] -->
-    <string name="setup_step2_title" translatable="false">"Switch to <xliff:g id="application_name">%s</xliff:g>."</string>
+    <string name="setup_step2_title">"Switch to <xliff:g id="application_name">%s</xliff:g>"</string>
     <!-- Detailed instruction of the 2nd step in the setup wizard. [CHAR LIMIT=80] -->
-    <string name="setup_step2_instruction" translatable="false">"Now that you've enabled <xliff:g id="application_name">%s</xliff:g>, you can switch to it."</string>
+    <string name="setup_step2_instruction">"Next, select \"<xliff:g id="application_name">%s</xliff:g>\" as your active text-input method."</string>
+    <!-- The label of the button that triggers the choose input method dialog in order to select the keyboard. [CHAR_LIMIT=64] -->
+    <string name="setup_step2_action">Switch input methods</string>
     <!-- Ordinal number of the 3rd step in the setup wizard. [CHAR LIMIT=5] -->
     <string name="setup_step3_bullet" translatable="false">3</string>
     <!-- Title of the 3rd step in the setup wizard. [CHAR LIMIT=64] -->
-    <string name="setup_step3_title" translatable="false">"Congratulations, you're all set!"</string>
+    <string name="setup_step3_title">"Congratulations, you're all set!"</string>
     <!-- Detailed instruction of the 3rd step in the setup wizard. [CHAR LIMIT=80] -->
-    <string name="setup_step3_instruction" translatable="false">Configure additional languages</string>
-    <!-- Title of the Language & input settings. This should be aligned with msgid="5292716747264442359" -->
-    <string name="language_settings">Language &amp; input</string>
-    <!-- Title of the Input method picker. This should be aligned with msgid="4653387336791222978" -->
-    <string name="select_input_method">Choose input method</string>
+    <string name="setup_step3_instruction">Now you can type in all your favorite apps with <xliff:g id="application_name">%s</xliff:g>.</string>
+    <!-- The label of the button that triggers the screen for configuaring additional languages of the keyboard. [CHAR_LIMIT=64] -->
+    <string name="setup_step3_action">Configure additional languages</string>
+    <!-- The label of the button that finishes the setup wizard. [CHAR_LIMIT=64] -->
+    <string name="setup_finish_action">Finished</string>
     <!-- Option to show setup wizard icon. [CHAR LIMIT=30]-->
-    <string name="show_setup_wizard_icon" translatable="false">Show setup wizard icon</string>
+    <string name="show_setup_wizard_icon">Show setup wizard icon</string>
 
     <!-- The dictionary provider application name. Visible in Settings/Applications/Manage applications. -->
     <string name="app_name">Dictionary Provider</string>
diff --git a/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java b/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java
index d4f1ea8..f8e1902 100644
--- a/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java
@@ -22,23 +22,23 @@
 import java.lang.reflect.Method;
 
 public final class TextViewCompatUtils {
-    // Note that TextView.setCompoundDrawablesRelative(Drawable,Drawable,Drawable,Drawable) has
-    // been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
-    private static final Method METHOD_setCompoundDrawablesRelative = CompatUtils.getMethod(
-            TextView.class, "setCompoundDrawablesRelative",
+    // Note that TextView.setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable,Drawable,
+    // Drawable,Drawable) has been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
+    private static final Method METHOD_setCompoundDrawablesRelativeWithIntrinsicBounds =
+            CompatUtils.getMethod(TextView.class, "setCompoundDrawablesRelativeWithIntrinsicBounds",
             Drawable.class, Drawable.class, Drawable.class, Drawable.class);
 
     private TextViewCompatUtils() {
         // This utility class is not publicly instantiable.
     }
 
-    public static void setCompoundDrawablesRelative(final TextView textView, final Drawable start,
-            final Drawable top, final Drawable end, final Drawable bottom) {
-        if (METHOD_setCompoundDrawablesRelative == null) {
-            textView.setCompoundDrawables(start, top, end, bottom);
+    public static void setCompoundDrawablesRelativeWithIntrinsicBounds(final TextView textView,
+            final Drawable start, final Drawable top, final Drawable end, final Drawable bottom) {
+        if (METHOD_setCompoundDrawablesRelativeWithIntrinsicBounds == null) {
+            textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
             return;
         }
-        CompatUtils.invoke(textView, null, METHOD_setCompoundDrawablesRelative,
+        CompatUtils.invoke(textView, null, METHOD_setCompoundDrawablesRelativeWithIntrinsicBounds,
                 start, top, end, bottom);
     }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
index df4a52f..faf5d3c 100644
--- a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
+++ b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
@@ -174,7 +174,7 @@
             final long downloadId = UpdateHandler.registerDownloadRequest(manager, request, db,
                     mWordList.mId, mWordList.mVersion);
             Utils.l("Starting download of", uri, "with id", downloadId);
-            PrivateLog.log("Starting download of " + uri + ", id : " + downloadId, context);
+            PrivateLog.log("Starting download of " + uri + ", id : " + downloadId);
         }
     }
 
@@ -333,7 +333,7 @@
                     mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mChecksum,
                     mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion);
             PrivateLog.log("Insert 'available' record for " + mWordList.mDescription
-                    + " and locale " + mWordList.mLocale, context);
+                    + " and locale " + mWordList.mLocale);
             db.insert(MetadataDbHelper.METADATA_TABLE_NAME, null, values);
         }
     }
@@ -383,7 +383,7 @@
                     mWordList.mChecksum, mWordList.mFileSize, mWordList.mVersion,
                     mWordList.mFormatVersion);
             PrivateLog.log("Insert 'preinstalled' record for " + mWordList.mDescription
-                    + " and locale " + mWordList.mLocale, context);
+                    + " and locale " + mWordList.mLocale);
             db.insert(MetadataDbHelper.METADATA_TABLE_NAME, null, values);
         }
     }
@@ -424,7 +424,7 @@
                     mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mChecksum,
                     mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion);
             PrivateLog.log("Updating record for " + mWordList.mDescription
-                    + " and locale " + mWordList.mLocale, context);
+                    + " and locale " + mWordList.mLocale);
             db.update(MetadataDbHelper.METADATA_TABLE_NAME, values,
                     MetadataDbHelper.WORDLISTID_COLUMN + " = ? AND "
                             + MetadataDbHelper.VERSION_COLUMN + " = ?",
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
index f8d1c4f..4fbe162 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
@@ -189,7 +189,7 @@
      */
     @Override
     public String getType(final Uri uri) {
-        PrivateLog.log("Asked for type of : " + uri, this);
+        PrivateLog.log("Asked for type of : " + uri);
         final int match = matchUri(uri);
         switch (match) {
             case NO_MATCH: return null;
@@ -220,7 +220,7 @@
     public Cursor query(final Uri uri, final String[] projection, final String selection,
             final String[] selectionArgs, final String sortOrder) {
         Utils.l("Uri =", uri);
-        PrivateLog.log("Query : " + uri, this);
+        PrivateLog.log("Query : " + uri);
         final String clientId = getClientId(uri);
         final int match = matchUri(uri);
         switch (match) {
@@ -228,7 +228,7 @@
             case DICTIONARY_V2_WHOLE_LIST:
                 final Cursor c = MetadataDbHelper.queryDictionaries(getContext(), clientId);
                 Utils.l("List of dictionaries with count", c.getCount());
-                PrivateLog.log("Returned a list of " + c.getCount() + " items", this);
+                PrivateLog.log("Returned a list of " + c.getCount() + " items");
                 return c;
             case DICTIONARY_V2_DICT_INFO:
                 // In protocol version 2, we return null if the client is unknown. Otherwise
@@ -248,10 +248,10 @@
                 // TODO: pass clientId to the following function
                 DictionaryService.updateNowIfNotUpdatedInAVeryLongTime(getContext());
                 if (null != dictFiles && dictFiles.size() > 0) {
-                    PrivateLog.log("Returned " + dictFiles.size() + " files", this);
+                    PrivateLog.log("Returned " + dictFiles.size() + " files");
                     return new ResourcePathCursor(dictFiles);
                 } else {
-                    PrivateLog.log("No dictionary files for this URL", this);
+                    PrivateLog.log("No dictionary files for this URL");
                     return new ResourcePathCursor(Collections.<WordListInfo>emptyList());
                 }
             // V2_METADATA and V2_DATAFILE are not supported for query()
@@ -488,7 +488,7 @@
     public Uri insert(final Uri uri, final ContentValues values)
             throws UnsupportedOperationException {
         if (null == uri || null == values) return null; // Should never happen but let's be safe
-        PrivateLog.log("Insert, uri = " + uri.toString(), this);
+        PrivateLog.log("Insert, uri = " + uri.toString());
         final String clientId = getClientId(uri);
         switch (matchUri(uri)) {
             case DICTIONARY_V2_METADATA:
@@ -517,7 +517,7 @@
                 break;
             case DICTIONARY_V1_WHOLE_LIST:
             case DICTIONARY_V1_DICT_INFO:
-                PrivateLog.log("Attempt to insert : " + uri, this);
+                PrivateLog.log("Attempt to insert : " + uri);
                 throw new UnsupportedOperationException(
                         "Insertion in the dictionary is not supported in this version");
         }
@@ -532,7 +532,7 @@
     @Override
     public int update(final Uri uri, final ContentValues values, final String selection,
             final String[] selectionArgs) throws UnsupportedOperationException {
-        PrivateLog.log("Attempt to update : " + uri, this);
+        PrivateLog.log("Attempt to update : " + uri);
         throw new UnsupportedOperationException("Updating dictionary words is not supported");
     }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
index 5817eb4..46bb554 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
@@ -21,7 +21,6 @@
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
-import android.content.SharedPreferences;
 import android.os.IBinder;
 import android.text.format.DateUtils;
 import android.util.Log;
@@ -190,7 +189,7 @@
         // is still more recent than UPDATE_FREQUENCY, do nothing.
         if (!isLastUpdateAtLeastThisOld(context, UPDATE_FREQUENCY)) return;
 
-        PrivateLog.log("Date changed - registering alarm", context);
+        PrivateLog.log("Date changed - registering alarm");
         AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
 
         // Best effort to wake between midnight and MAX_ALARM_DELAY in the morning.
@@ -215,7 +214,7 @@
     private static boolean isLastUpdateAtLeastThisOld(final Context context, final long time) {
         final long now = System.currentTimeMillis();
         final long lastUpdate = MetadataDbHelper.getOldestUpdateTime(context);
-        PrivateLog.log("Last update was " + lastUpdate, context);
+        PrivateLog.log("Last update was " + lastUpdate);
         return lastUpdate + time < now;
     }
 
diff --git a/java/src/com/android/inputmethod/dictionarypack/LogProblemReporter.java b/java/src/com/android/inputmethod/dictionarypack/LogProblemReporter.java
index c127ad5..c9e128d 100644
--- a/java/src/com/android/inputmethod/dictionarypack/LogProblemReporter.java
+++ b/java/src/com/android/inputmethod/dictionarypack/LogProblemReporter.java
@@ -28,7 +28,8 @@
         TAG = tag;
     }
 
+    @Override
     public void report(final Exception e) {
-        Log.e(TAG, "Reporting problem : " + e);
+        Log.e(TAG, "Reporting problem", e);
     }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index 55f545a..cb8e25e 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -16,13 +16,11 @@
 
 package com.android.inputmethod.dictionarypack;
 
-import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
-import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -309,8 +307,7 @@
      * @param uri the metadata URI we just downloaded
      */
     public static void saveLastUpdateTimeOfUri(final Context context, final String uri) {
-        PrivateLog.log("Save last update time of URI : " + uri + " " + System.currentTimeMillis(),
-                context);
+        PrivateLog.log("Save last update time of URI : " + uri + " " + System.currentTimeMillis());
         final ContentValues values = new ContentValues();
         values.put(CLIENT_LAST_UPDATE_DATE_COLUMN, System.currentTimeMillis());
         final SQLiteDatabase defaultDb = getDb(context, null);
diff --git a/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java b/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
index 8593c1c..67dd7b9 100644
--- a/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
+++ b/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
@@ -16,7 +16,6 @@
 
 package com.android.inputmethod.dictionarypack;
 
-import android.content.ContentProvider;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.sqlite.SQLiteDatabase;
@@ -24,6 +23,7 @@
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Locale;
 
 /**
  * Class to keep long-term log. This is inactive in production, and is only for debug purposes.
@@ -44,10 +44,10 @@
             + COLUMN_EVENT + " TEXT);";
 
     private static final SimpleDateFormat sDateFormat =
-            new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+            new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
 
     private static PrivateLog sInstance = new PrivateLog();
-    private static DebugHelper mDebugHelper = null;
+    private static DebugHelper sDebugHelper = null;
 
     private PrivateLog() {
     }
@@ -55,8 +55,8 @@
     public static synchronized PrivateLog getInstance(final Context context) {
         if (!DEBUG) return sInstance;
         synchronized(PrivateLog.class) {
-            if (sInstance.mDebugHelper == null) {
-                sInstance.mDebugHelper = new DebugHelper(context);
+            if (sDebugHelper == null) {
+                sDebugHelper = new DebugHelper(context);
             }
             return sInstance;
         }
@@ -94,16 +94,9 @@
 
     }
 
-    public static void log(String event, Context context) {
+    public static void log(String event) {
         if (!DEBUG) return;
-        final SQLiteDatabase l = getInstance(context).mDebugHelper.getWritableDatabase();
-        mDebugHelper.insert(l, event);
-    }
-
-    public static void log(String event, ContentProvider provider) {
-        if (!DEBUG) return;
-        final SQLiteDatabase l =
-                getInstance(provider.getContext()).mDebugHelper.getWritableDatabase();
-        mDebugHelper.insert(l, event);
+        final SQLiteDatabase l = sDebugHelper.getWritableDatabase();
+        DebugHelper.insert(l, event);
     }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
index e05a79b..a596609 100644
--- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
@@ -181,10 +181,9 @@
             if (!cursor.moveToFirst()) return;
             do {
                 final String clientId = cursor.getString(0);
-                if (TextUtils.isEmpty(clientId)) continue; // This probably can't happen
                 final String metadataUri =
                         MetadataDbHelper.getMetadataUriAsString(context, clientId);
-                PrivateLog.log("Update for clientId " + Utils.s(clientId), context);
+                PrivateLog.log("Update for clientId " + Utils.s(clientId));
                 Utils.l("Update for clientId", clientId, " which uses URI ", metadataUri);
                 uris.add(metadataUri);
             } while (cursor.moveToNext());
@@ -212,7 +211,7 @@
      */
     private static void updateClientsWithMetadataUri(final Context context,
             final boolean updateNow, final String metadataUri) {
-        PrivateLog.log("Update for metadata URI " + Utils.s(metadataUri), context);
+        PrivateLog.log("Update for metadata URI " + Utils.s(metadataUri));
         final Request metadataRequest = new Request(Uri.parse(metadataUri));
         Utils.l("Request =", metadataRequest);
 
@@ -258,7 +257,7 @@
             // method will ignore it.
             writeMetadataDownloadId(context, metadataUri, downloadId);
         }
-        PrivateLog.log("Requested download with id " + downloadId, context);
+        PrivateLog.log("Requested download with id " + downloadId);
     }
 
     /**
@@ -405,7 +404,7 @@
     /* package */ static void downloadFinished(final Context context, final Intent intent) {
         // Get and check the ID of the file that was downloaded
         final long fileId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, NOT_AN_ID);
-        PrivateLog.log("Download finished with id " + fileId, context);
+        PrivateLog.log("Download finished with id " + fileId);
         Utils.l("DownloadFinished with id", fileId);
         if (NOT_AN_ID == fileId) return; // Spurious wake-up: ignore
 
@@ -492,7 +491,7 @@
 
     private static void publishUpdateCycleCompletedEvent(final Context context) {
         // Even if this is not successful, we have to publish the new state.
-        PrivateLog.log("Publishing update cycle completed event", context);
+        PrivateLog.log("Publishing update cycle completed event");
         Utils.l("Publishing update cycle completed event");
         for (UpdateEventListener listener : linkedCopyOfList(sUpdateEventListeners)) {
             listener.updateCycleCompleted();
@@ -583,7 +582,7 @@
         }
 
         Utils.l("Downloaded metadata :", newMetadata);
-        PrivateLog.log("Downloaded metadata\n" + newMetadata, context);
+        PrivateLog.log("Downloaded metadata\n" + newMetadata);
 
         final ActionBatch actions = computeUpgradeTo(context, clientId, newMetadata);
         // TODO: Check with UX how we should report to the user
@@ -611,7 +610,7 @@
                 MetadataDbHelper.DESCRIPTION_COLUMN), "for", downloadRecord.mClientId);
         PrivateLog.log("Downloaded a new word list with description : "
                 + downloadRecord.mAttributes.getAsString(MetadataDbHelper.DESCRIPTION_COLUMN)
-                + " for " + downloadRecord.mClientId, context);
+                + " for " + downloadRecord.mClientId);
 
         final String locale =
                 downloadRecord.mAttributes.getAsString(MetadataDbHelper.LOCALE_COLUMN);
diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
index 0d923ae..93f12d5 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
@@ -23,7 +23,9 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.widget.Button;
+import android.widget.ListView;
 
 import com.android.inputmethod.latin.R;
 
@@ -42,6 +44,7 @@
     // What to display in the "status" field when we receive unknown data as a status from
     // the content provider. Empty string sounds sensible.
     static final private String NO_STATUS_MESSAGE = "";
+    static final private int NOT_AN_INDEX = -1;
 
     /// Actions
     static final private int ACTION_UNKNOWN = 0;
@@ -64,7 +67,8 @@
     static final private int ANIMATION_IN = 1;
     static final private int ANIMATION_OUT = 2;
 
-    private static Button sLastClickedActionButton = null;
+    private static int sLastClickedIndex = NOT_AN_INDEX;
+    private static String sLastClickedWordlistId = null;
     private final OnWordListPreferenceClick mPreferenceClickHandler =
             new OnWordListPreferenceClick();
     private final OnActionButtonClick mActionButtonClickHandler =
@@ -196,7 +200,8 @@
         ((ViewGroup)view).setLayoutTransition(null);
         final Button button = (Button)view.findViewById(R.id.wordlist_button);
         button.setText(getButtonLabel(mStatus));
-        button.setVisibility(View.INVISIBLE);
+        // String identity match. This is an ==, not an .equals, on purpose.
+        button.setVisibility(mWordlistId == sLastClickedWordlistId ? View.VISIBLE : View.INVISIBLE);
         button.setOnClickListener(mActionButtonClickHandler);
         view.setOnClickListener(mPreferenceClickHandler);
     }
@@ -205,15 +210,31 @@
         @Override
         public void onClick(final View v) {
             final Button button = (Button)v.findViewById(R.id.wordlist_button);
-            if (null != sLastClickedActionButton) {
-                animateButton(sLastClickedActionButton, ANIMATION_OUT);
-            }
             animateButton(button, ANIMATION_IN);
-            sLastClickedActionButton = button;
+            final ViewParent parent = v.getParent();
+            // Just in case something changed in the framework, test for the concrete class
+            if (!(parent instanceof ListView)) return;
+            final ListView listView = (ListView)parent;
+            final int myIndex = listView.indexOfChild(v) + listView.getFirstVisiblePosition();
+            if (NOT_AN_INDEX != sLastClickedIndex) {
+                animateButton(getButtonForIndex(listView, sLastClickedIndex), ANIMATION_OUT);
+            }
+            sLastClickedIndex = myIndex;
+            sLastClickedWordlistId = mWordlistId;
         }
     }
 
+    private Button getButtonForIndex(final ListView listView, final int index) {
+        final int indexInChildren = index - listView.getFirstVisiblePosition();
+        if (indexInChildren < 0 || index > listView.getLastVisiblePosition()) {
+            // The view is offscreen.
+            return null;
+        }
+        return (Button)listView.getChildAt(indexInChildren).findViewById(R.id.wordlist_button);
+    }
+
     private void animateButton(final Button button, final int direction) {
+        if (null == button) return;
         final float outerX = ((View)button.getParent()).getWidth();
         final float innerX = button.getX() - button.getTranslationX();
         if (View.INVISIBLE == button.getVisibility()) {
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index ba78d01..d74644d 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -1189,10 +1189,12 @@
                 if (ENABLE_USABILITY_STUDY_LOG) {
                     writeUsabilityStudyLog(me, action, eventTime, i, pointerId, px, py);
                 }
-                if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
-                    ResearchLogger.mainKeyboardView_processMotionEvent(
-                            me, action, eventTime, i, pointerId, px, py);
-                }
+                // TODO: This seems to be no longer necessary, and confusing because it leads to
+                // duplicate MotionEvents being recorded.
+                // if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
+                //     ResearchLogger.mainKeyboardView_processMotionEvent(
+                //             me, action, eventTime, i, pointerId, px, py);
+                // }
             }
         } else {
             final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 18e7122..dbc2b90 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -141,7 +141,6 @@
                 mOutputTypes);
         final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList();
         for (int j = 0; j < count; ++j) {
-            if (composerSize > 0 && mOutputScores[j] < 1) break;
             final int start = j * MAX_WORD_LENGTH;
             int len = 0;
             while (len < MAX_WORD_LENGTH && mOutputCodePoints[start + len] != 0) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 0e1c4dc..16eab4b 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -439,6 +439,7 @@
         mHandler.onCreate();
         DEBUG = LatinImeLogger.sDBG;
 
+        // TODO: Resolve mutual dependencies of {@link #loadSettings()} and {@link #initSuggest()}.
         loadSettings();
         initSuggest();
 
@@ -476,6 +477,7 @@
         final InputAttributes inputAttributes =
                 new InputAttributes(getCurrentInputEditorInfo(), isFullscreenMode());
         mSettings.loadSettings(locale, inputAttributes);
+        // May need to reset the contacts dictionary depending on the user settings.
         resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
     }
 
@@ -745,6 +747,11 @@
         mRecapitalizeStatus.deactivate();
         mCurrentlyPressedHardwareKeys.clear();
 
+        // Note: the following does a round-trip IPC on the main thread: be careful
+        final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+        if (null != mSuggest && null != currentLocale && !currentLocale.equals(mSuggest.mLocale)) {
+            initSuggest();
+        }
         if (mSuggestionStripView != null) {
             // This will set the punctuation suggestions if next word suggestion is off;
             // otherwise it will clear the suggestion strip.
@@ -797,8 +804,7 @@
         // to the user dictionary.
         if (null != mPositionalInfoForUserDictPendingAddition
                 && mPositionalInfoForUserDictPendingAddition.tryReplaceWithActualWord(
-                        mConnection, editorInfo, mLastSelectionEnd,
-                        mSubtypeSwitcher.getCurrentSubtypeLocale())) {
+                        mConnection, editorInfo, mLastSelectionEnd, currentLocale)) {
             mPositionalInfoForUserDictPendingAddition = null;
         }
         // If tryReplaceWithActualWord returns false, we don't know what word was
@@ -1678,7 +1684,7 @@
         private SuggestedWords getSuggestedWordsGestureLocked(final InputPointers batchPointers) {
             mLatinIme.mWordComposer.setBatchInputPointers(batchPointers);
             final SuggestedWords suggestedWords =
-                    mLatinIme.getSuggestedWords(Suggest.SESSION_GESTURE);
+                    mLatinIme.getSuggestedWordsOrOlderSuggestions(Suggest.SESSION_GESTURE);
             final int suggestionCount = suggestedWords.size();
             if (suggestionCount <= 1) {
                 final String mostProbableSuggestion = (suggestionCount == 0) ? null
@@ -1970,9 +1976,12 @@
         // If we have a recapitalize in progress, use it; otherwise, create a new one.
         if (!mRecapitalizeStatus.isActive()
                 || !mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) {
+            final CharSequence selectedText =
+                    mConnection.getSelectedText(0 /* flags, 0 for no styles */);
+            if (TextUtils.isEmpty(selectedText)) return; // Race condition with the input connection
             mRecapitalizeStatus.initialize(mLastSelectionStart, mLastSelectionEnd,
-                    mConnection.getSelectedText(0 /* flags, 0 for no styles */).toString(),
-                    mSettings.getCurrentLocale(), mSettings.getWordSeparators());
+                    selectedText.toString(), mSettings.getCurrentLocale(),
+                    mSettings.getWordSeparators());
             // We trim leading and trailing whitespace.
             mRecapitalizeStatus.trim();
             // Trimming the object may have changed the length of the string, and we need to
@@ -2152,7 +2161,8 @@
             return;
         }
 
-        final SuggestedWords suggestedWords = getSuggestedWords(Suggest.SESSION_TYPING);
+        final SuggestedWords suggestedWords =
+                getSuggestedWordsOrOlderSuggestions(Suggest.SESSION_TYPING);
         final String typedWord = mWordComposer.getTypedWord();
         showSuggestionStrip(suggestedWords, typedWord);
     }
@@ -2162,7 +2172,6 @@
         if (keyboard == null || mSuggest == null) {
             return SuggestedWords.EMPTY;
         }
-        final String typedWord = mWordComposer.getTypedWord();
         // Get the word on which we should search the bigrams. If we are composing a word, it's
         // whatever is *before* the half-committed word in the buffer, hence 2; if we aren't, we
         // should just skip whitespace if any, so 1.
@@ -2170,10 +2179,13 @@
         final String prevWord =
                 mConnection.getNthPreviousWord(mSettings.getCurrent().mWordSeparators,
                 mWordComposer.isComposingWord() ? 2 : 1);
-        final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
-                prevWord, keyboard.getProximityInfo(), mSettings.getCurrent().mCorrectionEnabled,
-                sessionId);
-        return maybeRetrieveOlderSuggestions(typedWord, suggestedWords);
+        return mSuggest.getSuggestedWords(mWordComposer, prevWord, keyboard.getProximityInfo(),
+                mSettings.getCurrent().mCorrectionEnabled, sessionId);
+    }
+
+    private SuggestedWords getSuggestedWordsOrOlderSuggestions(final int sessionId) {
+        return maybeRetrieveOlderSuggestions(mWordComposer.getTypedWord(),
+                getSuggestedWords(sessionId));
     }
 
     private SuggestedWords maybeRetrieveOlderSuggestions(final String typedWord,
@@ -2186,7 +2198,7 @@
         // old suggestions. Also, if we are showing the "add to dictionary" hint, we need to
         // revert to suggestions - although it is unclear how we can come here if it's displayed.
         if (suggestedWords.size() > 1 || typedWord.length() <= 1
-                || suggestedWords.mTypedWordValid
+                || suggestedWords.mTypedWordValid || null == mSuggestionStripView
                 || mSuggestionStripView.isShowingAddToDictionaryHint()) {
             return suggestedWords;
         } else {
@@ -2577,8 +2589,8 @@
     // Outside LatinIME, only used by the {@link InputTestsBase} test suite.
     @UsedForTesting
     void loadKeyboard() {
-        // When the device locale is changed in SetupWizard etc., this method may get called via
-        // onConfigurationChanged before SoftInputWindow is shown.
+        // TODO: Why are we calling {@link #loadSettings()} and {@link #initSuggest()} in a
+        // different order than in {@link #onStartInputView}?
         initSuggest();
         loadSettings();
         if (mKeyboardSwitcher.getMainKeyboardView() != null) {
diff --git a/java/src/com/android/inputmethod/latin/SettingsFragment.java b/java/src/com/android/inputmethod/latin/SettingsFragment.java
index a96c997..79036c2 100644
--- a/java/src/com/android/inputmethod/latin/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/SettingsFragment.java
@@ -77,10 +77,13 @@
         final Resources res = getResources();
         final Context context = getActivity();
 
-        // When we are called from the Settings application but we are not already running, the
-        // {@link SubtypeLocale} class may not have been initialized. It is safe to call
-        // {@link SubtypeLocale#init(Context)} multiple times.
+        // When we are called from the Settings application but we are not already running, some
+        // singleton and utility classes may not have been initialized.  We have to call
+        // initialization method of these classes here. See {@link LatinIME#onCreate()}.
+        SubtypeSwitcher.init(context);
         SubtypeLocale.init(context);
+        AudioAndHapticFeedbackManager.init(context);
+
         mVoicePreference = (ListPreference) findPreference(Settings.PREF_VOICE_MODE);
         mShowCorrectionSuggestionsPreference =
                 (ListPreference) findPreference(Settings.PREF_SHOW_SUGGESTIONS_SETTING);
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 2f9e34f..bef8a3c 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -80,6 +80,7 @@
 
     public static void init(final Context context) {
         SubtypeLocale.init(context);
+        RichInputMethodManager.init(context);
         sInstance.initialize(context);
     }
 
@@ -87,10 +88,13 @@
         // Intentional empty constructor for singleton.
     }
 
-    private void initialize(final Context service) {
-        mResources = service.getResources();
+    private void initialize(final Context context) {
+        if (mResources != null) {
+            return;
+        }
+        mResources = context.getResources();
         mRichImm = RichInputMethodManager.getInstance();
-        mConnectivityManager = (ConnectivityManager) service.getSystemService(
+        mConnectivityManager = (ConnectivityManager) context.getSystemService(
                 Context.CONNECTIVITY_SERVICE);
         mNoLanguageSubtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
                 SubtypeLocale.NO_LANGUAGE, SubtypeLocale.QWERTY);
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 671d714..59d0207 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -68,7 +68,7 @@
     private float mAutoCorrectionThreshold;
 
     // Locale used for upper- and title-casing words
-    private final Locale mLocale;
+    public final Locale mLocale;
 
     public Suggest(final Context context, final Locale locale,
             final SuggestInitializationListener listener) {
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
index 15d0bac..a7a4171 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
@@ -17,11 +17,12 @@
 package com.android.inputmethod.latin.setup;
 
 import android.app.Activity;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
+import android.media.MediaPlayer;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Message;
 import android.provider.Settings;
@@ -29,6 +30,7 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.TextView;
+import android.widget.VideoView;
 
 import com.android.inputmethod.compat.TextViewCompatUtils;
 import com.android.inputmethod.compat.ViewCompatUtils;
@@ -40,14 +42,23 @@
 
 import java.util.HashMap;
 
-public final class SetupActivity extends Activity {
+// TODO: Use Fragment to implement welcome screen and setup steps.
+public final class SetupActivity extends Activity implements View.OnClickListener {
+    private View mWelcomeScreen;
+    private View mSetupScreen;
     private SetupStepIndicatorView mStepIndicatorView;
-    private final SetupStepGroup mSetupSteps = new SetupStepGroup();
+    private Uri mWelcomeVideoUri;
+    private VideoView mWelcomeVideoView;
+    private View mActionStart;
+    private TextView mActionFinish;
+    private final SetupStepGroup mSetupStepGroup = new SetupStepGroup();
     private static final String STATE_STEP = "step";
     private int mStepNumber;
+    private static final int STEP_0 = 0;
     private static final int STEP_1 = 1;
     private static final int STEP_2 = 2;
     private static final int STEP_3 = 3;
+    private boolean mWasLanguageAndInputSettingsInvoked;
 
     private final SettingsPoolingHandler mHandler = new SettingsPoolingHandler(this);
 
@@ -109,17 +120,21 @@
             return;
         }
 
-        // TODO: Use sans-serif-thin font family depending on the system locale white list and
-        // the SDK version.
-        final TextView titleView = (TextView)findViewById(R.id.setup_title);
-        final int appName = getApplicationInfo().labelRes;
-        titleView.setText(getString(R.string.setup_title, getString(appName)));
+        final String applicationName = getResources().getString(getApplicationInfo().labelRes);
+        mWelcomeScreen = findViewById(R.id.setup_welcome_screen);
+        final TextView welcomeTitle = (TextView)findViewById(R.id.setup_welcome_title);
+        welcomeTitle.setText(getString(R.string.setup_welcome_title, applicationName));
+
+        mSetupScreen = findViewById(R.id.setup_steps_screen);
+        final TextView stepsTitle = (TextView)findViewById(R.id.setup_title);
+        stepsTitle.setText(getString(R.string.setup_steps_title, applicationName));
 
         mStepIndicatorView = (SetupStepIndicatorView)findViewById(R.id.setup_step_indicator);
 
-        final SetupStep step1 = new SetupStep(findViewById(R.id.setup_step1),
-                appName, R.string.setup_step1_title, R.string.setup_step1_instruction,
-                R.drawable.ic_settings_language, R.string.language_settings);
+        final SetupStep step1 = new SetupStep(applicationName,
+                (TextView)findViewById(R.id.setup_step1_bullet), findViewById(R.id.setup_step1),
+                R.string.setup_step1_title, R.string.setup_step1_instruction,
+                R.drawable.ic_setup_step1, R.string.setup_step1_action);
         step1.setAction(new Runnable() {
             @Override
             public void run() {
@@ -127,11 +142,12 @@
                 mHandler.startPollingImeSettings();
             }
         });
-        mSetupSteps.addStep(STEP_1, step1);
+        mSetupStepGroup.addStep(STEP_1, step1);
 
-        final SetupStep step2 = new SetupStep(findViewById(R.id.setup_step2),
-                appName, R.string.setup_step2_title, R.string.setup_step2_instruction,
-                0 /* actionIcon */, R.string.select_input_method);
+        final SetupStep step2 = new SetupStep(applicationName,
+                (TextView)findViewById(R.id.setup_step2_bullet), findViewById(R.id.setup_step2),
+                R.string.setup_step2_title, R.string.setup_step2_instruction,
+                R.drawable.ic_setup_step2, R.string.setup_step2_action);
         step2.setAction(new Runnable() {
             @Override
             public void run() {
@@ -140,18 +156,52 @@
                         .showInputMethodPicker();
             }
         });
-        mSetupSteps.addStep(STEP_2, step2);
+        mSetupStepGroup.addStep(STEP_2, step2);
 
-        final SetupStep step3 = new SetupStep(findViewById(R.id.setup_step3),
-                appName, R.string.setup_step3_title, 0 /* instruction */,
-                R.drawable.sym_keyboard_language_switch, R.string.setup_step3_instruction);
+        final SetupStep step3 = new SetupStep(applicationName,
+                (TextView)findViewById(R.id.setup_step3_bullet), findViewById(R.id.setup_step3),
+                R.string.setup_step3_title, R.string.setup_step3_instruction,
+                R.drawable.ic_setup_step3, R.string.setup_step3_action);
         step3.setAction(new Runnable() {
             @Override
             public void run() {
                 invokeSubtypeEnablerOfThisIme();
             }
         });
-        mSetupSteps.addStep(STEP_3, step3);
+        mSetupStepGroup.addStep(STEP_3, step3);
+
+        mWelcomeVideoUri = new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+                .authority(getPackageName())
+                .path(Integer.toString(R.raw.setup_welcome_video))
+                .build();
+        mWelcomeVideoView = (VideoView)findViewById(R.id.setup_welcome_video);
+        mWelcomeVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+            @Override
+            public void onCompletion(final MediaPlayer mp) {
+                mp.start();
+            }
+        });
+
+        mActionStart = findViewById(R.id.setup_start_label);
+        mActionStart.setOnClickListener(this);
+        mActionFinish = (TextView)findViewById(R.id.setup_finish);
+        TextViewCompatUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(mActionFinish,
+                getResources().getDrawable(R.drawable.ic_setup_finish), null, null, null);
+        mActionFinish.setOnClickListener(this);
+    }
+
+    @Override
+    public void onClick(final View v) {
+        if (v == mActionStart) {
+            mStepNumber = STEP_1;
+            updateSetupStepView();
+            return;
+        }
+        if (v == mActionFinish) {
+            finish();
+            return;
+        }
     }
 
     private void invokeSetupWizardOfThisIme() {
@@ -166,7 +216,8 @@
         final Intent intent = new Intent();
         intent.setClass(this, SettingsActivity.class);
         intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
-                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP
+                | Intent.FLAG_ACTIVITY_NO_HISTORY);
         startActivity(intent);
     }
 
@@ -175,6 +226,7 @@
         intent.setAction(Settings.ACTION_INPUT_METHOD_SETTINGS);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         startActivity(intent);
+        mWasLanguageAndInputSettingsInvoked = true;
     }
 
     private void invokeSubtypeEnablerOfThisIme() {
@@ -225,7 +277,7 @@
     private int determineSetupStepNumber() {
         mHandler.cancelPollingImeSettings();
         if (!isThisImeEnabled(this)) {
-            return STEP_1;
+            return mWasLanguageAndInputSettingsInvoked ? STEP_1 : STEP_0;
         }
         if (!isThisImeCurrent(this)) {
             return STEP_2;
@@ -264,6 +316,22 @@
     }
 
     @Override
+    public void onBackPressed() {
+        if (mStepNumber == STEP_1) {
+            mStepNumber = STEP_0;
+            updateSetupStepView();
+            return;
+        }
+        super.onBackPressed();
+    }
+
+    @Override
+    protected void onPause() {
+        mWelcomeVideoView.stopPlayback();
+        super.onPause();
+    }
+
+    @Override
     public void onWindowFocusChanged(final boolean hasFocus) {
         super.onWindowFocusChanged(hasFocus);
         if (!hasFocus) {
@@ -274,10 +342,20 @@
     }
 
     private void updateSetupStepView() {
+        final boolean welcomeScreen = (mStepNumber == STEP_0);
+        mWelcomeScreen.setVisibility(welcomeScreen ? View.VISIBLE : View.GONE);
+        mSetupScreen.setVisibility(welcomeScreen ? View.GONE: View.VISIBLE);
+        if (welcomeScreen) {
+            mWelcomeVideoView.setVideoURI(mWelcomeVideoUri);
+            mWelcomeVideoView.start();
+            return;
+        }
+        mWelcomeVideoView.stopPlayback();
         final int layoutDirection = ViewCompatUtils.getLayoutDirection(mStepIndicatorView);
         mStepIndicatorView.setIndicatorPosition(
-                getIndicatorPosition(mStepNumber, mSetupSteps.getTotalStep(), layoutDirection));
-        mSetupSteps.enableStep(mStepNumber);
+                getIndicatorPosition(mStepNumber, mSetupStepGroup.getTotalStep(), layoutDirection));
+        mSetupStepGroup.enableStep(mStepNumber);
+        mActionFinish.setVisibility((mStepNumber == STEP_3) ? View.VISIBLE : View.GONE);
     }
 
     private static float getIndicatorPosition(final int step, final int totalStep,
@@ -287,20 +365,26 @@
     }
 
     static final class SetupStep implements View.OnClickListener {
-        private final View mRootView;
+        private final View mStepView;
+        private final TextView mBulletView;
+        private final int mActivatedColor;
+        private final int mDeactivatedColor;
         private final TextView mActionLabel;
         private Runnable mAction;
 
-        public SetupStep(final View rootView, final int appName, final int title,
-                final int instruction, final int actionIcon, final int actionLabel) {
-            mRootView = rootView;
-            final Resources res = rootView.getResources();
-            final String applicationName = res.getString(appName);
+        public SetupStep(final String applicationName, final TextView bulletView,
+                final View stepView, final int title, final int instruction, final int actionIcon,
+                final int actionLabel) {
+            mStepView = stepView;
+            mBulletView = bulletView;
+            final Resources res = stepView.getResources();
+            mActivatedColor = res.getColor(R.color.setup_text_action);
+            mDeactivatedColor = res.getColor(R.color.setup_text_dark);
 
-            final TextView titleView = (TextView)rootView.findViewById(R.id.setup_step_title);
+            final TextView titleView = (TextView)mStepView.findViewById(R.id.setup_step_title);
             titleView.setText(res.getString(title, applicationName));
 
-            final TextView instructionView = (TextView)rootView.findViewById(
+            final TextView instructionView = (TextView)mStepView.findViewById(
                     R.id.setup_step_instruction);
             if (instruction == 0) {
                 instructionView.setVisibility(View.GONE);
@@ -308,23 +392,20 @@
                 instructionView.setText(res.getString(instruction, applicationName));
             }
 
-            mActionLabel = (TextView)rootView.findViewById(R.id.setup_step_action_label);
+            mActionLabel = (TextView)mStepView.findViewById(R.id.setup_step_action_label);
             mActionLabel.setText(res.getString(actionLabel));
             if (actionIcon == 0) {
                 final int paddingEnd = ViewCompatUtils.getPaddingEnd(mActionLabel);
                 ViewCompatUtils.setPaddingRelative(mActionLabel, paddingEnd, 0, paddingEnd, 0);
             } else {
-                final int overrideColor = res.getColor(R.color.setup_text_action);
-                final Drawable icon = res.getDrawable(actionIcon);
-                icon.setColorFilter(overrideColor, PorterDuff.Mode.MULTIPLY);
-                icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
-                TextViewCompatUtils.setCompoundDrawablesRelative(
-                        mActionLabel, icon, null, null, null);
+                TextViewCompatUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(
+                        mActionLabel, res.getDrawable(actionIcon), null, null, null);
             }
         }
 
         public void setEnabled(final boolean enabled) {
-            mRootView.setVisibility(enabled ? View.VISIBLE : View.GONE);
+            mStepView.setVisibility(enabled ? View.VISIBLE : View.GONE);
+            mBulletView.setTextColor(enabled ? mActivatedColor : mDeactivatedColor);
         }
 
         public void setAction(final Runnable action) {
@@ -334,8 +415,9 @@
 
         @Override
         public void onClick(final View v) {
-            if (mAction != null) {
+            if (v == mActionLabel && mAction != null) {
                 mAction.run();
+                return;
             }
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java b/java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java
new file mode 100644
index 0000000..ca974f6
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package com.android.inputmethod.latin.setup;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.inputmethod.compat.ViewCompatUtils;
+import com.android.inputmethod.latin.R;
+
+public final class SetupStartIndicatorView extends LinearLayout {
+    public SetupStartIndicatorView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        setOrientation(HORIZONTAL);
+        LayoutInflater.from(context).inflate(R.layout.setup_start_indicator_label, this);
+
+        final LabelView labelView = (LabelView)findViewById(R.id.setup_start_label);
+        labelView.setIndicatorView(findViewById(R.id.setup_start_indicator));
+    }
+
+    public static final class LabelView extends TextView {
+        private View mIndicatorView;
+
+        public LabelView(final Context context, final AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        public void setIndicatorView(final View indicatorView) {
+            mIndicatorView = indicatorView;
+        }
+
+        @Override
+        public void setPressed(final boolean pressed) {
+            super.setPressed(pressed);
+            if (mIndicatorView != null) {
+                mIndicatorView.setPressed(pressed);
+            }
+        }
+    }
+
+    public static final class IndicatorView extends View {
+        private final Path mIndicatorPath = new Path();
+        private final Paint mIndicatorPaint = new Paint();
+        private final ColorStateList mIndicatorColor;
+
+        public IndicatorView(final Context context, final AttributeSet attrs) {
+            super(context, attrs);
+            mIndicatorColor = getResources().getColorStateList(
+                    R.color.setup_step_action_background);
+            mIndicatorPaint.setStyle(Paint.Style.FILL);
+        }
+
+        @Override
+        public void setPressed(final boolean pressed) {
+            super.setPressed(pressed);
+            invalidate();
+        }
+
+        @Override
+        protected void onDraw(final Canvas canvas) {
+            super.onDraw(canvas);
+            final int layoutDirection = ViewCompatUtils.getLayoutDirection(this);
+            final int width = getWidth();
+            final int height = getHeight();
+            final float halfHeight = height / 2.0f;
+            final Path path = mIndicatorPath;
+            path.rewind();
+            if (layoutDirection == ViewCompatUtils.LAYOUT_DIRECTION_RTL) {
+                // Left arrow
+                path.moveTo(width, 0.0f);
+                path.lineTo(0.0f, halfHeight);
+                path.lineTo(width, height);
+            } else { // LAYOUT_DIRECTION_LTR
+                // Right arrow
+                path.moveTo(0.0f, 0.0f);
+                path.lineTo(width, halfHeight);
+                path.lineTo(0.0f, height);
+            }
+            path.close();
+            final int[] stateSet = getDrawableState();
+            final int color = mIndicatorColor.getColorForState(stateSet, 0);
+            mIndicatorPaint.setColor(color);
+            canvas.drawPath(path, mIndicatorPaint);
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/research/FeedbackFragment.java b/java/src/com/android/inputmethod/research/FeedbackFragment.java
index 39f9c87..a073829 100644
--- a/java/src/com/android/inputmethod/research/FeedbackFragment.java
+++ b/java/src/com/android/inputmethod/research/FeedbackFragment.java
@@ -65,12 +65,10 @@
         mCancelButton.setOnClickListener(this);
 
         if (savedInstanceState != null) {
-            Log.d(TAG, "restoring from savedInstanceState");
             restoreState(savedInstanceState);
         } else {
             final Bundle bundle = getActivity().getIntent().getExtras();
             if (bundle != null) {
-                Log.d(TAG, "restoring from getArguments()");
                 restoreState(bundle);
             }
         }
@@ -81,10 +79,7 @@
     public void onClick(final View view) {
         final ResearchLogger researchLogger = ResearchLogger.getInstance();
         if (view == mIncludingUserRecordingCheckBox) {
-            if (hasUserRecording()) {
-                // Remove the recording
-                setHasUserRecording(false);
-            } else {
+            if (mIncludingUserRecordingCheckBox.isChecked()) {
                 final Bundle bundle = new Bundle();
                 onSaveInstanceState(bundle);
 
@@ -103,9 +98,9 @@
                         R.string.research_feedback_empty_feedback_error_message,
                         Toast.LENGTH_LONG).show();
             } else {
-                final boolean isIncludingAccountName = isIncludingAccountName();
-                researchLogger.sendFeedback(feedbackContents,
-                        false /* isIncludingHistory */, isIncludingAccountName, hasUserRecording());
+                final boolean isIncludingAccountName = mIncludingAccountNameCheckBox.isChecked();
+                researchLogger.sendFeedback(feedbackContents, false /* isIncludingHistory */,
+                        isIncludingAccountName, mIncludingUserRecordingCheckBox.isChecked());
                 getActivity().finish();
                 researchLogger.setFeedbackDialogBundle(null);
                 researchLogger.onLeavingSendFeedbackDialog();
@@ -125,29 +120,13 @@
         final String savedFeedbackString = mEditText.getText().toString();
 
         bundle.putString(KEY_FEEDBACK_STRING, savedFeedbackString);
-        bundle.putBoolean(KEY_INCLUDE_ACCOUNT_NAME, isIncludingAccountName());
-        bundle.putBoolean(KEY_HAS_USER_RECORDING, hasUserRecording());
+        bundle.putBoolean(KEY_INCLUDE_ACCOUNT_NAME, mIncludingAccountNameCheckBox.isChecked());
+        bundle.putBoolean(KEY_HAS_USER_RECORDING, mIncludingUserRecordingCheckBox.isChecked());
     }
 
-    public void restoreState(final Bundle bundle) {
+    private void restoreState(final Bundle bundle) {
         mEditText.setText(bundle.getString(KEY_FEEDBACK_STRING));
-        setIsIncludingAccountName(bundle.getBoolean(KEY_INCLUDE_ACCOUNT_NAME));
-        setHasUserRecording(bundle.getBoolean(KEY_HAS_USER_RECORDING));
-    }
-
-    private boolean hasUserRecording() {
-        return mIncludingUserRecordingCheckBox.isChecked();
-    }
-
-    private void setHasUserRecording(final boolean hasRecording) {
-        mIncludingUserRecordingCheckBox.setChecked(hasRecording);
-    }
-
-    private boolean isIncludingAccountName() {
-        return mIncludingAccountNameCheckBox.isChecked();
-    }
-
-    private void setIsIncludingAccountName(final boolean isIncludingAccountName) {
-        mIncludingAccountNameCheckBox.setChecked(isIncludingAccountName);
+        mIncludingAccountNameCheckBox.setChecked(bundle.getBoolean(KEY_INCLUDE_ACCOUNT_NAME));
+        mIncludingUserRecordingCheckBox.setChecked(bundle.getBoolean(KEY_HAS_USER_RECORDING));
     }
 }
diff --git a/java/src/com/android/inputmethod/research/FixedLogBuffer.java b/java/src/com/android/inputmethod/research/FixedLogBuffer.java
index 78dc595..4249af5 100644
--- a/java/src/com/android/inputmethod/research/FixedLogBuffer.java
+++ b/java/src/com/android/inputmethod/research/FixedLogBuffer.java
@@ -51,38 +51,35 @@
         mNumActualWords = 0;
     }
 
-    protected int getNumActualWords() {
-        return mNumActualWords;
-    }
-
     /**
      * Adds a new LogUnit to the front of the LIFO queue, evicting existing LogUnit's
      * (oldest first) if word capacity is reached.
      */
     @Override
     public void shiftIn(final LogUnit newLogUnit) {
-        if (!newLogUnit.hasWord()) {
-            // This LogUnit isn't a word, so it doesn't count toward the word-limit.
+        if (!newLogUnit.hasOneOrMoreWords()) {
+            // This LogUnit doesn't contain any word, so it doesn't count toward the word-limit.
             super.shiftIn(newLogUnit);
             return;
         }
+        final int numWordsIncoming = newLogUnit.getNumWords();
         if (mNumActualWords >= mWordCapacity) {
             // Give subclass a chance to handle the buffer full condition by shifting out logUnits.
             onBufferFull();
             // If still full, evict.
             if (mNumActualWords >= mWordCapacity) {
-                shiftOutWords(1);
+                shiftOutWords(numWordsIncoming);
             }
         }
         super.shiftIn(newLogUnit);
-        mNumActualWords++; // Must be a word, or we wouldn't be here.
+        mNumActualWords += numWordsIncoming;
     }
 
     @Override
     public LogUnit unshiftIn() {
         final LogUnit logUnit = super.unshiftIn();
-        if (logUnit != null && logUnit.hasWord()) {
-            mNumActualWords--;
+        if (logUnit != null && logUnit.hasOneOrMoreWords()) {
+            mNumActualWords -= logUnit.getNumWords();
         }
         return logUnit;
     }
@@ -113,18 +110,30 @@
     @Override
     public LogUnit shiftOut() {
         final LogUnit logUnit = super.shiftOut();
-        if (logUnit != null && logUnit.hasWord()) {
-            mNumActualWords--;
+        if (logUnit != null && logUnit.hasOneOrMoreWords()) {
+            mNumActualWords -= logUnit.getNumWords();
         }
         return logUnit;
     }
 
-    protected void shiftOutWords(final int numWords) {
-        final int targetNumWords = mNumActualWords - numWords;
-        final LinkedList<LogUnit> logUnits = getLogUnits();
-        while (mNumActualWords > targetNumWords && !logUnits.isEmpty()) {
-            shiftOut();
+    /**
+     * Remove LogUnits from the front of the LogBuffer until {@code numWords} have been removed.
+     *
+     * If there are less than {@code numWords} word-containing {@link LogUnit}s, shifts out
+     * all {@code LogUnit}s in the buffer.
+     *
+     * @param numWords the minimum number of word-containing {@link LogUnit}s to shift out
+     * @return the number of actual {@code LogUnit}s shifted out
+     */
+    protected int shiftOutWords(final int numWords) {
+        int numWordContainingLogUnitsShiftedOut = 0;
+        for (LogUnit logUnit = shiftOut(); logUnit != null
+                && numWordContainingLogUnitsShiftedOut < numWords; logUnit = shiftOut()) {
+            if (logUnit.hasOneOrMoreWords()) {
+                numWordContainingLogUnitsShiftedOut += logUnit.getNumWords();
+            }
         }
+        return numWordContainingLogUnitsShiftedOut;
     }
 
     public void shiftOutAll() {
@@ -136,27 +145,31 @@
     }
 
     /**
-     * Returns a list of {@link LogUnit}s at the front of the buffer that have associated words.  No
-     * more than {@code n} LogUnits will have words associated with them.  If there are not enough
-     * LogUnits in the buffer to meet the word requirement, returns the all LogUnits.
+     * Returns a list of {@link LogUnit}s at the front of the buffer that have words associated with
+     * them.
+     *
+     * There will be no more than {@code n} words in the returned list.  So if 2 words are
+     * requested, and the first LogUnit has 3 words, it is not returned.  If 2 words are requested,
+     * and the first LogUnit has only 1 word, and the next LogUnit 2 words, only the first LogUnit
+     * is returned.  If the first LogUnit has no words associated with it, and the second LogUnit
+     * has three words, then only the first LogUnit (which has no associated words) is returned.  If
+     * there are not enough LogUnits in the buffer to meet the word requirement, then all LogUnits
+     * will be returned.
      *
      * @param n The maximum number of {@link LogUnit}s with words to return.
      * @return The list of the {@link LogUnit}s containing the first n words
      */
     public ArrayList<LogUnit> peekAtFirstNWords(int n) {
         final LinkedList<LogUnit> logUnits = getLogUnits();
-        final int length = logUnits.size();
         // Allocate space for n*2 logUnits.  There will be at least n, one for each word, and
         // there may be additional for punctuation, between-word commands, etc.  This should be
         // enough that reallocation won't be necessary.
-        final ArrayList<LogUnit> list = new ArrayList<LogUnit>(n * 2);
-        for (int i = 0; i < length && n > 0; i++) {
-            final LogUnit logUnit = logUnits.get(i);
-            list.add(logUnit);
-            if (logUnit.hasWord()) {
-                n--;
-            }
+        final ArrayList<LogUnit> resultList = new ArrayList<LogUnit>(n * 2);
+        for (final LogUnit logUnit : logUnits) {
+            n -= logUnit.getNumWords();
+            if (n < 0) break;
+            resultList.add(logUnit);
         }
-        return list;
+        return resultList;
     }
 }
diff --git a/java/src/com/android/inputmethod/research/LogUnit.java b/java/src/com/android/inputmethod/research/LogUnit.java
index 1c01675..4d60bda 100644
--- a/java/src/com/android/inputmethod/research/LogUnit.java
+++ b/java/src/com/android/inputmethod/research/LogUnit.java
@@ -25,10 +25,10 @@
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.define.ProductionFlag;
 
-import java.io.IOException;
-import java.io.StringWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.regex.Pattern;
 
 /**
  * A group of log statements related to each other.
@@ -49,27 +49,45 @@
     private static final boolean DEBUG = false
             && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
 
+    private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+");
+    private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
     private final ArrayList<LogStatement> mLogStatementList;
     private final ArrayList<Object[]> mValuesList;
     // Assume that mTimeList is sorted in increasing order.  Do not insert null values into
     // mTimeList.
     private final ArrayList<Long> mTimeList;
-    // Word that this LogUnit generates.  Should be null if the LogUnit does not generate a genuine
-    // word (i.e. separators alone do not count as a word).  Should never be empty.
-    private String mWord;
+    // Words that this LogUnit generates.  Should be null if the data in the LogUnit does not
+    // generate a genuine word (i.e. separators alone do not count as a word).  Should never be
+    // empty.  Note that if the user types spaces explicitly, then normally mWords should contain
+    // only a single word; it will only contain space-separate multiple words if the user does not
+    // enter a space, and the system enters one automatically.
+    private String mWords;
+    private String[] mWordArray = EMPTY_STRING_ARRAY;
     private boolean mMayContainDigit;
     private boolean mIsPartOfMegaword;
     private boolean mContainsCorrection;
 
-    // mCorrectionType indicates whether the word was corrected at all, and if so, whether it was
-    // to a different word or just a "typo" correction.  It is considered a "typo" if the final
-    // word was listed in the suggestions available the first time the word was gestured or
-    // tapped.
+    // mCorrectionType indicates whether the word was corrected at all, and if so, the nature of the
+    // correction.
     private int mCorrectionType;
+    // LogUnits start in this state.  If a word is entered without being corrected, it will have
+    // this CorrectiontType.
     public static final int CORRECTIONTYPE_NO_CORRECTION = 0;
+    // The LogUnit was corrected manually by the user in an unspecified way.
     public static final int CORRECTIONTYPE_CORRECTION = 1;
+    // The LogUnit was corrected manually by the user to a word not in the list of suggestions of
+    // the first word typed here.  (Note: this is a heuristic value, it may be incorrect, for
+    // example, if the user repositions the cursor).
     public static final int CORRECTIONTYPE_DIFFERENT_WORD = 2;
+    // The LogUnit was corrected manually by the user to a word that was in the list of suggestions
+    // of the first word typed here.  (Again, a heuristic).  It is probably a typo correction.
     public static final int CORRECTIONTYPE_TYPO = 3;
+    // TODO: Rather than just tracking the current state, keep a historical record of the LogUnit's
+    // state and statistics.  This should include how many times it has been corrected, whether
+    // other LogUnit edits were done between edits to this LogUnit, etc.  Also track when a LogUnit
+    // previously contained a word, but was corrected to empty (because it was deleted, and there is
+    // no known replacement).
 
     private SuggestedWords mSuggestedWords;
 
@@ -166,7 +184,7 @@
         final LogStatement logStatement;
         if (canIncludePrivateData) {
             LOGSTATEMENT_LOG_UNIT_BEGIN_WITH_PRIVATE_DATA.outputToLocked(jsonWriter,
-                    SystemClock.uptimeMillis(), getWord(), getCorrectionType());
+                    SystemClock.uptimeMillis(), getWordsAsString(), getCorrectionType());
         } else {
             LOGSTATEMENT_LOG_UNIT_BEGIN_WITHOUT_PRIVATE_DATA.outputToLocked(jsonWriter,
                     SystemClock.uptimeMillis());
@@ -181,22 +199,22 @@
     }
 
     /**
-     * Mark the current logUnit as containing data to generate {@code word}.
+     * Mark the current logUnit as containing data to generate {@code newWords}.
      *
      * If {@code setWord()} was previously called for this LogUnit, then the method will try to
      * determine what kind of correction it is, and update its internal state of the correctionType
      * accordingly.
      *
-     * @param word The word this LogUnit generates.  Caller should not pass null or the empty
+     * @param newWords The words this LogUnit generates.  Caller should not pass null or the empty
      * string.
      */
-    public void setWord(final String word) {
-        if (hasWord()) {
+    public void setWords(final String newWords) {
+        if (hasOneOrMoreWords()) {
             // The word was already set once, and it is now being changed.  See if the new word
             // is close to the old word.  If so, then the change is probably a typo correction.
             // If not, the user may have decided to enter a different word, so flag it.
             if (mSuggestedWords != null) {
-                if (isInSuggestedWords(word, mSuggestedWords)) {
+                if (isInSuggestedWords(newWords, mSuggestedWords)) {
                     mCorrectionType = CORRECTIONTYPE_TYPO;
                 } else {
                     mCorrectionType = CORRECTIONTYPE_DIFFERENT_WORD;
@@ -206,38 +224,71 @@
                 // Mark it as a generic correction.
                 mCorrectionType = CORRECTIONTYPE_CORRECTION;
             }
+        } else {
+            mCorrectionType = CORRECTIONTYPE_NO_CORRECTION;
         }
-        mWord = word;
+        mWords = newWords;
+
+        // Update mWordArray
+        mWordArray = (TextUtils.isEmpty(mWords)) ? EMPTY_STRING_ARRAY
+                : WHITESPACE_PATTERN.split(mWords);
+        if (mWordArray.length > 0 && TextUtils.isEmpty(mWordArray[0])) {
+            // Empty string at beginning of array.  Must have been whitespace at the start of the
+            // word.  Remove the empty string.
+            mWordArray = Arrays.copyOfRange(mWordArray, 1, mWordArray.length);
+        }
     }
 
-    public String getWord() {
-        return mWord;
+    public String getWordsAsString() {
+        return mWords;
     }
 
-    public boolean hasWord() {
-        return mWord != null && !TextUtils.isEmpty(mWord.trim());
+    /**
+     * Retuns the words generated by the data in this LogUnit.
+     *
+     * The first word may be an empty string, if the data in the LogUnit started by generating
+     * whitespace.
+     *
+     * @return the array of words. an empty list of there are no words associated with this LogUnit.
+     */
+    public String[] getWordsAsStringArray() {
+        return mWordArray;
     }
 
+    public boolean hasOneOrMoreWords() {
+        return mWordArray.length >= 1;
+    }
+
+    public int getNumWords() {
+        return mWordArray.length;
+    }
+
+    // TODO: Refactor to eliminate getter/setters
     public void setMayContainDigit() {
         mMayContainDigit = true;
     }
 
+    // TODO: Refactor to eliminate getter/setters
     public boolean mayContainDigit() {
         return mMayContainDigit;
     }
 
+    // TODO: Refactor to eliminate getter/setters
     public void setContainsCorrection() {
         mContainsCorrection = true;
     }
 
+    // TODO: Refactor to eliminate getter/setters
     public boolean containsCorrection() {
         return mContainsCorrection;
     }
 
+    // TODO: Refactor to eliminate getter/setters
     public void setCorrectionType(final int correctionType) {
         mCorrectionType = correctionType;
     }
 
+    // TODO: Refactor to eliminate getter/setters
     public int getCorrectionType() {
         return mCorrectionType;
     }
@@ -267,7 +318,7 @@
                         new ArrayList<Object[]>(laterValues),
                         new ArrayList<Long>(laterTimes),
                         true /* isPartOfMegaword */);
-                newLogUnit.mWord = null;
+                newLogUnit.mWords = null;
                 newLogUnit.mMayContainDigit = mMayContainDigit;
                 newLogUnit.mContainsCorrection = mContainsCorrection;
 
@@ -287,9 +338,9 @@
         mLogStatementList.addAll(logUnit.mLogStatementList);
         mValuesList.addAll(logUnit.mValuesList);
         mTimeList.addAll(logUnit.mTimeList);
-        mWord = null;
-        if (logUnit.mWord != null) {
-            setWord(logUnit.mWord);
+        mWords = null;
+        if (logUnit.mWords != null) {
+            setWords(logUnit.mWords);
         }
         mMayContainDigit = mMayContainDigit || logUnit.mMayContainDigit;
         mContainsCorrection = mContainsCorrection || logUnit.mContainsCorrection;
diff --git a/java/src/com/android/inputmethod/research/MainLogBuffer.java b/java/src/com/android/inputmethod/research/MainLogBuffer.java
index 3303d2b..42ef5d3 100644
--- a/java/src/com/android/inputmethod/research/MainLogBuffer.java
+++ b/java/src/com/android/inputmethod/research/MainLogBuffer.java
@@ -25,7 +25,6 @@
 
 import java.util.ArrayList;
 import java.util.LinkedList;
-import java.util.Random;
 
 /**
  * MainLogBuffer is a FixedLogBuffer that tracks the state of LogUnits to make privacy guarantees.
@@ -100,10 +99,6 @@
         return mSuggest.getMainDictionary();
     }
 
-    public void resetWordCounter() {
-        mNumWordsUntilSafeToSample = mNumWordsBetweenNGrams;
-    }
-
     public void setIsStopping() {
         mIsStopping = true;
     }
@@ -131,10 +126,7 @@
             final int length = logUnits.size();
             for (int i = 0; i < length; i++) {
                 final LogUnit logUnit = logUnits.get(i);
-                final String word = logUnit.getWord();
-                if (word != null) {
-                    numWordsInLogUnitList++;
-                }
+                numWordsInLogUnitList += logUnit.getNumWords();
             }
             return numWordsInLogUnitList >= minNGramSize;
         }
@@ -158,29 +150,31 @@
         // the complete buffer contents in detail.
         int numWordsInLogUnitList = 0;
         final int length = logUnits.size();
-        for (int i = 0; i < length; i++) {
-            final LogUnit logUnit = logUnits.get(i);
-            if (!logUnit.hasWord()) {
+        for (final LogUnit logUnit : logUnits) {
+            if (!logUnit.hasOneOrMoreWords()) {
                 // Digits outside words are a privacy threat.
                 if (logUnit.mayContainDigit()) {
                     return false;
                 }
             } else {
-                numWordsInLogUnitList++;
-                final String word = logUnit.getWord();
-                // Words not in the dictionary are a privacy threat.
-                if (ResearchLogger.hasLetters(word) && !(dictionary.isValidWord(word))) {
-                    if (DEBUG) {
-                        Log.d(TAG, "NOT SAFE!: hasLetters: " + ResearchLogger.hasLetters(word)
-                                + ", isValid: " + (dictionary.isValidWord(word)));
+                numWordsInLogUnitList += logUnit.getNumWords();
+                final String[] words = logUnit.getWordsAsStringArray();
+                for (final String word : words) {
+                    // Words not in the dictionary are a privacy threat.
+                    if (ResearchLogger.hasLetters(word) && !(dictionary.isValidWord(word))) {
+                        if (DEBUG) {
+                            Log.d(TAG, "\"" + word + "\" NOT SAFE!: hasLetters: "
+                                    + ResearchLogger.hasLetters(word)
+                                    + ", isValid: " + (dictionary.isValidWord(word)));
+                        }
+                        return false;
                     }
-                    return false;
                 }
             }
         }
 
-        // Finally, only return true if the minNGramSize is met.
-        return numWordsInLogUnitList >= minNGramSize;
+        // Finally, only return true if the ngram is the right size.
+        return numWordsInLogUnitList == minNGramSize;
     }
 
     public void shiftAndPublishAll() {
@@ -201,13 +195,16 @@
             // Good n-gram at the front of the buffer.  Publish it, disclosing details.
             publish(logUnits, true /* canIncludePrivateData */);
             shiftOutWords(N_GRAM_SIZE);
-            resetWordCounter();
+            mNumWordsUntilSafeToSample = mNumWordsBetweenNGrams;
         } else {
-            // No good n-gram at front, and buffer is full.  Shift out the first word (or if there
-            // is none, the existing logUnits).
-            logUnits = peekAtFirstNWords(1);
+            // No good n-gram at front, and buffer is full.  Shift out up through the first logUnit
+            // with associated words (or if there is none, all the existing logUnits).
+            logUnits.clear();
+            for (LogUnit logUnit = shiftOut(); logUnit != null && !logUnit.hasOneOrMoreWords();
+                    logUnit = shiftOut()) {
+                logUnits.add(logUnit);
+            }
             publish(logUnits, false /* canIncludePrivateData */);
-            shiftOutWords(1);
         }
     }
 
@@ -224,13 +221,13 @@
             final boolean canIncludePrivateData);
 
     @Override
-    protected void shiftOutWords(final int numWords) {
-        final int oldNumActualWords = getNumActualWords();
-        super.shiftOutWords(numWords);
-        final int numWordsShifted = oldNumActualWords - getNumActualWords();
-        mNumWordsUntilSafeToSample -= numWordsShifted;
+    protected int shiftOutWords(final int numWords) {
+        final int numWordContainingLogUnitsShiftedOut = super.shiftOutWords(numWords);
+        mNumWordsUntilSafeToSample = Math.max(0, mNumWordsUntilSafeToSample
+                - numWordContainingLogUnitsShiftedOut);
         if (DEBUG) {
             Log.d(TAG, "wordsUntilSafeToSample now at " + mNumWordsUntilSafeToSample);
         }
+        return numWordContainingLogUnitsShiftedOut;
     }
 }
diff --git a/java/src/com/android/inputmethod/research/ResearchLog.java b/java/src/com/android/inputmethod/research/ResearchLog.java
index 35a491f..18bf7ba 100644
--- a/java/src/com/android/inputmethod/research/ResearchLog.java
+++ b/java/src/com/android/inputmethod/research/ResearchLog.java
@@ -108,10 +108,14 @@
             @Override
             public Object call() throws Exception {
                 try {
-                    if (mHasWrittenData) {
-                        mJsonWriter.endArray();
-                        mHasWrittenData = false;
+                    // TODO: This is necessary to avoid an exception.  Better would be to not even
+                    // open the JsonWriter if the file is not even opened unless there is valid data
+                    // to write.
+                    if (!mHasWrittenData) {
+                        mJsonWriter.beginArray();
                     }
+                    mJsonWriter.endArray();
+                    mHasWrittenData = false;
                     mJsonWriter.flush();
                     mJsonWriter.close();
                     if (DEBUG) {
@@ -159,6 +163,12 @@
             public Object call() throws Exception {
                 try {
                     if (mHasWrittenData) {
+                        // TODO: This is necessary to avoid an exception.  Better would be to not
+                        // even open the JsonWriter if the file is not even opened unless there is
+                        // valid data to write.
+                        if (!mHasWrittenData) {
+                            mJsonWriter.beginArray();
+                        }
                         mJsonWriter.endArray();
                         mJsonWriter.close();
                         mHasWrittenData = false;
diff --git a/java/src/com/android/inputmethod/research/ResearchLogDirectory.java b/java/src/com/android/inputmethod/research/ResearchLogDirectory.java
index 291dea5..d156068 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogDirectory.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogDirectory.java
@@ -97,15 +97,17 @@
         }
     }
 
-    public File getLogFilePath(final long time) {
-        return new File(mFilesDir, getUniqueFilename(LOG_FILENAME_PREFIX, time));
+    public File getLogFilePath(final long time, final long nanoTime) {
+        return new File(mFilesDir, getUniqueFilename(LOG_FILENAME_PREFIX, time, nanoTime));
     }
 
-    public File getUserRecordingFilePath(final long time) {
-        return new File(mFilesDir, getUniqueFilename(USER_RECORDING_FILENAME_PREFIX, time));
+    public File getUserRecordingFilePath(final long time, final long nanoTime) {
+        return new File(mFilesDir, getUniqueFilename(USER_RECORDING_FILENAME_PREFIX, time,
+                nanoTime));
     }
 
-    private static String getUniqueFilename(final String prefix, final long time) {
-        return prefix + "-" + time + FILENAME_SUFFIX;
+    private static String getUniqueFilename(final String prefix, final long time,
+            final long nanoTime) {
+        return prefix + "-" + time + "-" + nanoTime + FILENAME_SUFFIX;
     }
 }
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index 7a23ddb..1f6845c 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -389,7 +389,7 @@
         }
         if (mMainLogBuffer == null) {
             mMainResearchLog = new ResearchLog(mResearchLogDirectory.getLogFilePath(
-                    System.currentTimeMillis()), mLatinIME);
+                    System.currentTimeMillis(), System.nanoTime()), mLatinIME);
             final int numWordsToIgnore = new Random().nextInt(NUMBER_OF_WORDS_BETWEEN_SAMPLES + 1);
             mMainLogBuffer = new MainLogBuffer(NUMBER_OF_WORDS_BETWEEN_SAMPLES, numWordsToIgnore,
                     mSuggest) {
@@ -397,13 +397,14 @@
                 protected void publish(final ArrayList<LogUnit> logUnits,
                         boolean canIncludePrivateData) {
                     canIncludePrivateData |= IS_LOGGING_EVERYTHING;
-                    final int length = logUnits.size();
-                    for (int i = 0; i < length; i++) {
-                        final LogUnit logUnit = logUnits.get(i);
-                        final String word = logUnit.getWord();
-                        if (word != null && word.length() > 0 && hasLetters(word)) {
-                            Log.d(TAG, "onPublish: " + word + ", hc: "
-                                    + logUnit.containsCorrection());
+                    for (final LogUnit logUnit : logUnits) {
+                        if (DEBUG) {
+                            final String wordsString = logUnit.getWordsAsString();
+                            Log.d(TAG, "onPublish: '" + wordsString
+                                    + "', hc: " + logUnit.containsCorrection()
+                                    + ", cipd: " + canIncludePrivateData);
+                        }
+                        for (final String word : logUnit.getWordsAsStringArray()) {
                             final Dictionary dictionary = getDictionary();
                             mStatistics.recordWordEntered(
                                     dictionary != null && dictionary.isValidWord(word),
@@ -420,7 +421,7 @@
 
     private void resetFeedbackLogging() {
         mFeedbackLog = new ResearchLog(mResearchLogDirectory.getLogFilePath(
-                System.currentTimeMillis()), mLatinIME);
+                System.currentTimeMillis(), System.nanoTime()), mLatinIME);
         mFeedbackLogBuffer = new FixedLogBuffer(FEEDBACK_WORD_BUFFER_SIZE);
     }
 
@@ -545,7 +546,7 @@
             mUserRecordingLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
         }
         mUserRecordingFile = mResearchLogDirectory.getUserRecordingFilePath(
-                System.currentTimeMillis());
+                System.currentTimeMillis(), System.nanoTime());
         mUserRecordingLog = new ResearchLog(mUserRecordingFile, mLatinIME);
         mUserRecordingLogBuffer = new LogBuffer();
         resetRecordingTimer();
@@ -813,7 +814,7 @@
                 // enabled.  The dot is actually a zero-width, zero-height rectangle, placed at the
                 // lower-right corner of the canvas, painted with a non-zero border width.
                 paint.setStrokeWidth(3);
-                canvas.drawRect(width, height, width, height, paint);
+                canvas.drawRect(width - 1, height - 1, width, height, paint);
             }
             paint.setColor(savedColor);
             paint.setStyle(savedStyle);
@@ -852,8 +853,8 @@
 
     /* package for test */ void commitCurrentLogUnit() {
         if (DEBUG) {
-            Log.d(TAG, "commitCurrentLogUnit" + (mCurrentLogUnit.hasWord() ?
-                    ": " + mCurrentLogUnit.getWord() : ""));
+            Log.d(TAG, "commitCurrentLogUnit" + (mCurrentLogUnit.hasOneOrMoreWords() ?
+                    ": " + mCurrentLogUnit.getWordsAsString() : ""));
         }
         if (!mCurrentLogUnit.isEmpty()) {
             if (mMainLogBuffer != null) {
@@ -893,8 +894,8 @@
 
         // Check that expected word matches.
         if (oldLogUnit != null) {
-            final String oldLogUnitWord = oldLogUnit.getWord();
-            if (!oldLogUnitWord.equals(expectedWord)) {
+            final String oldLogUnitWords = oldLogUnit.getWordsAsString();
+            if (oldLogUnitWords != null && !oldLogUnitWords.equals(expectedWord)) {
                 return;
             }
         }
@@ -916,7 +917,8 @@
         enqueueEvent(LOGSTATEMENT_UNCOMMIT_CURRENT_LOGUNIT);
         if (DEBUG) {
             Log.d(TAG, "uncommitCurrentLogUnit (dump=" + dumpCurrentLogUnit + ") back to "
-                    + (mCurrentLogUnit.hasWord() ? ": '" + mCurrentLogUnit.getWord() + "'" : ""));
+                    + (mCurrentLogUnit.hasOneOrMoreWords() ? ": '"
+                        + mCurrentLogUnit.getWordsAsString() + "'" : ""));
         }
     }
 
@@ -950,8 +952,9 @@
         }
         for (LogUnit logUnit : logUnits) {
             if (DEBUG) {
-                Log.d(TAG, "publishLogBuffer: " + (logUnit.hasWord() ? logUnit.getWord()
-                        : "<wordless>") + ", correction?: " + logUnit.containsCorrection());
+                Log.d(TAG, "publishLogBuffer: " + (logUnit.hasOneOrMoreWords()
+                        ? logUnit.getWordsAsString() : "<wordless>")
+                        + ", correction?: " + logUnit.containsCorrection());
             }
             researchLog.publish(logUnit, canIncludePrivateData);
         }
@@ -986,7 +989,7 @@
             return;
         }
         if (word.length() > 0 && hasLetters(word)) {
-            mCurrentLogUnit.setWord(word);
+            mCurrentLogUnit.setWords(word);
         }
         final LogUnit newLogUnit = mCurrentLogUnit.splitByTime(maxTime);
         enqueueCommitText(word, isBatchMode);
@@ -1107,7 +1110,7 @@
             packageInfo = mLatinIME.getPackageManager().getPackageInfo(mLatinIME.getPackageName(),
                     0);
             final String versionName = packageInfo.versionName;
-            return !(developerBuildRegex.matcher(versionName).find());
+            return developerBuildRegex.matcher(versionName).find();
         } catch (final NameNotFoundException e) {
             Log.e(TAG, "Could not determine package name", e);
             return false;
@@ -1478,7 +1481,7 @@
         }
         if (originallyTypedWord.length() > 0 && hasLetters(originallyTypedWord)) {
             if (logUnit != null) {
-                logUnit.setWord(originallyTypedWord);
+                logUnit.setWords(originallyTypedWord);
             }
         }
         researchLogger.enqueueEvent(logUnit != null ? logUnit : researchLogger.mCurrentLogUnit,
@@ -1616,7 +1619,7 @@
      * Log a call to LatinIME.commitCurrentAutoCorrection().
      *
      * SystemResponse: The IME has committed an auto-correction.  An auto-correction changes the raw
-     * text input to another word that the user more likely desired to type.
+     * text input to another word (or words) that the user more likely desired to type.
      */
     private static final LogStatement LOGSTATEMENT_LATINIME_COMMITCURRENTAUTOCORRECTION =
             new LogStatement("LatinIMECommitCurrentAutoCorrection", true, true, "typedWord",
@@ -1826,6 +1829,9 @@
     public static void latinIME_onEndBatchInput(final CharSequence enteredText,
             final int enteredWordPos, final SuggestedWords suggestedWords) {
         final ResearchLogger researchLogger = getInstance();
+        if (!TextUtils.isEmpty(enteredText) && hasLetters(enteredText.toString())) {
+            researchLogger.mCurrentLogUnit.setWords(enteredText.toString());
+        }
         researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONENDBATCHINPUT, enteredText,
                 enteredWordPos);
         researchLogger.mCurrentLogUnit.initializeSuggestions(suggestedWords);
diff --git a/java/src/com/android/inputmethod/research/UploaderService.java b/java/src/com/android/inputmethod/research/UploaderService.java
index 6a9717b..d2db349 100644
--- a/java/src/com/android/inputmethod/research/UploaderService.java
+++ b/java/src/com/android/inputmethod/research/UploaderService.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.SystemClock;
 
 import com.android.inputmethod.latin.define.ProductionFlag;
 
@@ -79,28 +80,14 @@
      */
     public static void cancelAndRescheduleUploadingService(final Context context,
             final boolean needsRescheduling) {
-        final PendingIntent pendingIntent = getPendingIntentForService(context);
+        final Intent intent = new Intent(context, UploaderService.class);
+        final PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
         final AlarmManager alarmManager = (AlarmManager) context.getSystemService(
                 Context.ALARM_SERVICE);
-        cancelAnyScheduledServiceAlarm(alarmManager, pendingIntent);
-        if (needsRescheduling) {
-            scheduleServiceAlarm(alarmManager, pendingIntent);
-        }
-    }
-
-    private static PendingIntent getPendingIntentForService(final Context context) {
-        final Intent intent = new Intent(context, UploaderService.class);
-        return PendingIntent.getService(context, 0, intent, 0);
-    }
-
-    private static void cancelAnyScheduledServiceAlarm(final AlarmManager alarmManager,
-            final PendingIntent pendingIntent) {
         alarmManager.cancel(pendingIntent);
-    }
-
-    private static void scheduleServiceAlarm(final AlarmManager alarmManager,
-            final PendingIntent pendingIntent) {
-        alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, UploaderService.RUN_INTERVAL,
-                pendingIntent);
+        if (needsRescheduling) {
+            alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()
+                    + UploaderService.RUN_INTERVAL, pendingIntent);
+        }
     }
 }
diff --git a/native/jni/src/binary_format.h b/native/jni/src/binary_format.h
index 2d2e195..ad16039 100644
--- a/native/jni/src/binary_format.h
+++ b/native/jni/src/binary_format.h
@@ -66,6 +66,7 @@
     static int detectFormat(const uint8_t *const dict);
     static int getHeaderSize(const uint8_t *const dict);
     static int getFlags(const uint8_t *const dict);
+    static bool hasBlacklistedOrNotAWordFlag(const int flags);
     static void readHeaderValue(const uint8_t *const dict, const char *const key, int *outValue,
             const int outValueSize);
     static int readHeaderValueInt(const uint8_t *const dict, const char *const key);
@@ -162,6 +163,10 @@
     }
 }
 
+inline bool BinaryFormat::hasBlacklistedOrNotAWordFlag(const int flags) {
+    return flags & (FLAG_IS_BLACKLISTED | FLAG_IS_NOT_A_WORD);
+}
+
 inline int BinaryFormat::getHeaderSize(const uint8_t *const dict) {
     switch (detectFormat(dict)) {
     case 1:
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index 32faae5..e843254 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -210,8 +210,7 @@
     }
 
     bool isImpossibleBigramWord() const {
-        const int probability = mDicNodeProperties.getProbability();
-        if (probability == 0) {
+        if (mDicNodeProperties.hasBlacklistedOrNotAWordFlag()) {
             return true;
         }
         const int prevWordLen = mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength()
@@ -360,11 +359,6 @@
         return mDicNodeState.mDicNodeStateScoring.getCompoundDistance(languageWeight);
     }
 
-    // Note that "cost" means delta for "distance" that is weighted.
-    float getTotalPrevWordsLanguageCost() const {
-        return mDicNodeState.mDicNodeStateScoring.getTotalPrevWordsLanguageCost();
-    }
-
     // Used to commit input partially
     int getPrevWordNodePos() const {
         return mDicNodeState.mDicNodeStatePrevWord.getPrevWordNodePos();
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_properties.h b/native/jni/src/suggest/core/dicnode/dic_node_properties.h
index 173ef35..63a6b13 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_properties.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_properties.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 
+#include "binary_format.h"
 #include "defines.h"
 
 namespace latinime {
@@ -144,6 +145,10 @@
         return mChildrenCount > 0 || mDepth != mLeavingDepth;
     }
 
+    bool hasBlacklistedOrNotAWordFlag() const {
+        return BinaryFormat::hasBlacklistedOrNotAWordFlag(mFlags);
+    }
+
  private:
     // Caution!!!
     // Use a default copy constructor and an assign operator because shallow copies are ok
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h b/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h
index 8902d31..fd9d610 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h
@@ -31,7 +31,7 @@
               mDigraphIndex(DigraphUtils::NOT_A_DIGRAPH_INDEX),
               mEditCorrectionCount(0), mProximityCorrectionCount(0),
               mNormalizedCompoundDistance(0.0f), mSpatialDistance(0.0f), mLanguageDistance(0.0f),
-              mTotalPrevWordsLanguageCost(0.0f), mRawLength(0.0f) {
+              mRawLength(0.0f) {
     }
 
     virtual ~DicNodeStateScoring() {}
@@ -42,7 +42,6 @@
         mNormalizedCompoundDistance = 0.0f;
         mSpatialDistance = 0.0f;
         mLanguageDistance = 0.0f;
-        mTotalPrevWordsLanguageCost = 0.0f;
         mRawLength = 0.0f;
         mDoubleLetterLevel = NOT_A_DOUBLE_LETTER;
         mDigraphIndex = DigraphUtils::NOT_A_DIGRAPH_INDEX;
@@ -54,7 +53,6 @@
         mNormalizedCompoundDistance = scoring->mNormalizedCompoundDistance;
         mSpatialDistance = scoring->mSpatialDistance;
         mLanguageDistance = scoring->mLanguageDistance;
-        mTotalPrevWordsLanguageCost = scoring->mTotalPrevWordsLanguageCost;
         mRawLength = scoring->mRawLength;
         mDoubleLetterLevel = scoring->mDoubleLetterLevel;
         mDigraphIndex = scoring->mDigraphIndex;
@@ -70,9 +68,6 @@
         if (isProximityCorrection) {
             ++mProximityCorrectionCount;
         }
-        if (languageCost > 0.0f) {
-            setTotalPrevWordsLanguageCost(mTotalPrevWordsLanguageCost + languageCost);
-        }
     }
 
     void addRawLength(const float rawLength) {
@@ -148,10 +143,6 @@
         }
     }
 
-    float getTotalPrevWordsLanguageCost() const {
-        return mTotalPrevWordsLanguageCost;
-    }
-
  private:
     // Caution!!!
     // Use a default copy constructor and an assign operator because shallow copies are ok
@@ -165,7 +156,6 @@
     float mNormalizedCompoundDistance;
     float mSpatialDistance;
     float mLanguageDistance;
-    float mTotalPrevWordsLanguageCost;
     float mRawLength;
 
     AK_FORCE_INLINE void addDistance(float spatialDistance, float languageDistance,
@@ -179,11 +169,6 @@
                     / static_cast<float>(max(1, totalInputIndex));
         }
     }
-
-    //TODO: remove
-    AK_FORCE_INLINE void setTotalPrevWordsLanguageCost(float totalPrevWordsLanguageCost) {
-        mTotalPrevWordsLanguageCost = totalPrevWordsLanguageCost;
-    }
 };
 } // namespace latinime
 #endif // LATINIME_DIC_NODE_STATE_SCORING_H
diff --git a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
index 0fa684f..11ccf17 100644
--- a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
@@ -35,17 +35,17 @@
 const float ScoringParams::INSERTION_COST_SAME_CHAR = 0.526f;
 const float ScoringParams::INSERTION_COST_FIRST_CHAR = 0.563f;
 const float ScoringParams::TRANSPOSITION_COST = 0.494f;
-const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.239f;
+const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.289f;
 const float ScoringParams::ADDITIONAL_PROXIMITY_COST = 0.380f;
 const float ScoringParams::SUBSTITUTION_COST = 0.363f;
-const float ScoringParams::COST_NEW_WORD = 0.054f;
+const float ScoringParams::COST_NEW_WORD = 0.024f;
 const float ScoringParams::COST_NEW_WORD_CAPITALIZED = 0.174f;
 const float ScoringParams::DISTANCE_WEIGHT_LANGUAGE = 1.123f;
 const float ScoringParams::COST_FIRST_LOOKAHEAD = 0.462f;
 const float ScoringParams::COST_LOOKAHEAD = 0.092f;
 const float ScoringParams::HAS_PROXIMITY_TERMINAL_COST = 0.126f;
 const float ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST = 0.056f;
-const float ScoringParams::HAS_MULTI_WORD_TERMINAL_COST = 0.136f;
+const float ScoringParams::HAS_MULTI_WORD_TERMINAL_COST = 0.536f;
 const float ScoringParams::TYPING_BASE_OUTPUT_SCORE = 1.0f;
 const float ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT = 0.1f;
 const float ScoringParams::MAX_NORM_DISTANCE_FOR_EDIT = 0.1f;
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
index 74e4e34..34d25ae 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
@@ -140,7 +140,7 @@
             const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
             hash_map_compat<int, int16_t> *const bigramCacheMap) const {
         return DicNodeUtils::getBigramNodeImprobability(traverseSession->getOffsetDict(),
-                dicNode, bigramCacheMap);
+                dicNode, bigramCacheMap) * ScoringParams::DISTANCE_WEIGHT_LANGUAGE;
     }
 
     float getCompletionCost(const DicTraverseSession *const traverseSession,
@@ -164,13 +164,8 @@
         // because the input word shouldn't be treated as perfect
         const bool isExactMatch = !hasEditCount && !hasMultipleWords
                 && !hasProximityErrors && isSameLength;
-
-        const float totalPrevWordsLanguageCost = dicNode->getTotalPrevWordsLanguageCost();
         const float languageImprobability = isExactMatch ? 0.0f : dicNodeLanguageImprobability;
-        const float languageWeight = ScoringParams::DISTANCE_WEIGHT_LANGUAGE;
-        // TODO: Caveat: The following equation should be:
-        // totalPrevWordsLanguageCost + (languageImprobability * languageWeight);
-        return (totalPrevWordsLanguageCost + languageImprobability) * languageWeight;
+        return languageImprobability * ScoringParams::DISTANCE_WEIGHT_LANGUAGE;
     }
 
     AK_FORCE_INLINE bool needsToNormalizeCompoundDistance() const {
diff --git a/native/jni/src/terminal_attributes.h b/native/jni/src/terminal_attributes.h
index 144ae14..92ef71c 100644
--- a/native/jni/src/terminal_attributes.h
+++ b/native/jni/src/terminal_attributes.h
@@ -72,7 +72,7 @@
     }
 
     bool isBlacklistedOrNotAWord() const {
-        return mFlags & (BinaryFormat::FLAG_IS_BLACKLISTED | BinaryFormat::FLAG_IS_NOT_A_WORD);
+        return BinaryFormat::hasBlacklistedOrNotAWordFlag(mFlags);
     }
 
  private: