Merge "Don't start long press timer while other one is running"
diff --git a/java/res/drawable-hdpi/sym_keyboard_settings_holo_dark.png b/java/res/drawable-hdpi/sym_keyboard_settings_holo_dark.png
index 5af09ad..2ea4a74 100644
--- a/java/res/drawable-hdpi/sym_keyboard_settings_holo_dark.png
+++ b/java/res/drawable-hdpi/sym_keyboard_settings_holo_dark.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_settings_holo_dark.png b/java/res/drawable-mdpi/sym_keyboard_settings_holo_dark.png
index 36c8c96..613f4dc 100644
--- a/java/res/drawable-mdpi/sym_keyboard_settings_holo_dark.png
+++ b/java/res/drawable-mdpi/sym_keyboard_settings_holo_dark.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_settings_holo_dark.png b/java/res/drawable-xhdpi/sym_keyboard_settings_holo_dark.png
index 99ee97d..15a9739 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_settings_holo_dark.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_settings_holo_dark.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/sym_keyboard_settings_holo_dark.png b/java/res/drawable-xxhdpi/sym_keyboard_settings_holo_dark.png
index 7041bb6..bf643e1 100644
--- a/java/res/drawable-xxhdpi/sym_keyboard_settings_holo_dark.png
+++ b/java/res/drawable-xxhdpi/sym_keyboard_settings_holo_dark.png
Binary files differ
diff --git a/java/res/raw/main_de.dict b/java/res/raw/main_de.dict
index 69796bb..c65698d 100644
--- a/java/res/raw/main_de.dict
+++ b/java/res/raw/main_de.dict
Binary files differ
diff --git a/java/res/values-be/bools.xml b/java/res/values-be-rBY/bools.xml
similarity index 100%
rename from java/res/values-be/bools.xml
rename to java/res/values-be-rBY/bools.xml
diff --git a/java/res/values-be/strings-action-keys.xml b/java/res/values-be-rBY/strings-action-keys.xml
similarity index 100%
rename from java/res/values-be/strings-action-keys.xml
rename to java/res/values-be-rBY/strings-action-keys.xml
diff --git a/java/res/values-be/strings-appname.xml b/java/res/values-be/strings-appname.xml
deleted file mode 100644
index 2f9593b..0000000
--- a/java/res/values-be/strings-appname.xml
+++ /dev/null
@@ -1,27 +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">
-    <string name="english_ime_name" msgid="5940510615957428904">"Клавіятура Android (AOSP)"</string>
-    <string name="spell_checker_service_name" msgid="1254221805440242662">"Iнструмент праверкi правапiсу для Android (AOSP)"</string>
-    <string name="english_ime_settings" msgid="5760361067176802794">"Налады клавіятуры Android (AOSP)"</string>
-    <string name="android_spell_checker_settings" msgid="6123949487832861885">"Налады інструмента праверкі правапісу для Android (AOSP)"</string>
-</resources>
diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml
deleted file mode 100644
index c7aac0c..0000000
--- a/java/res/values-be/strings.xml
+++ /dev/null
@@ -1,247 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="english_ime_input_options" msgid="3909945612939668554">"Параметры ўводу"</string>
-    <string name="english_ime_research_log" msgid="8492602295696577851">"Каманды гiсторыя даследаванняў"</string>
-    <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Шукаць імёны кантактаў"</string>
-    <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Модуль праверкі правапісу выкарыстоўвае запісы са спісу кантактаў"</string>
-    <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вібрацыя пры націску клавіш"</string>
-    <string name="sound_on_keypress" msgid="6093592297198243644">"Гук пры націску"</string>
-    <string name="popup_on_keypress" msgid="123894815723512944">"Па націску на клавішы ўсплывае акно"</string>
-    <string name="general_category" msgid="1859088467017573195">"Агульныя"</string>
-    <string name="correction_category" msgid="2236750915056607613">"Выпраўленне тэксту"</string>
-    <string name="gesture_typing_category" msgid="497263612130532630">"Набор жэстамі"</string>
-    <string name="misc_category" msgid="6894192814868233453">"Іншыя параметры"</string>
-    <string name="advanced_settings" msgid="362895144495591463">"Адмысловыя налады"</string>
-    <string name="advanced_settings_summary" msgid="4487980456152830271">"Функцыi для спецыялістаў"</string>
-    <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Перакл. да інш. спос. ув."</string>
-    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Кнопка пераключэння мовы звязана i з iншымi спосабамi ўводу"</string>
-    <string name="show_language_switch_key" msgid="5915478828318774384">"Кнопка пераключэння мовы"</string>
-    <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Паказваць, калі ўключана некалькі моў ўводу"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Iндыкатар слайд-шоу"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Паказаць візуальны сігнал падчас слiзгання клавiш Shift або Symbol"</string>
-    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Затрым. скр. падк. клав."</string>
-    <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Няма затрымкі"</string>
-    <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Па змаўчанні"</string>
-    <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> мс"</string>
-    <!-- no translation found for settings_system_default (6268225104743331821) -->
-    <skip />
-    <string name="use_contacts_dict" msgid="4435317977804180815">"Прапан. імёны кантактаў"</string>
-    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Выкарыстоўваць імёны са спісу кантактаў для прапаноў і выпраўл."</string>
-    <string name="use_double_space_period" msgid="8781529969425082860">"Падвойны iнтэрвал"</string>
-    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Падвойнае нацiсканне на прабел ўстаўляе iнтэрвал з наступным прабелам"</string>
-    <string name="auto_cap" msgid="1719746674854628252">"Аўтаматычна рабіць вялікія літары"</string>
-    <string name="auto_cap_summary" msgid="7934452761022946874">"Пісаць з загалоўнай літары першае слова ў кожным сказе"</string>
-    <string name="edit_personal_dictionary" msgid="3996910038952940420">"Персанальны слоўнік"</string>
-    <string name="configure_dictionaries_title" msgid="4238652338556902049">"Дадатковыя слоўнікі"</string>
-    <string name="main_dictionary" msgid="4798763781818361168">"Асноўны слоўнік"</string>
-    <string name="prefs_show_suggestions" msgid="8026799663445531637">"Паказаць прапановы на выпраўленне"</string>
-    <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Паказваць прапанаваныя словы падчас набору тэксту"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Заўсёды паказваць"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Паказаць у партрэтным рэжыме"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Заўседы хаваць"</string>
-    <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Блакіраваць абразлівыя словы"</string>
-    <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Не прапануйце патэнцыяльна абразлівых слоў"</string>
-    <string name="auto_correction" msgid="7630720885194996950">"Аўтавыпраўленне"</string>
-    <string name="auto_correction_summary" msgid="5625751551134658006">"Прабелы і пунктуацыйныя знакі дазваляюць аўтаматычна выпраўляць памылкова ўведзеныя словы"</string>
-    <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Адключаны"</string>
-    <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Сціплы"</string>
-    <!-- no translation found for auto_correction_threshold_mode_aggressive (7319007299148899623) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_very_aggressive (1853309024129480416) -->
-    <skip />
-    <string name="bigram_prediction" msgid="1084449187723948550">"Падказкi для наступнага слова"</string>
-    <string name="bigram_prediction_summary" msgid="3896362682751109677">"Выкарыстоўваць папярэдняе слова, каб атрымлiваць падказкi"</string>
-    <string name="gesture_input" msgid="826951152254563827">"Уключыць набор жэстамі"</string>
-    <string name="gesture_input_summary" msgid="9180350639305731231">"Уводзьце слова, перасоўваючы палец па літарах"</string>
-    <string name="gesture_preview_trail" msgid="3802333369335722221">"Паказаць след жэста"</string>
-    <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Дынамічны плаваючы прагляд"</string>
-    <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Праглядаць прапанаванае слова падчас жэсту"</string>
-    <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Захаваныя"</string>
-    <string name="spoken_use_headphones" msgid="896961781287283493">"Каб праслухаць паролi, падключыце гарнiтуру."</string>
-    <string name="spoken_current_text_is" msgid="2485723011272583845">"Бягучы тэкст %s"</string>
-    <string name="spoken_no_text_entered" msgid="7479685225597344496">"Тэкст не ўведзены"</string>
-    <!-- no translation found for spoken_auto_correct (8005997889020109763) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct_obscured (6276420476908833791) -->
-    <skip />
-    <string name="spoken_description_unknown" msgid="3197434010402179157">"Клавішны код %d"</string>
-    <string name="spoken_description_shift" msgid="244197883292549308">"Зрух"</string>
-    <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift уключаны (націснiце, каб адключыць)"</string>
-    <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock уключаны (націснiце, каб адключыць)"</string>
-    <string name="spoken_description_delete" msgid="8740376944276199801">"Выдаліць"</string>
-    <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Сімвалы"</string>
-    <string name="spoken_description_to_alpha" msgid="23129338819771807">"Літары"</string>
-    <string name="spoken_description_to_numeric" msgid="591752092685161732">"Лічбы"</string>
-    <string name="spoken_description_settings" msgid="4627462689603838099">"Налады"</string>
-    <string name="spoken_description_tab" msgid="2667716002663482248">"Укладка"</string>
-    <string name="spoken_description_space" msgid="2582521050049860859">"Прабел"</string>
-    <string name="spoken_description_mic" msgid="615536748882611950">"Галасавы ўвод"</string>
-    <string name="spoken_description_smiley" msgid="2256309826200113918">"Смайлік"</string>
-    <string name="spoken_description_return" msgid="8178083177238315647">"Увод"</string>
-    <string name="spoken_description_search" msgid="1247236163755920808">"Пошук"</string>
-    <string name="spoken_description_dot" msgid="40711082435231673">"Кропка"</string>
-    <string name="spoken_description_language_switch" msgid="5507091328222331316">"Пераключыць мову"</string>
-    <string name="spoken_description_action_next" msgid="8636078276664150324">"Далей"</string>
-    <string name="spoken_description_action_previous" msgid="800872415009336208">"Назад"</string>
-    <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift уключаны"</string>
-    <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock уключаны"</string>
-    <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift адключаны"</string>
-    <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Рэжым знакаў"</string>
-    <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Рэжым лiтар"</string>
-    <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Рэжым тэлефона"</string>
-    <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Рэжым тэлефонных знакаў"</string>
-    <string name="announce_keyboard_hidden" msgid="8718927835531429807">"Клавіятура схавана"</string>
-    <string name="announce_keyboard_mode" msgid="4729081055438508321">"Паказана клавiятура ў рэжыме \" <xliff:g id="MODE">%s</xliff:g>\""</string>
-    <string name="keyboard_mode_date" msgid="3137520166817128102">"дата"</string>
-    <string name="keyboard_mode_date_time" msgid="339593358488851072">"дата i час"</string>
-    <string name="keyboard_mode_email" msgid="6216248078128294262">"электронная пошта"</string>
-    <string name="keyboard_mode_im" msgid="1137405089766557048">"абмен паведамленнямі"</string>
-    <string name="keyboard_mode_number" msgid="7991623440699957069">"нумар"</string>
-    <string name="keyboard_mode_phone" msgid="6851627527401433229">"тэлефон"</string>
-    <string name="keyboard_mode_text" msgid="6479436687899701619">"тэкст"</string>
-    <string name="keyboard_mode_time" msgid="4381856885582143277">"час"</string>
-    <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string>
-    <string name="voice_input" msgid="3583258583521397548">"Ключ галасавога ўводу"</string>
-    <string name="configure_input_method" msgid="373356270290742459">"Налада метадаў уводу"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Мовы ўводу"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Адправіць водгук"</string>
-    <string name="select_language" msgid="3693815588777926848">"Мовы ўводу"</string>
-    <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">"Дапамажыце палепшыць гэты рэдактар ​​метаду ўводу, аўтаматычна адпраўляючы статыстыку выкарыстання і справаздачы аб збоях Google."</string>
-    <string name="keyboard_layout" msgid="8451164783510487501">"Тэма клавіятуры"</string>
-    <string name="subtype_en_GB" msgid="88170601942311355">"Англійская (ЗК)"</string>
-    <string name="subtype_en_US" msgid="6160452336634534239">"Англійская (ЗША)"</string>
-    <string name="subtype_es_US" msgid="5583145191430180200">"iспанская (ЗША)"</string>
-    <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Англійская (Вялікабрытанія) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
-    <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Англійская (ЗША) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
-    <string name="subtype_with_layout_es_US" msgid="6261791057007890189">"iспанская (ЗША) ( <xliff:g id="LAYOUT">%s</xliff:g> )"</string>
-    <!-- no translation found for subtype_nepali_traditional (9032247506728040447) -->
-    <skip />
-    <!-- no translation found for subtype_no_language (7137390094240139495) -->
-    <skip />
-    <!-- no translation found for subtype_no_language_qwerty (244337630616742604) -->
-    <skip />
-    <!-- no translation found for subtype_no_language_qwertz (443066912507547976) -->
-    <skip />
-    <!-- no translation found for subtype_no_language_azerty (8144348527575640087) -->
-    <skip />
-    <!-- no translation found for subtype_no_language_dvorak (1564494667584718094) -->
-    <skip />
-    <!-- no translation found for subtype_no_language_colemak (5837418400010302623) -->
-    <skip />
-    <!-- no translation found for subtype_no_language_pcqwerty (5354918232046200018) -->
-    <skip />
-    <!-- no translation found for subtype_emoji (7483586578074549196) -->
-    <skip />
-    <string name="custom_input_styles_title" msgid="8429952441821251512">"Карыстальніцкія стылі ўводу"</string>
-    <string name="add_style" msgid="6163126614514489951">"Дадаць стыль"</string>
-    <string name="add" msgid="8299699805688017798">"Дадаць"</string>
-    <string name="remove" msgid="4486081658752944606">"Выдаліць"</string>
-    <string name="save" msgid="7646738597196767214">"Захаваць"</string>
-    <string name="subtype_locale" msgid="8576443440738143764">"Мова"</string>
-    <string name="keyboard_layout_set" msgid="4309233698194565609">"Раскладка"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Карыстальніцкі метад уводу павінен быць уключаны, перш чым пачаць выкарыстоўваць яго. Жадаеце ўключыць яго зараз?"</string>
-    <string name="enable" msgid="5031294444630523247">"Уключыць"</string>
-    <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_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>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Вылучыце файл слоўніка для ўсталёўкі"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Сапраўды ўсталяваць гэты файл на мове: <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Была памылка"</string>
-    <string name="button_default" msgid="3988017840431881491">"Па змаўчанні"</string>
-    <string name="setup_welcome_title" msgid="6112821709832031715">"Вітаем у прыкладанні <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <string name="setup_welcome_additional_description" msgid="8150252008545768953">"з уводам жэстамі"</string>
-    <string name="setup_start_action" msgid="8936036460897347708">"Пачаць"</string>
-    <string name="setup_next_action" msgid="371821437915144603">"Далей"</string>
-    <string name="setup_steps_title" msgid="6400373034871816182">"Наладка прыкладання <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <string name="setup_step1_title" msgid="3147967630253462315">"Уключыць прыкладанне <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <string name="setup_step1_instruction" msgid="2578631936624637241">"Праверце прыкладанне \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" на сваёй мове і параметры ўводу. Гэта дасць магчымасць дазволіць яму працаваць на вашай прыладзе."</string>
-    <string name="setup_step1_finished_instruction" msgid="10761482004957994">"Прыкладанне <xliff:g id="APPLICATION_NAME">%s</xliff:g> ужо ўключана для вашай мовы і параметраў уводу, так што гэты крок зроблены. Пераходзім да наступнага!"</string>
-    <string name="setup_step1_action" msgid="4366513534999901728">"Уключыць у наладах"</string>
-    <string name="setup_step2_title" msgid="6860725447906690594">"Пераключыцца на прыкладанне <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
-    <string name="setup_step2_instruction" msgid="9141481964870023336">"Выберыце \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" як актыўны метад уводу тэксту."</string>
-    <string name="setup_step2_action" msgid="1660330307159824337">"Пераключэнне метадаў уводу"</string>
-    <string name="setup_step3_title" msgid="3154757183631490281">"Усё гатова!"</string>
-    <string name="setup_step3_instruction" msgid="8025981829605426000">"Цяпер вы можаце ўводзіць ўсе свае любімыя прыкладанні з iмем <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
-    <string name="setup_step3_action" msgid="600879797256942259">"Наладка дадатковых моў"</string>
-    <string name="setup_finish_action" msgid="276559243409465389">"Гатова"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Паказаць значок прыкладання"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Паказаць значок прыкладання ў панэлi запуску"</string>
-    <string name="app_name" msgid="6320102637491234792">"Пастаўшчык слоўніка"</string>
-    <string name="dictionary_provider_name" msgid="3027315045397363079">"Пастаўшчык слоўніка"</string>
-    <string name="dictionary_service_name" msgid="6237472350693511448">"Слоўнік"</string>
-    <string name="download_description" msgid="6014835283119198591">"Інфармацыя абнаўлення слоўніка"</string>
-    <string name="dictionary_settings_title" msgid="8091417676045693313">"Дадатковыя слоўнікі"</string>
-    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Даступны слоўнік"</string>
-    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Налады для слоўнікаў"</string>
-    <string name="user_dictionaries" msgid="3582332055892252845">"Карыстальніцкія слоўнікі"</string>
-    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Карыстацкі слоўнік"</string>
-    <string name="dictionary_available" msgid="4728975345815214218">"Даступны слоўнік"</string>
-    <string name="dictionary_downloading" msgid="2982650524622620983">"Спампоўваецца зараз"</string>
-    <string name="dictionary_installed" msgid="8081558343559342962">"Усталявана"</string>
-    <string name="dictionary_disabled" msgid="8950383219564621762">"Усталявана, адключана"</string>
-    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Праблема падключэння да слоўніка"</string>
-    <string name="no_dictionaries_available" msgid="8039920716566132611">"Слоўнікаў няма"</string>
-    <string name="check_for_updates_now" msgid="8087688440916388581">"Абнавіць"</string>
-    <string name="last_update" msgid="730467549913588780">"Апошняе абнаўленне"</string>
-    <string name="message_updating" msgid="4457761393932375219">"Праверка наяўнасці абнаўленняў"</string>
-    <string name="message_loading" msgid="8689096636874758814">"Загрузка..."</string>
-    <string name="main_dict_description" msgid="3072821352793492143">"Асноўны слоўнік"</string>
-    <string name="cancel" msgid="6830980399865683324">"Адмяніць"</string>
-    <string name="install_dict" msgid="180852772562189365">"Усталяваць"</string>
-    <string name="cancel_download_dict" msgid="7843340278507019303">"Адмена"</string>
-    <string name="delete_dict" msgid="756853268088330054">"Выдаліць"</string>
-    <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Для выбранай мовы на мабільнай прыладзе ёсць слоўнік.&lt;br/&gt; Мы рэкамендуем &lt;b&gt;спампаваць&lt;/b&gt; слоўнік для мовы \"<xliff:g id="LANGUAGE">%1$s</xliff:g>\" для паляпшэння зручнасці набору.&lt;br/&gt; &lt;br/&gt; Спампоўка можа заняць хвіліну або дзве ў 3G-сетках. Калі ў вас няма &lt;b&gt;безлімітнага тарыфнага плану перадачы дадзеных&lt;/b&gt;, могуць прымяняцца дадатковыя плацяжы&lt;br/&gt;. Калі вы не ведаеце дакладна, які ў вас тарыфны план, мы рэкамендуем знайсці падлучэнне да сеткі Wi-Fi, каб пачаць аўтаматычную спампоўку.&lt;br/&gt; &lt;br/&gt; Парада: можна спампоўваць і выдаляць слоўнікі, перайшоўшы ў раздзел &lt;b&gt;Мова і ўвод&lt;/b&gt; у меню &lt;b&gt;Налады&lt;/b&gt; вашай мабільнай прылады."</string>
-    <string name="download_over_metered" msgid="1643065851159409546">"Спампаваць зараз (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>МБ)"</string>
-    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Спампаваць праз Wi-Fi"</string>
-    <string name="dict_available_notification_title" msgid="6514288591959117288">"Слоўнік для мовы \"<xliff:g id="LANGUAGE">%1$s</xliff:g>\""</string>
-    <string name="dict_available_notification_description" msgid="1075194169443163487">"Нацiснiце, каб прагледзець i спампаваць"</string>
-    <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Загрузка: прапановы для мовы \"<xliff:g id="LANGUAGE">%1$s</xliff:g>\" хутка з\'явяцца."</string>
-    <string name="version_text" msgid="2715354215568469385">"Версія <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
-    <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Дадаць"</string>
-    <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Дадаць у слоўнік"</string>
-    <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"Выраз"</string>
-    <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"Дадатковыя параметры"</string>
-    <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"Асн. параметры"</string>
-    <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"OК"</string>
-    <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"Слова:"</string>
-    <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Шлях хуткага доступу:"</string>
-    <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Мова:"</string>
-    <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"Увядзіце слова"</string>
-    <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Дадатковы цэтлiк"</string>
-    <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Рэдагаваць слова"</string>
-    <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Рэдагаваць"</string>
-    <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Выдаліць"</string>
-    <string name="user_dict_settings_empty_text" msgid="558499587532668203">"У вашым карыстальніцкім слоўніку няма ніводнага слова. Вы можаце дадаваць словы, дакранаючыся да кнопкі \"+\" у пункце меню \"Дадаць\"."</string>
-    <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"Для ўсіх моў"</string>
-    <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"Іншыя мовы..."</string>
-    <string name="user_dict_settings_delete" msgid="110413335187193859">"Выдаліць"</string>
-    <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
-</resources>
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 26ceb89..78e771f 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -25,7 +25,7 @@
     af: Afrikaans/qwerty
     ar: Arabic/arabic
     (az: Azerbaijani/qwerty)  # disabled temporarily. waiting for string resources.
-    be: Belarusian/east_slavic
+    be_BY: Belarusian/east_slavic
     bg: Bulgarian/bulgarian
     bg: Bulgarian/bulgarian_bds
     ca: Catalan/spanish
@@ -144,7 +144,7 @@
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x1dc3a859"
-            android:imeSubtypeLocale="be"
+            android:imeSubtypeLocale="be_BY"
             android:imeSubtypeMode="keyboard"
             android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable"
             android:isAsciiCapable="false"
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index 39d2689..f1b5bc1 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -680,8 +680,8 @@
         /* 15 */ "\u011F",
     };
 
-    /* Language be: Belarusian */
-    private static final String[] LANGUAGE_be = {
+    /* Language be_BY: Belarusian (Belarus) */
+    private static final String[] LANGUAGE_be_BY = {
         /* 0~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null,
@@ -1297,8 +1297,8 @@
         /* 125 */ "\u00F1",
     };
 
-    /* Language et: Estonian */
-    private static final String[] LANGUAGE_et = {
+    /* Language et_EE: Estonian (Estonia) */
+    private static final String[] LANGUAGE_et_EE = {
         // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
         // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
         // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
@@ -1803,8 +1803,8 @@
         /* 55 */ "!text/double_raqm_laqm",
     };
 
-    /* Language hy: Armenian */
-    private static final String[] LANGUAGE_hy = {
+    /* Language hy_AM: Armenian (Armenia) */
+    private static final String[] LANGUAGE_hy_AM = {
         /* 0~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
@@ -2015,8 +2015,8 @@
         /* 67 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
     };
 
-    /* Language ka: Georgian */
-    private static final String[] LANGUAGE_ka = {
+    /* Language ka_GE: Georgian (Georgia) */
+    private static final String[] LANGUAGE_ka_GE = {
         /* 0~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
@@ -2082,8 +2082,8 @@
         /* 51 */ "\u0410\u0411\u0412",
     };
 
-    /* Language km: Khmer */
-    private static final String[] LANGUAGE_km = {
+    /* Language km_KH: Khmer (Cambodia) */
+    private static final String[] LANGUAGE_km_KH = {
         /* 0~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
@@ -2145,8 +2145,8 @@
         /* 51 */ "\u0410\u0411\u0412",
     };
 
-    /* Language lo: Lao */
-    private static final String[] LANGUAGE_lo = {
+    /* Language lo_LA: Lao (Laos) */
+    private static final String[] LANGUAGE_lo_LA = {
         /* 0~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
@@ -2389,8 +2389,8 @@
         /* 53 */ "!text/double_9qm_lqm",
     };
 
-    /* Language mn: Mongolian */
-    private static final String[] LANGUAGE_mn = {
+    /* Language mn_MN: Mongolian (Mongolia) */
+    private static final String[] LANGUAGE_mn_MN = {
         /* 0~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
@@ -3521,12 +3521,14 @@
         /* 19 */ "\u0175",
     };
 
+    // TODO: Use the language + "_" + region representation for the locale string key.
+    // Currently we are dropping the region from the key.
     private static final Object[] LANGUAGES_AND_TEXTS = {
         "DEFAULT", LANGUAGE_DEFAULT, /* default */
         "af", LANGUAGE_af, /* Afrikaans */
         "ar", LANGUAGE_ar, /* Arabic */
         "az", LANGUAGE_az, /* Azerbaijani */
-        "be", LANGUAGE_be, /* Belarusian */
+        "be" /* "be_BY" */, LANGUAGE_be_BY, /* Belarusian (Belarus) */
         "bg", LANGUAGE_bg, /* Bulgarian */
         "ca", LANGUAGE_ca, /* Catalan */
         "cs", LANGUAGE_cs, /* Czech */
@@ -3536,26 +3538,26 @@
         "en", LANGUAGE_en, /* English */
         "eo", LANGUAGE_eo, /* Esperanto */
         "es", LANGUAGE_es, /* Spanish */
-        "et", LANGUAGE_et, /* Estonian */
+        "et" /* "et_EE" */, LANGUAGE_et_EE, /* Estonian (Estonia) */
         "fa", LANGUAGE_fa, /* Persian */
         "fi", LANGUAGE_fi, /* Finnish */
         "fr", LANGUAGE_fr, /* French */
         "hi", LANGUAGE_hi, /* Hindi */
         "hr", LANGUAGE_hr, /* Croatian */
         "hu", LANGUAGE_hu, /* Hungarian */
-        "hy", LANGUAGE_hy, /* Armenian */
+        "hy" /* "hy_AM" */, LANGUAGE_hy_AM, /* Armenian (Armenia) */
         "is", LANGUAGE_is, /* Icelandic */
         "it", LANGUAGE_it, /* Italian */
         "iw", LANGUAGE_iw, /* Hebrew */
-        "ka", LANGUAGE_ka, /* Georgian */
+        "ka" /* "ka_GE" */, LANGUAGE_ka_GE, /* Georgian (Georgia) */
         "kk", LANGUAGE_kk, /* Kazakh */
-        "km", LANGUAGE_km, /* Khmer */
+        "km" /* "km_KH" */, LANGUAGE_km_KH, /* Khmer (Cambodia) */
         "ky", LANGUAGE_ky, /* Kirghiz */
-        "lo", LANGUAGE_lo, /* Lao */
+        "lo" /* "lo_LA" */, LANGUAGE_lo_LA, /* Lao (Laos) */
         "lt", LANGUAGE_lt, /* Lithuanian */
         "lv", LANGUAGE_lv, /* Latvian */
         "mk", LANGUAGE_mk, /* Macedonian */
-        "mn", LANGUAGE_mn, /* Mongolian */
+        "mn" /* "mn_MN" */, LANGUAGE_mn_MN, /* Mongolian (Mongolia) */
         "nb", LANGUAGE_nb, /* Norwegian Bokmål */
         "ne", LANGUAGE_ne, /* Nepali */
         "nl", LANGUAGE_nl, /* Dutch */
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index fa79f5a..e0452484 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -52,13 +52,10 @@
     public static final String TYPE_CONTACTS = "contacts";
     // User dictionary, the system-managed one.
     public static final String TYPE_USER = "user";
-    // User history dictionary internal to LatinIME. This assumes bigram prediction for now.
+    // User history dictionary internal to LatinIME.
     public static final String TYPE_USER_HISTORY = "history";
-    // Personalization binary dictionary internal to LatinIME.
+    // Personalization dictionary.
     public static final String TYPE_PERSONALIZATION = "personalization";
-    // Personalization prediction dictionary internal to LatinIME's Java code.
-    public static final String TYPE_PERSONALIZATION_PREDICTION_IN_JAVA =
-            "personalization_prediction_in_java";
     public final String mDictType;
 
     public Dictionary(final String dictType) {
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index f53dc37..5d1c396 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -144,7 +144,7 @@
         return mBinaryDictionary.isValidDictionary();
     }
 
-    protected String getFileNameExtentionToOpenDict() {
+    protected String getFileNameExtensionToOpenDict() {
         return "";
     }
 
@@ -265,7 +265,7 @@
                     // We have 'fileToOpen' in addition to 'file' for the v4 dictionary format
                     // where 'file' is a directory, and 'fileToOpen' is a normal file.
                     final File fileToOpen = new File(mContext.getFilesDir(), mFilename
-                            + getFileNameExtentionToOpenDict());
+                            + getFileNameExtensionToOpenDict());
                     // TODO: Make BinaryDictionary's constructor be able to accept filename
                     // without extension.
                     mBinaryDictionary = new BinaryDictionary(
@@ -521,7 +521,7 @@
         }
 
         final File file = new File(mContext.getFilesDir(), mFilename
-                + getFileNameExtentionToOpenDict());
+                + getFileNameExtensionToOpenDict());
         final String filename = file.getAbsolutePath();
         final long length = file.length();
 
@@ -703,7 +703,7 @@
     /**
      * Generate binary dictionary using DictionaryWriter.
      */
-    protected void asyncFlashAllBinaryDictionary() {
+    protected void asyncFlushBinaryDictionary() {
         final Runnable newTask = new Runnable() {
             @Override
             public void run() {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index b3e7116..6a10131 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -80,7 +80,6 @@
 import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
 import com.android.inputmethod.latin.personalization.PersonalizationDictionarySessionRegister;
 import com.android.inputmethod.latin.personalization.PersonalizationHelper;
-import com.android.inputmethod.latin.personalization.PersonalizationPredictionDictionary;
 import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.settings.SettingsActivity;
@@ -182,7 +181,6 @@
     private boolean mIsMainDictionaryAvailable;
     private UserBinaryDictionary mUserDictionary;
     private UserHistoryDictionary mUserHistoryDictionary;
-    private PersonalizationPredictionDictionary mPersonalizationPredictionDictionary;
     private PersonalizationDictionary mPersonalizationDictionary;
     private boolean mIsUserDictionaryAvailable;
 
@@ -644,17 +642,12 @@
         mIsUserDictionaryAvailable = mUserDictionary.isEnabled();
         newSuggest.setUserDictionary(mUserDictionary);
 
-        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
-
         mUserHistoryDictionary = PersonalizationHelper.getUserHistoryDictionary(
                 this, subtypeLocale);
         newSuggest.setUserHistoryDictionary(mUserHistoryDictionary);
         mPersonalizationDictionary =
                 PersonalizationHelper.getPersonalizationDictionary(this, subtypeLocale);
         newSuggest.setPersonalizationDictionary(mPersonalizationDictionary);
-        mPersonalizationPredictionDictionary =
-                PersonalizationHelper.getPersonalizationPredictionDictionary(this, subtypeLocale);
-        newSuggest.setPersonalizationPredictionDictionary(mPersonalizationPredictionDictionary);
 
         final Suggest oldSuggest = mSuggest;
         resetContactsDictionary(null != oldSuggest ? oldSuggest.getContactsDictionary() : null);
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 53f04b1..0ecb411 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -25,7 +25,6 @@
 import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
-import com.android.inputmethod.latin.personalization.PersonalizationPredictionDictionary;
 import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.utils.AutoCorrectionUtils;
@@ -90,7 +89,6 @@
                 PreferenceManager.getDefaultSharedPreferences(context))) {
             mOnlyDictionarySetForDebug = new HashSet<String>();
             mOnlyDictionarySetForDebug.add(Dictionary.TYPE_PERSONALIZATION);
-            mOnlyDictionarySetForDebug.add(Dictionary.TYPE_PERSONALIZATION_PREDICTION_IN_JAVA);
         }
     }
 
@@ -194,12 +192,6 @@
         addOrReplaceDictionaryInternal(Dictionary.TYPE_USER_HISTORY, userHistoryDictionary);
     }
 
-    public void setPersonalizationPredictionDictionary(
-            final PersonalizationPredictionDictionary personalizationPredictionDictionary) {
-        addOrReplaceDictionaryInternal(Dictionary.TYPE_PERSONALIZATION_PREDICTION_IN_JAVA,
-                personalizationPredictionDictionary);
-    }
-
     public void setPersonalizationDictionary(
             final PersonalizationDictionary personalizationDictionary) {
         addOrReplaceDictionaryInternal(Dictionary.TYPE_PERSONALIZATION,
diff --git a/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java
index b75fc37..bbbb8e4 100644
--- a/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java
@@ -36,27 +36,25 @@
     private static final int ERROR_CANNOT_READ = 1;
     private static final int ERROR_WRONG_FORMAT = 2;
 
-    protected FileHeader readHeader(final DictBuffer dictBuffer)
+    protected FileHeader readHeader(final DictBuffer headerBuffer)
             throws IOException, UnsupportedFormatException {
-        if (dictBuffer == null) {
+        if (headerBuffer == null) {
             openDictBuffer();
         }
 
-        final int version = HeaderReader.readVersion(dictBuffer);
+        final int version = HeaderReader.readVersion(headerBuffer);
         if (version < FormatSpec.MINIMUM_SUPPORTED_VERSION
                 || version > FormatSpec.MAXIMUM_SUPPORTED_VERSION) {
           throw new UnsupportedFormatException("Unsupported version : " + version);
         }
         // TODO: Remove this field.
-        final int optionsFlags = HeaderReader.readOptionFlags(dictBuffer);
-
-        final int headerSize = HeaderReader.readHeaderSize(dictBuffer);
-
+        final int optionsFlags = HeaderReader.readOptionFlags(headerBuffer);
+        final int headerSize = HeaderReader.readHeaderSize(headerBuffer);
         if (headerSize < 0) {
             throw new UnsupportedFormatException("header size can't be negative.");
         }
 
-        final HashMap<String, String> attributes = HeaderReader.readAttributes(dictBuffer,
+        final HashMap<String, String> attributes = HeaderReader.readAttributes(headerBuffer,
                 headerSize);
 
         final FileHeader header = new FileHeader(headerSize,
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
index 17c609f..83ee7d6 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
@@ -600,7 +600,7 @@
 
         Map<Integer, PtNodeArray> reverseNodeArrayMapping = new TreeMap<Integer, PtNodeArray>();
         Map<Integer, PtNode> reversePtNodeMapping = new TreeMap<Integer, PtNode>();
-        final PtNodeArray root = readNodeArray(dictDecoder, fileHeader.mHeaderSize,
+        final PtNodeArray root = readNodeArray(dictDecoder, fileHeader.mBodyOffset,
                 reverseNodeArrayMapping, reversePtNodeMapping, fileHeader.mFormatOptions);
 
         FusionDictionary newDict = new FusionDictionary(root, fileHeader.mDictionaryOptions);
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
index 62d9ad8..86ebf58 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
@@ -62,7 +62,7 @@
      * Retrieves all node arrays without recursive call.
      */
     private static void readUnigramsAndBigramsBinaryInner(final DictDecoder dictDecoder,
-            final int headerSize, final Map<Integer, String> words,
+            final int bodyOffset, final Map<Integer, String> words,
             final Map<Integer, Integer> frequencies,
             final Map<Integer, ArrayList<PendingAttribute>> bigrams,
             final FormatOptions formatOptions) {
@@ -71,7 +71,7 @@
         Stack<Position> stack = new Stack<Position>();
         int index = 0;
 
-        Position initPos = new Position(headerSize, 0);
+        Position initPos = new Position(bodyOffset, 0);
         stack.push(initPos);
 
         while (!stack.empty()) {
@@ -154,7 +154,7 @@
             UnsupportedFormatException {
         // Read header
         final FileHeader header = dictDecoder.readHeader();
-        readUnigramsAndBigramsBinaryInner(dictDecoder, header.mHeaderSize, words,
+        readUnigramsAndBigramsBinaryInner(dictDecoder, header.mBodyOffset, words,
                 frequencies, bigrams, header.mFormatOptions);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
index b81c8d8..846aacf 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
@@ -199,13 +199,19 @@
      */
 
     public static final int MAGIC_NUMBER = 0x9BC13AFE;
-    static final int MINIMUM_SUPPORTED_VERSION = 2;
-    static final int MAXIMUM_SUPPORTED_VERSION = 4;
     static final int NOT_A_VERSION_NUMBER = -1;
     static final int FIRST_VERSION_WITH_DYNAMIC_UPDATE = 3;
     static final int FIRST_VERSION_WITH_TERMINAL_ID = 4;
+
+    // These MUST have the same values as the relevant constants in format_utils.h.
+    // From version 4 on, we use version * 100 + revision as a version number. That allows
+    // us to change the format during development while having testing devices remove
+    // older files with each upgrade, while still having a readable versioning scheme.
+    public static final int VERSION2 = 2;
     public static final int VERSION3 = 3;
-    public static final int VERSION4 = 4;
+    public static final int VERSION4 = 400;
+    static final int MINIMUM_SUPPORTED_VERSION = VERSION2;
+    static final int MAXIMUM_SUPPORTED_VERSION = VERSION4;
 
     // These options need to be the same numeric values as the one in the native reading code.
     static final int GERMAN_UMLAUT_PROCESSING_FLAG = 0x1;
@@ -263,8 +269,10 @@
     static final int PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE = 3;
     static final int PTNODE_SHORTCUT_LIST_SIZE_SIZE = 2;
 
-    // These values are used only by version 4 or later.
-    public static final String TRIE_FILE_EXTENSION = ".trie";
+    // These values are used only by version 4 or later. They MUST match the definitions in
+    // ver4_dict_constants.cpp.
+    static final String TRIE_FILE_EXTENSION = ".trie";
+    public static final String HEADER_FILE_EXTENSION = ".header";
     static final String FREQ_FILE_EXTENSION = ".freq";
     static final String UNIGRAM_TIMESTAMP_FILE_EXTENSION = ".timestamp";
     // tat = Terminal Address Table
@@ -361,7 +369,7 @@
      * Class representing file header.
      */
     public static final class FileHeader {
-        public final int mHeaderSize;
+        public final int mBodyOffset;
         public final DictionaryOptions mDictionaryOptions;
         public final FormatOptions mFormatOptions;
         // Note that these are corresponding definitions in native code in latinime::HeaderPolicy
@@ -377,9 +385,9 @@
         private static final String DICTIONARY_DESCRIPTION_ATTRIBUTE = "description";
         public FileHeader(final int headerSize, final DictionaryOptions dictionaryOptions,
                 final FormatOptions formatOptions) {
-            mHeaderSize = headerSize;
             mDictionaryOptions = dictionaryOptions;
             mFormatOptions = formatOptions;
+            mBodyOffset = formatOptions.mVersion < VERSION4 ? headerSize : 0;
             if (null == getLocaleString()) {
                 throw new RuntimeException("Cannot create a FileHeader without a locale");
             }
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
index 2cbec7c..07522b5 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
@@ -45,10 +45,12 @@
     protected static final int FILETYPE_TERMINAL_ADDRESS_TABLE = 3;
     protected static final int FILETYPE_BIGRAM_FREQ = 4;
     protected static final int FILETYPE_SHORTCUT = 5;
+    protected static final int FILETYPE_HEADER = 6;
 
     protected final File mDictDirectory;
     protected final DictionaryBufferFactory mBufferFactory;
     protected DictBuffer mDictBuffer;
+    protected DictBuffer mHeaderBuffer;
     protected DictBuffer mFrequencyBuffer;
     protected DictBuffer mTerminalAddressTableBuffer;
     private BigramContentReader mBigramReader;
@@ -83,7 +85,7 @@
     @UsedForTesting
     /* package */ Ver4DictDecoder(final File dictDirectory, final int factoryFlag) {
         mDictDirectory = dictDirectory;
-        mDictBuffer = mFrequencyBuffer = null;
+        mDictBuffer = mHeaderBuffer = mFrequencyBuffer = null;
 
         if ((factoryFlag & MASK_DICTBUFFER) == USE_READONLY_BYTEBUFFER) {
             mBufferFactory = new DictionaryBufferFromReadOnlyByteBufferFactory();
@@ -100,13 +102,16 @@
     /* package */ Ver4DictDecoder(final File dictDirectory, final DictionaryBufferFactory factory) {
         mDictDirectory = dictDirectory;
         mBufferFactory = factory;
-        mDictBuffer = mFrequencyBuffer = null;
+        mDictBuffer = mHeaderBuffer = mFrequencyBuffer = null;
     }
 
     protected File getFile(final int fileType) throws UnsupportedFormatException {
         if (fileType == FILETYPE_TRIE) {
             return new File(mDictDirectory,
                     mDictDirectory.getName() + FormatSpec.TRIE_FILE_EXTENSION);
+        } else if (fileType == FILETYPE_HEADER) {
+            return new File(mDictDirectory,
+                    mDictDirectory.getName() + FormatSpec.HEADER_FILE_EXTENSION);
         } else if (fileType == FILETYPE_FREQUENCY) {
             return new File(mDictDirectory,
                     mDictDirectory.getName() + FormatSpec.FREQ_FILE_EXTENSION);
@@ -132,6 +137,7 @@
         if (!mDictDirectory.isDirectory()) {
             throw new UnsupportedFormatException("Format 4 dictionary needs a directory");
         }
+        mHeaderBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_HEADER));
         mDictBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_TRIE));
         mFrequencyBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_FREQUENCY));
         mTerminalAddressTableBuffer = mBufferFactory.getDictionaryBuffer(
@@ -150,16 +156,22 @@
     }
 
     @UsedForTesting
+    /* package */ DictBuffer getHeaderBuffer() {
+        return mHeaderBuffer;
+    }
+
+    @UsedForTesting
     /* package */ DictBuffer getDictBuffer() {
         return mDictBuffer;
     }
 
     @Override
     public FileHeader readHeader() throws IOException, UnsupportedFormatException {
-        if (mDictBuffer == null) {
+        if (mHeaderBuffer == null) {
             openDictBuffer();
         }
-        final FileHeader header = super.readHeader(mDictBuffer);
+        mHeaderBuffer.position(0);
+        final FileHeader header = super.readHeader(mHeaderBuffer);
         final int version = header.mFormatOptions.mVersion;
         if (version != FormatSpec.VERSION4) {
             throw new UnsupportedFormatException("File header has a wrong version : " + version);
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
index 6d045c8..1a245b6 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
@@ -26,6 +26,7 @@
 import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
 import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
 import com.android.inputmethod.latin.utils.CollectionUtils;
+import com.android.inputmethod.latin.utils.FileUtils;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -45,8 +46,8 @@
     private final File mDictPlacedDir;
     private byte[] mTrieBuf;
     private int mTriePos;
-    private int mHeaderSize;
     private OutputStream mTrieOutStream;
+    private OutputStream mHeaderOutStream;
     private OutputStream mFreqOutStream;
     private OutputStream mUnigramTimestampOutStream;
     private OutputStream mTerminalAddressTableOutStream;
@@ -185,16 +186,21 @@
         mBaseFilename = header.getId() + "." + header.getVersion();
         mDictDir = new File(mDictPlacedDir, mBaseFilename);
         final File trieFile = new File(mDictDir, mBaseFilename + FormatSpec.TRIE_FILE_EXTENSION);
+        final File headerFile = new File(mDictDir,
+                mBaseFilename + FormatSpec.HEADER_FILE_EXTENSION);
         final File freqFile = new File(mDictDir, mBaseFilename + FormatSpec.FREQ_FILE_EXTENSION);
         final File timestampFile = new File(mDictDir,
                 mBaseFilename + FormatSpec.UNIGRAM_TIMESTAMP_FILE_EXTENSION);
         final File terminalAddressTableFile = new File(mDictDir,
                 mBaseFilename + FormatSpec.TERMINAL_ADDRESS_TABLE_FILE_EXTENSION);
         if (!mDictDir.isDirectory()) {
-            if (mDictDir.exists()) mDictDir.delete();
+            if (mDictDir.exists()) {
+                FileUtils.deleteRecursively(mDictDir);
+            }
             mDictDir.mkdirs();
         }
         mTrieOutStream = new FileOutputStream(trieFile);
+        mHeaderOutStream = new FileOutputStream(headerFile);
         mFreqOutStream = new FileOutputStream(freqFile);
         mTerminalAddressTableOutStream = new FileOutputStream(terminalAddressTableFile);
         if (formatOptions.mHasTimestamp) {
@@ -207,6 +213,9 @@
             if (mTrieOutStream != null) {
                 mTrieOutStream.close();
             }
+            if (mHeaderOutStream != null) {
+                mHeaderOutStream.close();
+            }
             if (mFreqOutStream != null) {
                 mFreqOutStream.close();
             }
@@ -218,6 +227,7 @@
             }
         } finally {
             mTrieOutStream = null;
+            mHeaderOutStream = null;
             mFreqOutStream = null;
             mTerminalAddressTableOutStream = null;
         }
@@ -238,8 +248,7 @@
             openStreams(formatOptions, dict.mOptions);
         }
 
-        mHeaderSize = BinaryDictEncoderUtils.writeDictionaryHeader(mTrieOutStream, dict,
-                formatOptions);
+        BinaryDictEncoderUtils.writeDictionaryHeader(mHeaderOutStream, dict, formatOptions);
 
         MakedictLog.i("Flattening the tree...");
         ArrayList<PtNodeArray> flatNodes = BinaryDictEncoderUtils.flattenTree(dict.mRootNodeArray);
@@ -423,7 +432,7 @@
                             ptNode.mFrequency, FormatSpec.FREQUENCY_AND_FLAGS_SIZE);
                     BinaryDictEncoderUtils.writeUIntToBuffer(terminalAddressTableBuf,
                             ptNode.mTerminalId * FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE,
-                            ptNode.mCachedAddressAfterUpdate + mHeaderSize,
+                            ptNode.mCachedAddressAfterUpdate,
                             FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE);
                 }
             }
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index f9733f7..386e123 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -27,7 +27,6 @@
 import com.android.inputmethod.latin.makedict.DictDecoder;
 import com.android.inputmethod.latin.makedict.FormatSpec;
 import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
-import com.android.inputmethod.latin.utils.CollectionUtils;
 import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils;
 import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils.OnAddWordListener;
 
@@ -61,12 +60,6 @@
 
     private final String mFileName;
 
-    private final ArrayList<PersonalizationDictionaryUpdateSession> mSessions =
-            CollectionUtils.newArrayList();
-
-    // Should always be false except when we use this class for test
-    @UsedForTesting boolean mIsTest = false;
-
     /* package */ DecayingExpandableBinaryDictionaryBase(final Context context,
             final Locale locale, final String dictionaryType, final String fileName) {
         super(context, fileName, locale, dictionaryType, true);
@@ -83,8 +76,7 @@
             dumpAllWordsForDebug();
         }
         // Flush pending writes.
-        // TODO: Remove after this class become to use a dynamic binary dictionary.
-        asyncFlashAllBinaryDictionary();
+        asyncFlushBinaryDictionary();
     }
 
     @Override
@@ -121,8 +113,9 @@
     }
 
     @Override
-    protected String getFileNameExtentionToOpenDict() {
-        return "/" + FormatSpec.TRIE_FILE_EXTENSION;
+    protected String getFileNameExtensionToOpenDict() {
+        // TODO: pass the directory name instead
+        return "/" + FormatSpec.HEADER_FILE_EXTENSION;
     }
 
     public void addMultipleDictionaryEntriesToDictionary(
@@ -164,25 +157,11 @@
         }
     }
 
-    public void cancelAddingUserHistory(final String word0, final String word1) {
-        removeBigramDynamically(word0, word1);
-    }
-
     @Override
     protected void loadDictionaryAsync() {
         // Never loaded to memory in Java side.
     }
 
-    public void registerUpdateSession(PersonalizationDictionaryUpdateSession session) {
-        session.setPredictionDictionary(this);
-        mSessions.add(session);
-        session.onDictionaryReady();
-    }
-
-    public void unRegisterUpdateSession(PersonalizationDictionaryUpdateSession session) {
-        mSessions.remove(session);
-    }
-
     @UsedForTesting
     public void dumpAllWordsForDebug() {
         runAfterGcForDebug(new Runnable() {
@@ -239,7 +218,7 @@
         // Clear the node structure on memory
         clear();
         // Then flush the cleared state of the dictionary on disk.
-        asyncFlashAllBinaryDictionary();
+        asyncFlushBinaryDictionary();
     }
 
     /* package */ void decayIfNeeded() {
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
index 8d3dcc3..413a951 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
@@ -20,44 +20,28 @@
 import com.android.inputmethod.latin.ExpandableBinaryDictionary;
 import com.android.inputmethod.latin.utils.CollectionUtils;
 
-import android.content.Context;
-
 import java.util.ArrayList;
 import java.util.Locale;
 
-/**
- * This class is a dictionary for the personalized language model that uses binary dictionary.
- */
-public class PersonalizationDictionary extends ExpandableBinaryDictionary {
-    private static final String NAME = "personalization";
+import android.content.Context;
+
+public class PersonalizationDictionary extends DecayingExpandableBinaryDictionaryBase {
+    private static final String NAME = PersonalizationDictionary.class.getSimpleName();
+
     private final ArrayList<PersonalizationDictionaryUpdateSession> mSessions =
             CollectionUtils.newArrayList();
 
-    public PersonalizationDictionary(final Context context, final Locale locale) {
-        // TODO: Make isUpdatable true.
-        super(context, getFilenameWithLocale(NAME, locale), locale,
-                Dictionary.TYPE_PERSONALIZATION, false /* isUpdatable */);
-        // TODO: Restore last updated time
-        loadDictionary();
+    /* package */ PersonalizationDictionary(final Context context, final Locale locale) {
+        super(context, locale, Dictionary.TYPE_PERSONALIZATION,
+                getDictionaryFileName(locale.toString()));
     }
 
-    @Override
-    protected void loadDictionaryAsync() {
-        // TODO: Implement
-    }
-
-    @Override
-    protected boolean hasContentChanged() {
-        return false;
-    }
-
-    @Override
-    protected boolean needsToReloadBeforeWriting() {
-        return false;
+    private static String getDictionaryFileName(final String locale) {
+        return NAME + "." + locale + ExpandableBinaryDictionary.DICT_FILE_EXTENSION;
     }
 
     public void registerUpdateSession(PersonalizationDictionaryUpdateSession session) {
-        session.setDictionary(this);
+        session.setPredictionDictionary(this);
         mSessions.add(session);
         session.onDictionaryReady();
     }
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionarySessionRegister.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionarySessionRegister.java
index c1833ff..542bda6 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionarySessionRegister.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionarySessionRegister.java
@@ -20,18 +20,18 @@
 import android.content.res.Configuration;
 
 public class PersonalizationDictionarySessionRegister {
-    public static void init(Context context) {
+    public static void init(final Context context) {
     }
 
     public static void onConfigurationChanged(final Context context, final Configuration conf) {
     }
 
-    public static void onUpdateData(Context context, String type) {
+    public static void onUpdateData(final Context context, final String type) {
     }
 
-    public static void onRemoveData(Context context, String type) {
+    public static void onRemoveData(final Context context, final String type) {
     }
 
-    public static void onDestroy(Context context) {
+    public static void onDestroy(final Context context) {
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java
index 3eb8bf4..6135476 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java
@@ -30,9 +30,7 @@
  * dictionary.
  */
 public abstract class PersonalizationDictionaryUpdateSession {
-    // TODO: Use a dynamic binary dictionary instead
     public WeakReference<PersonalizationDictionary> mDictionary;
-    public WeakReference<DecayingExpandableBinaryDictionaryBase> mPredictionDictionary;
     public final Locale mSystemLocale;
 
     public PersonalizationDictionaryUpdateSession(final Locale locale) {
@@ -41,25 +39,16 @@
 
     public abstract void onDictionaryReady();
 
-    public abstract void onDictionaryClosed(Context context);
+    public abstract void onDictionaryClosed(final Context context);
 
-    public void setDictionary(PersonalizationDictionary dictionary) {
+    public void setPredictionDictionary(final PersonalizationDictionary dictionary) {
         mDictionary = new WeakReference<PersonalizationDictionary>(dictionary);
     }
 
-    public void setPredictionDictionary(DecayingExpandableBinaryDictionaryBase dictionary) {
-        mPredictionDictionary =
-                new WeakReference<DecayingExpandableBinaryDictionaryBase>(dictionary);
-    }
-
     protected PersonalizationDictionary getDictionary() {
         return mDictionary == null ? null : mDictionary.get();
     }
 
-    protected DecayingExpandableBinaryDictionaryBase getPredictionDictionary() {
-        return mPredictionDictionary == null ? null : mPredictionDictionary.get();
-    }
-
     private void unsetDictionary() {
         final PersonalizationDictionary dictionary = getDictionary();
         if (dictionary == null) {
@@ -68,43 +57,24 @@
         dictionary.unRegisterUpdateSession(this);
     }
 
-    private void unsetPredictionDictionary() {
-        final DecayingExpandableBinaryDictionaryBase dictionary = getPredictionDictionary();
-        if (dictionary == null) {
-            return;
-        }
-        dictionary.unRegisterUpdateSession(this);
-    }
-
-    public void clearAndFlushPredictionDictionary(Context context) {
-        final DecayingExpandableBinaryDictionaryBase dictionary = getPredictionDictionary();
+    public void clearAndFlushDictionary(final Context context) {
+        final PersonalizationDictionary dictionary = getDictionary();
         if (dictionary == null) {
             return;
         }
         dictionary.clearAndFlushDictionary();
     }
 
-    public void closeSession(Context context) {
+    public void closeSession(final Context context) {
         unsetDictionary();
-        unsetPredictionDictionary();
         onDictionaryClosed(context);
     }
 
-    // TODO: Support multi locale to add bigram
-    public void addBigramToPersonalizationDictionary(String word0, String word1, boolean isValid,
-            int frequency, int timestamp) {
-        final DecayingExpandableBinaryDictionaryBase dictionary = getPredictionDictionary();
-        if (dictionary == null) {
-            return;
-        }
-        dictionary.addToDictionary(word0, word1, isValid, timestamp);
-    }
-
     // TODO: Support multi locale.
-    public void addMultipleDictionaryEntriesToPersonalizationDictionary(
+    public void addMultipleDictionaryEntriesToDictionary(
             final ArrayList<LanguageModelParam> languageModelParams,
             final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) {
-        final DecayingExpandableBinaryDictionaryBase dictionary = getPredictionDictionary();
+        final PersonalizationDictionary dictionary = getDictionary();
         if (dictionary == null) {
             if (callback != null) {
                 callback.onFinished();
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
index f73bb28..d55cae1 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
@@ -19,8 +19,6 @@
 import com.android.inputmethod.latin.utils.CollectionUtils;
 
 import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
 import android.util.Log;
 
 import java.lang.ref.SoftReference;
@@ -32,15 +30,9 @@
     private static final boolean DEBUG = false;
     private static final ConcurrentHashMap<String, SoftReference<UserHistoryDictionary>>
             sLangUserHistoryDictCache = CollectionUtils.newConcurrentHashMap();
-
     private static final ConcurrentHashMap<String, SoftReference<PersonalizationDictionary>>
             sLangPersonalizationDictCache = CollectionUtils.newConcurrentHashMap();
 
-    private static final ConcurrentHashMap<String,
-            SoftReference<PersonalizationPredictionDictionary>>
-                    sLangPersonalizationPredictionDictCache =
-                            CollectionUtils.newConcurrentHashMap();
-
     public static UserHistoryDictionary getUserHistoryDictionary(
             final Context context, final Locale locale) {
         final String localeStr = locale.toString();
@@ -77,12 +69,10 @@
     }
 
     public static void registerPersonalizationDictionaryUpdateSession(final Context context,
-            final PersonalizationDictionaryUpdateSession session, Locale locale) {
-        final PersonalizationPredictionDictionary predictionDictionary =
-                getPersonalizationPredictionDictionary(context, locale);
-        predictionDictionary.registerUpdateSession(session);
-        final PersonalizationDictionary dictionary = getPersonalizationDictionary(context, locale);
-        dictionary.registerUpdateSession(session);
+            final PersonalizationDictionaryUpdateSession session, final Locale locale) {
+        final PersonalizationDictionary personalizationDictionary =
+                getPersonalizationDictionary(context, locale);
+        personalizationDictionary.registerUpdateSession(session);
     }
 
     public static PersonalizationDictionary getPersonalizationDictionary(
@@ -95,7 +85,7 @@
                 final PersonalizationDictionary dict = ref == null ? null : ref.get();
                 if (dict != null) {
                     if (DEBUG) {
-                        Log.w(TAG, "Use cached PersonalizationDictCache for " + locale);
+                        Log.w(TAG, "Use cached PersonalizationDictionary for " + locale);
                     }
                     return dict;
                 }
@@ -106,27 +96,4 @@
             return dict;
         }
     }
-
-    public static PersonalizationPredictionDictionary getPersonalizationPredictionDictionary(
-            final Context context, final Locale locale) {
-        final String localeStr = locale.toString();
-        synchronized (sLangPersonalizationPredictionDictCache) {
-            if (sLangPersonalizationPredictionDictCache.containsKey(localeStr)) {
-                final SoftReference<PersonalizationPredictionDictionary> ref =
-                        sLangPersonalizationPredictionDictCache.get(localeStr);
-                final PersonalizationPredictionDictionary dict = ref == null ? null : ref.get();
-                if (dict != null) {
-                    if (DEBUG) {
-                        Log.w(TAG, "Use cached PersonalizationPredictionDictionary for " + locale);
-                    }
-                    return dict;
-                }
-            }
-            final PersonalizationPredictionDictionary dict =
-                    new PersonalizationPredictionDictionary(context, locale);
-            sLangPersonalizationPredictionDictCache.put(
-                    localeStr, new SoftReference<PersonalizationPredictionDictionary>(dict));
-            return dict;
-        }
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDictionary.java
deleted file mode 100644
index 6d94716..0000000
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDictionary.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.personalization;
-
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-
-import java.util.Locale;
-
-import android.content.Context;
-
-public class PersonalizationPredictionDictionary extends DecayingExpandableBinaryDictionaryBase {
-    private static final String NAME = PersonalizationPredictionDictionary.class.getSimpleName();
-
-    /* package */ PersonalizationPredictionDictionary(final Context context, final Locale locale) {
-        super(context, locale, Dictionary.TYPE_PERSONALIZATION_PREDICTION_IN_JAVA,
-                getDictionaryFileName(locale.toString()));
-    }
-
-    private static String getDictionaryFileName(final String locale) {
-        return NAME + "." + locale + ExpandableBinaryDictionary.DICT_FILE_EXTENSION;
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index 60370d8..975224f 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -38,4 +38,8 @@
     private static String getDictionaryFileName(final String locale) {
         return NAME + "." + locale + ExpandableBinaryDictionary.DICT_FILE_EXTENSION;
     }
+
+    public void cancelAddingUserHistory(final String word0, final String word1) {
+        removeBigramDynamically(word0, word1);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java b/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java
index c2e97a3..d12aad6 100644
--- a/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java
+++ b/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java
@@ -20,7 +20,7 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * This class is a holder of a result of asynchronous computation.
+ * This class is a holder of the result of an asynchronous computation.
  *
  * @param <E> the type of the result.
  */
@@ -36,9 +36,9 @@
     }
 
     /**
-     * Sets the result value to this holder.
+     * Sets the result value of this holder.
      *
-     * @param result the value which is set.
+     * @param result the value to set.
      */
     public void set(final E result) {
         synchronized(mLock) {
@@ -54,12 +54,12 @@
      * Causes the current thread to wait unless the value is set or the specified time is elapsed.
      *
      * @param defaultValue the default value.
-     * @param timeOut the time to wait.
-     * @return if the result is set until the time limit then the result, otherwise defaultValue.
+     * @param timeOut the maximum time to wait.
+     * @return if the result is set before the time limit then the result, otherwise defaultValue.
      */
     public E get(final E defaultValue, final long timeOut) {
         try {
-            if(mLatch.await(timeOut, TimeUnit.MILLISECONDS)) {
+            if (mLatch.await(timeOut, TimeUnit.MILLISECONDS)) {
                 return mResult;
             } else {
                 return defaultValue;
diff --git a/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java
index b4ff849..0c55484 100644
--- a/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java
@@ -165,12 +165,14 @@
      * Creates a locale from a string specification.
      */
     public static Locale constructLocaleFromString(final String localeStr) {
-        if (localeStr == null)
+        if (localeStr == null) {
             return null;
+        }
         synchronized (sLocaleCache) {
-            if (sLocaleCache.containsKey(localeStr))
-                return sLocaleCache.get(localeStr);
-            Locale retval = null;
+            Locale retval = sLocaleCache.get(localeStr);
+            if (retval != null) {
+                return retval;
+            }
             String[] localeParams = localeStr.split("_", 3);
             if (localeParams.length == 1) {
                 retval = new Locale(localeParams[0]);
diff --git a/native/jni/src/suggest/core/dictionary/digraph_utils.cpp b/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
index 3271c1b..5f9b8f3 100644
--- a/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
@@ -28,11 +28,8 @@
         { { 'a', 'e', 0x00E4 }, // U+00E4 : LATIN SMALL LETTER A WITH DIAERESIS
         { 'o', 'e', 0x00F6 },   // U+00F6 : LATIN SMALL LETTER O WITH DIAERESIS
         { 'u', 'e', 0x00FC } }; // U+00FC : LATIN SMALL LETTER U WITH DIAERESIS
-const DigraphUtils::digraph_t DigraphUtils::FRENCH_LIGATURES_DIGRAPHS[] =
-        { { 'a', 'e', 0x00E6 }, // U+00E6 : LATIN SMALL LETTER AE
-        { 'o', 'e', 0x0153 } }; // U+0153 : LATIN SMALL LIGATURE OE
 const DigraphUtils::DigraphType DigraphUtils::USED_DIGRAPH_TYPES[] =
-        { DIGRAPH_TYPE_GERMAN_UMLAUT, DIGRAPH_TYPE_FRENCH_LIGATURES };
+        { DIGRAPH_TYPE_GERMAN_UMLAUT };
 
 /* static */ bool DigraphUtils::hasDigraphForCodePoint(
         const DictionaryHeaderStructurePolicy *const headerPolicy,
@@ -50,9 +47,6 @@
     if (headerPolicy->requiresGermanUmlautProcessing()) {
         return DIGRAPH_TYPE_GERMAN_UMLAUT;
     }
-    if (headerPolicy->requiresFrenchLigatureProcessing()) {
-        return DIGRAPH_TYPE_FRENCH_LIGATURES;
-    }
     return DIGRAPH_TYPE_NONE;
 }
 
@@ -86,10 +80,6 @@
         *digraphs = GERMAN_UMLAUT_DIGRAPHS;
         return NELEMS(GERMAN_UMLAUT_DIGRAPHS);
     }
-    if (digraphType == DIGRAPH_TYPE_FRENCH_LIGATURES) {
-        *digraphs = FRENCH_LIGATURES_DIGRAPHS;
-        return NELEMS(FRENCH_LIGATURES_DIGRAPHS);
-    }
     return 0;
 }
 
diff --git a/native/jni/src/suggest/core/dictionary/digraph_utils.h b/native/jni/src/suggest/core/dictionary/digraph_utils.h
index 6ae16e3..bec2cd6 100644
--- a/native/jni/src/suggest/core/dictionary/digraph_utils.h
+++ b/native/jni/src/suggest/core/dictionary/digraph_utils.h
@@ -34,7 +34,6 @@
     typedef enum {
         DIGRAPH_TYPE_NONE,
         DIGRAPH_TYPE_GERMAN_UMLAUT,
-        DIGRAPH_TYPE_FRENCH_LIGATURES
     } DigraphType;
 
     typedef struct { int first; int second; int compositeGlyph; } digraph_t;
@@ -55,7 +54,6 @@
             const DigraphType digraphType, const int compositeGlyphCodePoint);
 
     static const digraph_t GERMAN_UMLAUT_DIGRAPHS[];
-    static const digraph_t FRENCH_LIGATURES_DIGRAPHS[];
     static const DigraphType USED_DIGRAPH_TYPES[];
 };
 } // namespace latinime
diff --git a/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h b/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h
index b05b7c3..b76b139 100644
--- a/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h
+++ b/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h
@@ -31,12 +31,8 @@
 
     virtual int getFormatVersionNumber() const = 0;
 
-    virtual bool supportsDynamicUpdate() const = 0;
-
     virtual bool requiresGermanUmlautProcessing() const = 0;
 
-    virtual bool requiresFrenchLigatureProcessing() const = 0;
-
     virtual float getMultiWordCostMultiplier() const = 0;
 
     virtual int getLastDecayedTime() const = 0;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
index 133ae9f..be7a3c2 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
@@ -20,6 +20,8 @@
 
 // Note that these are corresponding definitions in Java side in FormatSpec.FileHeader.
 const char *const HeaderPolicy::MULTIPLE_WORDS_DEMOTION_RATE_KEY = "MULTIPLE_WORDS_DEMOTION_RATE";
+const char *const HeaderPolicy::REQUIRES_GERMAN_UMLAUT_PROCESSING_KEY =
+        "REQUIRES_GERMAN_UMLAUT_PROCESSING";
 // TODO: Change attribute string to "IS_DECAYING_DICT".
 const char *const HeaderPolicy::IS_DECAYING_DICT_KEY = "USES_FORGETTING_CURVE";
 const char *const HeaderPolicy::LAST_UPDATED_TIME_KEY = "date";
@@ -66,6 +68,11 @@
     return MULTIPLE_WORD_COST_MULTIPLIER_SCALE / static_cast<float>(demotionRate);
 }
 
+bool HeaderPolicy::readRequiresGermanUmlautProcessing() const {
+    return HeaderReadWriteUtils::readBoolAttributeValue(&mAttributeMap,
+            REQUIRES_GERMAN_UMLAUT_PROCESSING_KEY, false);
+}
+
 bool HeaderPolicy::writeHeaderToBuffer(BufferWithExtendableBuffer *const bufferToWrite,
         const bool updatesLastUpdatedTime, const bool updatesLastDecayedTime,
         const int unigramCount, const int bigramCount, const int extendedRegionSize) const {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
index d71e0a0..5e8b5f1 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
@@ -36,6 +36,7 @@
               mSize(HeaderReadWriteUtils::getHeaderSize(dictBuf)),
               mAttributeMap(createAttributeMapAndReadAllAttributes(dictBuf)),
               mMultiWordCostMultiplier(readMultipleWordCostMultiplier()),
+              mRequiresGermanUmlautProcessing(readRequiresGermanUmlautProcessing()),
               mIsDecayingDict(HeaderReadWriteUtils::readBoolAttributeValue(&mAttributeMap,
                       IS_DECAYING_DICT_KEY, false /* defaultValue */)),
               mLastUpdatedTime(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
@@ -58,6 +59,7 @@
               mDictionaryFlags(HeaderReadWriteUtils::createAndGetDictionaryFlagsUsingAttributeMap(
                       attributeMap)), mSize(0), mAttributeMap(*attributeMap),
               mMultiWordCostMultiplier(readMultipleWordCostMultiplier()),
+              mRequiresGermanUmlautProcessing(readRequiresGermanUmlautProcessing()),
               mIsDecayingDict(HeaderReadWriteUtils::readBoolAttributeValue(&mAttributeMap,
                       IS_DECAYING_DICT_KEY, false /* defaultValue */)),
               mLastUpdatedTime(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
@@ -71,7 +73,8 @@
     // Temporary dummy header.
     HeaderPolicy()
             : mDictFormatVersion(FormatUtils::UNKNOWN_VERSION), mDictionaryFlags(0), mSize(0),
-              mAttributeMap(), mMultiWordCostMultiplier(0.0f), mIsDecayingDict(false),
+              mAttributeMap(), mMultiWordCostMultiplier(0.0f),
+              mRequiresGermanUmlautProcessing(false), mIsDecayingDict(false),
               mLastUpdatedTime(0), mLastDecayedTime(0), mUnigramCount(0), mBigramCount(0),
               mExtendedRegionSize(0), mHasHistoricalInfoOfWords(false) {}
 
@@ -109,18 +112,6 @@
         return mSize;
     }
 
-    AK_FORCE_INLINE bool supportsDynamicUpdate() const {
-        return HeaderReadWriteUtils::supportsDynamicUpdate(mDictionaryFlags);
-    }
-
-    AK_FORCE_INLINE bool requiresGermanUmlautProcessing() const {
-        return HeaderReadWriteUtils::requiresGermanUmlautProcessing(mDictionaryFlags);
-    }
-
-    AK_FORCE_INLINE bool requiresFrenchLigatureProcessing() const {
-        return HeaderReadWriteUtils::requiresFrenchLigatureProcessing(mDictionaryFlags);
-    }
-
     AK_FORCE_INLINE float getMultiWordCostMultiplier() const {
         return mMultiWordCostMultiplier;
     }
@@ -129,6 +120,10 @@
         return mIsDecayingDict;
     }
 
+    AK_FORCE_INLINE bool requiresGermanUmlautProcessing() const {
+        return mRequiresGermanUmlautProcessing;
+    }
+
     AK_FORCE_INLINE int getLastUpdatedTime() const {
         return mLastUpdatedTime;
     }
@@ -164,6 +159,7 @@
     DISALLOW_COPY_AND_ASSIGN(HeaderPolicy);
 
     static const char *const MULTIPLE_WORDS_DEMOTION_RATE_KEY;
+    static const char *const REQUIRES_GERMAN_UMLAUT_PROCESSING_KEY;
     static const char *const IS_DECAYING_DICT_KEY;
     static const char *const LAST_UPDATED_TIME_KEY;
     static const char *const LAST_DECAYED_TIME_KEY;
@@ -179,6 +175,7 @@
     const int mSize;
     HeaderReadWriteUtils::AttributeMap mAttributeMap;
     const float mMultiWordCostMultiplier;
+    const bool mRequiresGermanUmlautProcessing;
     const bool mIsDecayingDict;
     const int mLastUpdatedTime;
     const int mLastDecayedTime;
@@ -188,6 +185,7 @@
     const bool mHasHistoricalInfoOfWords;
 
     float readMultipleWordCostMultiplier() const;
+    bool readRequiresGermanUmlautProcessing() const;
 
     static HeaderReadWriteUtils::AttributeMap createAttributeMapAndReadAllAttributes(
             const uint8_t *const dictBuf);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp
index f5eee99..2d45470 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp
@@ -35,22 +35,6 @@
 const int HeaderReadWriteUtils::HEADER_SIZE_FIELD_SIZE = 4;
 
 const HeaderReadWriteUtils::DictionaryFlags HeaderReadWriteUtils::NO_FLAGS = 0;
-// Flags for special processing
-// Those *must* match the flags in makedict (FormatSpec#*_PROCESSING_FLAG) or
-// something very bad (like, the apocalypse) will happen. Please update both at the same time.
-const HeaderReadWriteUtils::DictionaryFlags
-        HeaderReadWriteUtils::GERMAN_UMLAUT_PROCESSING_FLAG = 0x1;
-const HeaderReadWriteUtils::DictionaryFlags
-        HeaderReadWriteUtils::SUPPORTS_DYNAMIC_UPDATE_FLAG = 0x2;
-const HeaderReadWriteUtils::DictionaryFlags
-        HeaderReadWriteUtils::FRENCH_LIGATURE_PROCESSING_FLAG = 0x4;
-
-// Note that these are corresponding definitions in Java side in FormatSpec.FileHeader.
-const char *const HeaderReadWriteUtils::SUPPORTS_DYNAMIC_UPDATE_KEY = "SUPPORTS_DYNAMIC_UPDATE";
-const char *const HeaderReadWriteUtils::REQUIRES_GERMAN_UMLAUT_PROCESSING_KEY =
-        "REQUIRES_GERMAN_UMLAUT_PROCESSING";
-const char *const HeaderReadWriteUtils::REQUIRES_FRENCH_LIGATURE_PROCESSING_KEY =
-        "REQUIRES_FRENCH_LIGATURE_PROCESSING";
 
 /* static */ int HeaderReadWriteUtils::getHeaderSize(const uint8_t *const dictBuf) {
     // See the format of the header in the comment in
@@ -68,17 +52,7 @@
 /* static */ HeaderReadWriteUtils::DictionaryFlags
         HeaderReadWriteUtils::createAndGetDictionaryFlagsUsingAttributeMap(
                 const HeaderReadWriteUtils::AttributeMap *const attributeMap) {
-    const bool requiresGermanUmlautProcessing = readBoolAttributeValue(attributeMap,
-            REQUIRES_GERMAN_UMLAUT_PROCESSING_KEY, false /* defaultValue */);
-    const bool requiresFrenchLigatureProcessing = readBoolAttributeValue(attributeMap,
-            REQUIRES_FRENCH_LIGATURE_PROCESSING_KEY, false /* defaultValue */);
-    const bool supportsDynamicUpdate = readBoolAttributeValue(attributeMap,
-            SUPPORTS_DYNAMIC_UPDATE_KEY, false /* defaultValue */);
-    DictionaryFlags dictflags = NO_FLAGS;
-    dictflags |= requiresGermanUmlautProcessing ? GERMAN_UMLAUT_PROCESSING_FLAG : 0;
-    dictflags |= requiresFrenchLigatureProcessing ? FRENCH_LIGATURE_PROCESSING_FLAG : 0;
-    dictflags |= supportsDynamicUpdate ? SUPPORTS_DYNAMIC_UPDATE_FLAG : 0;
-    return dictflags;
+    return NO_FLAGS;
 }
 
 /* static */ void HeaderReadWriteUtils::fetchAllHeaderAttributes(const uint8_t *const dictBuf,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.h b/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.h
index 2259683..fc24bbd 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.h
@@ -37,18 +37,6 @@
 
     static DictionaryFlags getFlags(const uint8_t *const dictBuf);
 
-    static AK_FORCE_INLINE bool supportsDynamicUpdate(const DictionaryFlags flags) {
-        return (flags & SUPPORTS_DYNAMIC_UPDATE_FLAG) != 0;
-    }
-
-    static AK_FORCE_INLINE bool requiresGermanUmlautProcessing(const DictionaryFlags flags) {
-        return (flags & GERMAN_UMLAUT_PROCESSING_FLAG) != 0;
-    }
-
-    static AK_FORCE_INLINE bool requiresFrenchLigatureProcessing(const DictionaryFlags flags) {
-        return (flags & FRENCH_LIGATURE_PROCESSING_FLAG) != 0;
-    }
-
     static AK_FORCE_INLINE int getHeaderOptionsPosition() {
         return HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE + HEADER_FLAG_SIZE
                 + HEADER_SIZE_FIELD_SIZE;
@@ -101,17 +89,8 @@
     static const int HEADER_FLAG_SIZE;
     static const int HEADER_SIZE_FIELD_SIZE;
 
+    // Value for the "flags" field. It's unused at the moment.
     static const DictionaryFlags NO_FLAGS;
-    // Flags for special processing
-    // Those *must* match the flags in makedict (FormatSpec#*_PROCESSING_FLAGS) or
-    // something very bad (like, the apocalypse) will happen. Please update both at the same time.
-    static const DictionaryFlags GERMAN_UMLAUT_PROCESSING_FLAG;
-    static const DictionaryFlags SUPPORTS_DYNAMIC_UPDATE_FLAG;
-    static const DictionaryFlags FRENCH_LIGATURE_PROCESSING_FLAG;
-
-    static const char *const SUPPORTS_DYNAMIC_UPDATE_KEY;
-    static const char *const REQUIRES_GERMAN_UMLAUT_PROCESSING_KEY;
-    static const char *const REQUIRES_FRENCH_LIGATURE_PROCESSING_KEY;
 
     static void setIntAttributeInner(AttributeMap *const headerAttributes,
             const AttributeMap::key_type *const key, const int value);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
index f1b733a..dfb110c 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
@@ -47,7 +47,7 @@
         case FormatUtils::VERSION_4: {
             const int dictDirPathBufSize = strlen(path) + 1 /* terminator */;
             char dictDirPath[dictDirPathBufSize];
-            if (!FileUtils::getFilePathWithoutSuffix(path, Ver4DictConstants::TRIE_FILE_EXTENSION,
+            if (!FileUtils::getFilePathWithoutSuffix(path, Ver4DictConstants::HEADER_FILE_EXTENSION,
                     dictDirPathBufSize, dictDirPath)) {
                 // Dictionary file name is not valid as a version 4 dictionary.
                 return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(0);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h
index bf83323..9512bdb 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h
@@ -60,9 +60,8 @@
     }
 
     bool flush(const char *const dictDirPath, const char *const contentFileName) const {
-        const BufferWithExtendableBuffer *bufferPtr = &mExpandableContentBuffer;
-        return DictFileWritingUtils::flushBuffersToFileInDir(dictDirPath, contentFileName,
-                &bufferPtr, 1 /* bufferCount */);
+        return DictFileWritingUtils::flushBufferToFileInDir(dictDirPath, contentFileName,
+                &mExpandableContentBuffer);
     }
 
  private:
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.cpp
index c654206..84aceef 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.cpp
@@ -21,19 +21,16 @@
 bool SparseTableDictContent::flush(const char *const dictDirPath,
         const char *const lookupTableFileName, const char *const addressTableFileName,
         const char *const contentFileName) const {
-    const BufferWithExtendableBuffer *lookupTableBufferPtr = &mExpandableLookupTableBuffer;
-    if (!DictFileWritingUtils::flushBuffersToFileInDir(dictDirPath, lookupTableFileName,
-            &lookupTableBufferPtr, 1 /* bufferCount */)) {
+    if (!DictFileWritingUtils::flushBufferToFileInDir(dictDirPath, lookupTableFileName,
+            &mExpandableLookupTableBuffer)){
         return false;
     }
-    const BufferWithExtendableBuffer *addressTableBufferPtr = &mExpandableAddressTableBuffer;
-    if (!DictFileWritingUtils::flushBuffersToFileInDir(dictDirPath, addressTableFileName,
-            &addressTableBufferPtr, 1 /* bufferCount */)) {
+    if (!DictFileWritingUtils::flushBufferToFileInDir(dictDirPath, addressTableFileName,
+            &mExpandableAddressTableBuffer)) {
         return false;
     }
-    const BufferWithExtendableBuffer *contentBufferPtr = &mExpandableContentBuffer;
-    if (!DictFileWritingUtils::flushBuffersToFileInDir(dictDirPath, contentFileName,
-            &contentBufferPtr, 1 /* bufferCount */)) {
+    if (!DictFileWritingUtils::flushBufferToFileInDir(dictDirPath, contentFileName,
+            &mExpandableContentBuffer)) {
         return false;
     }
     return true;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
index d0853a5..24f62cd 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
@@ -28,7 +28,7 @@
     const int terminalPos = getBuffer()->readUint(
             Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(terminalId));
     return (terminalPos == Ver4DictConstants::NOT_A_TERMINAL_ADDRESS) ?
-            NOT_A_DICT_POS : terminalPos - mHeaderRegionSize;
+            NOT_A_DICT_POS : terminalPos;
 }
 
 bool TerminalPositionLookupTable::setTerminalPtNodePosition(
@@ -45,18 +45,16 @@
         mSize++;
     }
     const int terminalPos = (terminalPtNodePos != NOT_A_DICT_POS) ?
-            terminalPtNodePos + mHeaderRegionSize : Ver4DictConstants::NOT_A_TERMINAL_ADDRESS;
+            terminalPtNodePos : Ver4DictConstants::NOT_A_TERMINAL_ADDRESS;
     return getWritableBuffer()->writeUint(terminalPos,
             Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(terminalId));
 }
 
-bool TerminalPositionLookupTable::flushToFile(const char *const dictDirPath,
-        const int newHeaderRegionSize) const {
-    const int headerRegionSizeDiff = newHeaderRegionSize - mHeaderRegionSize;
-    // If header region size has been changed or used buffer size is smaller than actual buffer
-    // size, regenerate lookup table and write the new table to file.
-    if (headerRegionSizeDiff != 0 || getEntryPos(mSize) < getBuffer()->getTailPosition()) {
-        TerminalPositionLookupTable lookupTableToWrite(newHeaderRegionSize);
+bool TerminalPositionLookupTable::flushToFile(const char *const dictDirPath) const {
+    // If the used buffer size is smaller than the actual buffer size, regenerate the lookup
+    // table and write the new table to the file.
+    if (getEntryPos(mSize) < getBuffer()->getTailPosition()) {
+        TerminalPositionLookupTable lookupTableToWrite;
         for (int i = 0; i < mSize; ++i) {
             const int terminalPtNodePosition = getTerminalPtNodePosition(i);
             if (!lookupTableToWrite.setTerminalPtNodePosition(i, terminalPtNodePosition)) {
@@ -68,7 +66,7 @@
         return lookupTableToWrite.flush(dictDirPath,
                 Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION);
     } else {
-        // We can simply use this lookup table because the header region size has not been
+        // We can simply use this lookup table because the buffer size has not been
         // changed.
         return flush(dictDirPath, Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION);
     }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h
index 80b358c..283b402 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h
@@ -28,19 +28,13 @@
  public:
     typedef hash_map_compat<int, int> TerminalIdMap;
 
-    // TODO: Quit using headerRegionSize.
-    TerminalPositionLookupTable(const char *const dictDirPath, const bool isUpdatable,
-            const int headerRegionSize)
+    TerminalPositionLookupTable(const char *const dictDirPath, const bool isUpdatable)
             : SingleDictContent(dictDirPath,
                       Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION, isUpdatable),
               mSize(getBuffer()->getTailPosition()
-                      / Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE),
-              mHeaderRegionSize(headerRegionSize) {}
+                      / Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE) {}
 
-    explicit TerminalPositionLookupTable(const int headerRegionSize)
-            : mSize(0), mHeaderRegionSize(headerRegionSize) {}
-
-    TerminalPositionLookupTable() : mSize(0), mHeaderRegionSize(0) {}
+    TerminalPositionLookupTable() : mSize(0) {}
 
     int getTerminalPtNodePosition(const int terminalId) const;
 
@@ -50,7 +44,7 @@
         return mSize;
     }
 
-    bool flushToFile(const char *const dictDirPath, const int newHeaderRegionSize) const;
+    bool flushToFile(const char *const dictDirPath) const;
 
     bool runGCTerminalIds(TerminalIdMap *const terminalIdMap);
 
@@ -62,7 +56,6 @@
     }
 
     int mSize;
-    const int mHeaderRegionSize;
 };
 } // namespace latinime
 #endif // LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
index 40c9b5e..10f8d32 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
@@ -45,16 +45,22 @@
         AKLOGE("Cannot create directory: %s. errno: %d.", tmpDirPath, errno);
         return false;
     }
+    // Write header file.
+    if (!DictFileWritingUtils::flushBufferToFileInDir(tmpDirPath,
+            Ver4DictConstants::HEADER_FILE_EXTENSION, headerBuffer)) {
+        AKLOGE("Dictionary header file %s/%s cannot be written.", tmpDirPath,
+                Ver4DictConstants::HEADER_FILE_EXTENSION);
+        return false;
+    }
     // Write trie file.
-    const BufferWithExtendableBuffer *buffers[] = {headerBuffer, &mExpandableTrieBuffer};
-    if (!DictFileWritingUtils::flushBuffersToFileInDir(tmpDirPath,
-            Ver4DictConstants::TRIE_FILE_EXTENSION, buffers, 2 /* bufferCount */)) {
+    if (!DictFileWritingUtils::flushBufferToFileInDir(tmpDirPath,
+            Ver4DictConstants::TRIE_FILE_EXTENSION, &mExpandableTrieBuffer)) {
         AKLOGE("Dictionary trie file %s/%s cannot be written.", tmpDirPath,
                 Ver4DictConstants::TRIE_FILE_EXTENSION);
         return false;
     }
     // Write dictionary contents.
-    if (!mTerminalPositionLookupTable.flushToFile(tmpDirPath, headerBuffer->getTailPosition())) {
+    if (!mTerminalPositionLookupTable.flushToFile(tmpDirPath)) {
         AKLOGE("Terminal position lookup table cannot be written. %s", tmpDirPath);
         return false;
     }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
index 153d899..8a13671 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
@@ -34,9 +34,10 @@
     typedef ExclusiveOwnershipPointer<Ver4DictBuffers> Ver4DictBuffersPtr;
 
     static AK_FORCE_INLINE Ver4DictBuffersPtr openVer4DictBuffers(const char *const dictDirPath,
-            const MmappedBuffer::MmappedBufferPtr &dictBuffer) {
-        const bool isUpdatable = dictBuffer.get() ? dictBuffer.get()->isUpdatable() : false;
-        return Ver4DictBuffersPtr(new Ver4DictBuffers(dictDirPath, dictBuffer, isUpdatable));
+            const MmappedBuffer::MmappedBufferPtr &headerBuffer) {
+        const bool isUpdatable = headerBuffer.get() ? headerBuffer.get()->isUpdatable() : false;
+        // TODO: take only dictDirPath, and open both header and trie files in the constructor below
+        return Ver4DictBuffersPtr(new Ver4DictBuffers(dictDirPath, headerBuffer, isUpdatable));
     }
 
     static AK_FORCE_INLINE Ver4DictBuffersPtr createVer4DictBuffers(
@@ -121,16 +122,17 @@
     DISALLOW_COPY_AND_ASSIGN(Ver4DictBuffers);
 
     AK_FORCE_INLINE Ver4DictBuffers(const char *const dictDirPath,
-            const MmappedBuffer::MmappedBufferPtr &dictBuffer, const bool isUpdatable)
-            : mDictBuffer(dictBuffer),
-              mHeaderPolicy(mDictBuffer.get()->getBuffer(), FormatUtils::VERSION_4),
-              mExpandableHeaderBuffer(dictBuffer.get()->getBuffer(), mHeaderPolicy.getSize(),
+            const MmappedBuffer::MmappedBufferPtr &headerBuffer, const bool isUpdatable)
+            : mHeaderBuffer(headerBuffer),
+              mDictBuffer(MmappedBuffer::openBuffer(dictDirPath,
+                      Ver4DictConstants::TRIE_FILE_EXTENSION, isUpdatable)),
+              mHeaderPolicy(headerBuffer.get()->getBuffer(), FormatUtils::VERSION_4),
+              mExpandableHeaderBuffer(headerBuffer.get()->getBuffer(), mHeaderPolicy.getSize(),
                       BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-              mExpandableTrieBuffer(dictBuffer.get()->getBuffer() + mHeaderPolicy.getSize(),
-                      dictBuffer.get()->getBufferSize() - mHeaderPolicy.getSize(),
+              mExpandableTrieBuffer(mDictBuffer.get()->getBuffer(),
+                      mDictBuffer.get()->getBufferSize(),
                       BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-              // TODO: Quit using header size.
-              mTerminalPositionLookupTable(dictDirPath, isUpdatable, mHeaderPolicy.getSize()),
+              mTerminalPositionLookupTable(dictDirPath, isUpdatable),
               mProbabilityDictContent(dictDirPath, mHeaderPolicy.hasHistoricalInfoOfWords(),
                       isUpdatable),
               mBigramDictContent(dictDirPath, mHeaderPolicy.hasHistoricalInfoOfWords(),
@@ -139,7 +141,7 @@
               mIsUpdatable(isUpdatable) {}
 
     AK_FORCE_INLINE Ver4DictBuffers(const HeaderPolicy *const headerPolicy)
-            : mDictBuffer(0), mHeaderPolicy(),
+            : mHeaderBuffer(0), mDictBuffer(0), mHeaderPolicy(),
               mExpandableHeaderBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
               mExpandableTrieBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
               mTerminalPositionLookupTable(),
@@ -147,6 +149,7 @@
               mBigramDictContent(headerPolicy->hasHistoricalInfoOfWords()), mShortcutDictContent(),
               mIsUpdatable(true) {}
 
+    const MmappedBuffer::MmappedBufferPtr mHeaderBuffer;
     const MmappedBuffer::MmappedBufferPtr mDictBuffer;
     const HeaderPolicy mHeaderPolicy;
     BufferWithExtendableBuffer mExpandableHeaderBuffer;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
index 066d6ed..34fecc2 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
@@ -18,7 +18,9 @@
 
 namespace latinime {
 
+// These values MUST match the definitions in FormatSpec.java.
 const char *const Ver4DictConstants::TRIE_FILE_EXTENSION = ".trie";
+const char *const Ver4DictConstants::HEADER_FILE_EXTENSION = ".header";
 const char *const Ver4DictConstants::FREQ_FILE_EXTENSION = ".freq";
 // tat = Terminal Address Table
 const char *const Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION = ".tat";
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
index 7afdc86..c16e0bd 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
@@ -25,6 +25,7 @@
 class Ver4DictConstants {
  public:
     static const char *const TRIE_FILE_EXTENSION;
+    static const char *const HEADER_FILE_EXTENSION;
     static const char *const FREQ_FILE_EXTENSION;
     static const char *const TERMINAL_ADDRESS_TABLE_FILE_EXTENSION;
     static const char *const BIGRAM_FILE_EXTENSION;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
index b463d41..9223356 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
@@ -68,42 +68,43 @@
     char tmpFileName[tmpFileNameBufSize];
     FileUtils::getFilePathWithSuffix(filePath, TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE,
             tmpFileNameBufSize, tmpFileName);
-    const BufferWithExtendableBuffer *buffers[] = {dictHeader, dictBody};
-    if (!DictFileWritingUtils::flushBuffersToFile(tmpFileName, buffers, 2 /* bufferCount */)) {
+    if (!DictFileWritingUtils::flushBufferToFile(tmpFileName, dictHeader)) {
+        AKLOGE("Dictionary header cannot be written to %s.", tmpFileName);
+        return false;
+    }
+    if (!DictFileWritingUtils::flushBufferToFile(tmpFileName, dictBody)) {
         AKLOGE("Dictionary structure cannot be written to %s.", tmpFileName);
         return false;
     }
     if (rename(tmpFileName, filePath) != 0) {
         AKLOGE("Dictionary file %s cannot be renamed to %s", tmpFileName, filePath);;
+        return false;
     }
     return true;
 }
 
-/* static */ bool DictFileWritingUtils::flushBuffersToFileInDir(const char *const dirPath,
-        const char *const fileName, const BufferWithExtendableBuffer **const buffers,
-        const int bufferCount) {
+/* static */ bool DictFileWritingUtils::flushBufferToFileInDir(const char *const dirPath,
+        const char *const fileName, const BufferWithExtendableBuffer *const buffer) {
     const int filePathBufSize = FileUtils::getFilePathBufSize(dirPath, fileName);
     char filePath[filePathBufSize];
     FileUtils::getFilePath(dirPath, fileName, filePathBufSize, filePath);
-    return flushBuffersToFile(filePath, buffers, bufferCount);
+    return flushBufferToFile(filePath, buffer);
 }
 
-/* static */ bool DictFileWritingUtils::flushBuffersToFile(const char *const filePath,
-        const BufferWithExtendableBuffer **const buffers, const int bufferCount) {
+/* static */ bool DictFileWritingUtils::flushBufferToFile(const char *const filePath,
+        const BufferWithExtendableBuffer *const buffer) {
     FILE *const file = fopen(filePath, "wb");
     if (!file) {
         AKLOGE("File %s cannot be opened.", filePath);
         ASSERT(false);
         return false;
     }
-    for (int i = 0; i < bufferCount; ++i) {
-        if (!writeBufferToFile(file, buffers[i])) {
-            remove(filePath);
-            AKLOGE("Buffer cannot be written to the file %s. size: %d", filePath,
-                    buffers[i]->getTailPosition());
-            ASSERT(false);
-            return false;
-        }
+    if (!writeBufferToFile(file, buffer)) {
+        remove(filePath);
+        AKLOGE("Buffer cannot be written to the file %s. size: %d", filePath,
+                buffer->getTailPosition());
+        ASSERT(false);
+        return false;
     }
     fclose(file);
     return true;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h
index 612d754..ffd9db6 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h
@@ -37,8 +37,8 @@
             BufferWithExtendableBuffer *const dictHeader,
             BufferWithExtendableBuffer *const dictBody);
 
-    static bool flushBuffersToFileInDir(const char *const dirPath, const char *const fileName,
-            const BufferWithExtendableBuffer **const buffers, const int bufferCount);
+    static bool flushBufferToFileInDir(const char *const dirPath, const char *const fileName,
+            const BufferWithExtendableBuffer *const buffer);
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(DictFileWritingUtils);
@@ -46,8 +46,8 @@
     static bool createEmptyV4DictFile(const char *const filePath,
             const HeaderReadWriteUtils::AttributeMap *const attributeMap);
 
-    static bool flushBuffersToFile(const char *const filePath,
-            const BufferWithExtendableBuffer **const buffers, const int bufferCount);
+    static bool flushBufferToFile(const char *const filePath,
+            const BufferWithExtendableBuffer *const buffer);
 
     static bool writeBufferToFile(FILE *const file,
             const BufferWithExtendableBuffer *const buffer);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
index 3d14d26..34727b8 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
@@ -29,9 +29,10 @@
 class FormatUtils {
  public:
     enum FORMAT_VERSION {
+        // These MUST have the same values as the relevant constants in FormatSpec.java.
         VERSION_2 = 2,
         VERSION_3 = 3,
-        VERSION_4 = 4,
+        VERSION_4 = 400,
         UNKNOWN_VERSION = -1
     };
 
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
index c63193a..d76a552 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
@@ -22,6 +22,7 @@
 
 import com.android.inputmethod.latin.makedict.CodePointUtils;
 import com.android.inputmethod.latin.makedict.FormatSpec;
+import com.android.inputmethod.latin.utils.FileUtils;
 
 import java.io.File;
 import java.io.IOException;
@@ -102,7 +103,7 @@
 
     private File createEmptyDictionaryAndGetFile(final String dictId,
             final int formatVersion) throws IOException {
-        if (formatVersion == 4) {
+        if (formatVersion == FormatSpec.VERSION4) {
             return createEmptyVer4DictionaryAndGetFile(dictId);
         } else {
             throw new IOException("Dictionary format version " + formatVersion
@@ -112,7 +113,7 @@
     private File createEmptyVer4DictionaryAndGetFile(final String dictId) throws IOException {
         final File file = File.createTempFile(dictId, TEST_DICT_FILE_EXTENSION,
                 getContext().getCacheDir());
-        file.delete();
+        FileUtils.deleteRecursively(file);
         file.mkdir();
         Map<String, String> attributeMap = new HashMap<String, String>();
         attributeMap.put(FormatSpec.FileHeader.SUPPORTS_DYNAMIC_UPDATE_ATTRIBUTE,
@@ -123,10 +124,10 @@
                 FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE);
         if (BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(),
                 FormatSpec.VERSION4, attributeMap)) {
-            return new File(file, FormatSpec.TRIE_FILE_EXTENSION);
+            return new File(file, FormatSpec.HEADER_FILE_EXTENSION);
         } else {
             throw new IOException("Empty dictionary " + file.getAbsolutePath() + " "
-                    + FormatSpec.TRIE_FILE_EXTENSION + " cannot be created.");
+                    + FormatSpec.HEADER_FILE_EXTENSION + " cannot be created.");
         }
     }
 
@@ -140,11 +141,11 @@
         binaryDictionary.getPropertyForTests(query);
     }
 
-    public void testControllCurrentTime() {
-        testControllCurrentTime(FormatSpec.VERSION4);
+    public void testControlCurrentTime() {
+        testControlCurrentTime(FormatSpec.VERSION4);
     }
 
-    private void testControllCurrentTime(final int formatVersion) {
+    private void testControlCurrentTime(final int formatVersion) {
         final int TEST_COUNT = 1000;
         final long seed = System.currentTimeMillis();
         final Random random = new Random(seed);
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index 7fa52e9..c148402 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -72,10 +72,10 @@
                 FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE);
         if (BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(),
                 FormatSpec.VERSION4, attributeMap)) {
-            return new File(file, FormatSpec.TRIE_FILE_EXTENSION);
+            return new File(file, FormatSpec.HEADER_FILE_EXTENSION);
         } else {
             throw new IOException("Empty dictionary " + file.getAbsolutePath() + " "
-                    + FormatSpec.TRIE_FILE_EXTENSION + " cannot be created.");
+                    + FormatSpec.HEADER_FILE_EXTENSION + " cannot be created.");
         }
     }
 
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
index 05de37d..e3ec2ec 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
@@ -523,7 +523,7 @@
             return null;
         }
         if (fileHeader == null) return null;
-        return BinaryDictDecoderUtils.getWordAtPosition(dictDecoder, fileHeader.mHeaderSize,
+        return BinaryDictDecoderUtils.getWordAtPosition(dictDecoder, fileHeader.mBodyOffset,
                 address, fileHeader.mFormatOptions).mWord;
     }
 
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
index da217ce..3089194 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
@@ -216,7 +216,7 @@
             final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file);
             final FileHeader fileHeader = dictDecoder.readHeader();
             assertEquals(word,
-                    BinaryDictDecoderUtils.getWordAtPosition(dictDecoder, fileHeader.mHeaderSize,
+                    BinaryDictDecoderUtils.getWordAtPosition(dictDecoder, fileHeader.mBodyOffset,
                             position, fileHeader.mFormatOptions).mWord);
         } catch (IOException e) {
             Log.e(TAG, "Raised an IOException while looking up a word", e);
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
index 8b1521a..ad17a71 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
@@ -29,17 +29,18 @@
 
     public static final String TEST_DICT_FILE_EXTENSION = ".testDict";
 
-    public static final FormatSpec.FormatOptions VERSION2 = new FormatSpec.FormatOptions(2);
+    public static final FormatSpec.FormatOptions VERSION2 =
+            new FormatSpec.FormatOptions(FormatSpec.VERSION2);
     public static final FormatSpec.FormatOptions VERSION3_WITHOUT_DYNAMIC_UPDATE =
-            new FormatSpec.FormatOptions(3, false /* supportsDynamicUpdate */);
+            new FormatSpec.FormatOptions(FormatSpec.VERSION3, false /* supportsDynamicUpdate */);
     public static final FormatSpec.FormatOptions VERSION3_WITH_DYNAMIC_UPDATE =
-            new FormatSpec.FormatOptions(3, true /* supportsDynamicUpdate */);
+            new FormatSpec.FormatOptions(FormatSpec.VERSION3, true /* supportsDynamicUpdate */);
     public static final FormatSpec.FormatOptions VERSION4_WITHOUT_DYNAMIC_UPDATE =
-            new FormatSpec.FormatOptions(4, false /* supportsDynamicUpdate */);
+            new FormatSpec.FormatOptions(FormatSpec.VERSION4, false /* supportsDynamicUpdate */);
     public static final FormatSpec.FormatOptions VERSION4_WITH_DYNAMIC_UPDATE =
-            new FormatSpec.FormatOptions(4, true /* supportsDynamicUpdate */);
+            new FormatSpec.FormatOptions(FormatSpec.VERSION4, true /* supportsDynamicUpdate */);
     public static final FormatSpec.FormatOptions VERSION4_WITH_DYNAMIC_UPDATE_AND_TIMESTAMP =
-            new FormatSpec.FormatOptions(4, true /* supportsDynamicUpdate */,
+            new FormatSpec.FormatOptions(FormatSpec.VERSION4, true /* supportsDynamicUpdate */,
                     true /* hasTimestamp */);
 
     public static DictionaryOptions makeDictionaryOptions(final String id, final String version) {
@@ -53,9 +54,10 @@
 
     public static File getDictFile(final String name, final String version,
             final FormatOptions formatOptions, final File directory) {
-        if (formatOptions.mVersion == 2 || formatOptions.mVersion == 3) {
+        if (formatOptions.mVersion == FormatSpec.VERSION2
+                || formatOptions.mVersion == FormatSpec.VERSION3) {
             return new File(directory, name + "." + version + TEST_DICT_FILE_EXTENSION);
-        } else if (formatOptions.mVersion == 4) {
+        } else if (formatOptions.mVersion == FormatSpec.VERSION4) {
             return new File(directory, name + "." + version);
         } else {
             throw new RuntimeException("the format option has a wrong version : "
@@ -67,7 +69,8 @@
             final File cacheDir) {
         if (formatOptions.mVersion == FormatSpec.VERSION4) {
             return new Ver4DictEncoder(cacheDir);
-        } else if (formatOptions.mVersion == 3 || formatOptions.mVersion == 2) {
+        } else if (formatOptions.mVersion == FormatSpec.VERSION3
+                || formatOptions.mVersion == FormatSpec.VERSION2) {
             return new Ver3DictEncoder(file);
         } else {
             throw new RuntimeException("The format option has a wrong version : "
@@ -79,7 +82,7 @@
             throws UnsupportedFormatException {
         if (formatOptions.mVersion == FormatSpec.VERSION4) {
             return new Ver4DictUpdater(file, DictDecoder.USE_WRITABLE_BYTEBUFFER);
-        } else if (formatOptions.mVersion == 3) {
+        } else if (formatOptions.mVersion == FormatSpec.VERSION3) {
             return new Ver3DictUpdater(file, DictDecoder.USE_WRITABLE_BYTEBUFFER);
         } else {
             throw new UnsupportedFormatException("The format option has a wrong version : "
diff --git a/tools/dicttool/Android.mk b/tools/dicttool/Android.mk
index 3d09c05..895e4a2 100644
--- a/tools/dicttool/Android.mk
+++ b/tools/dicttool/Android.mk
@@ -30,6 +30,7 @@
 USED_TARGETTED_UTILS := \
         $(LATINIME_CORE_SOURCE_DIRECTORY)/utils/ByteArrayDictBuffer.java \
         $(LATINIME_CORE_SOURCE_DIRECTORY)/utils/CollectionUtils.java \
+        $(LATINIME_CORE_SOURCE_DIRECTORY)/utils/FileUtils.java \
         $(LATINIME_CORE_SOURCE_DIRECTORY)/utils/JniUtils.java
 
 DICTTOOL_ONDEVICE_TESTS_DIRECTORY := \
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
index 5c7e8b4..b3543a0 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
@@ -159,9 +159,9 @@
                     if (OPTION_VERSION_2.equals(arg)) {
                         // Do nothing, this is the default
                     } else if (OPTION_VERSION_3.equals(arg)) {
-                        outputBinaryFormatVersion = 3;
+                        outputBinaryFormatVersion = FormatSpec.VERSION3;
                     } else if (OPTION_VERSION_4.equals(arg)) {
-                        outputBinaryFormatVersion = 4;
+                        outputBinaryFormatVersion = FormatSpec.VERSION4;
                     } else if (OPTION_HELP.equals(arg)) {
                         displayHelp();
                     } else {
@@ -358,7 +358,7 @@
         final File outputFile = new File(outputFilename);
         final FormatSpec.FormatOptions formatOptions = new FormatSpec.FormatOptions(version);
         final DictEncoder dictEncoder;
-        if (version == 4) {
+        if (version == FormatSpec.VERSION4) {
             dictEncoder = new Ver4DictEncoder(outputFile);
         } else {
             dictEncoder = new Ver3DictEncoder(outputFile);
diff --git a/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl b/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl
index 072daa4..a8ac981 100644
--- a/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl
+++ b/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl
@@ -113,6 +113,8 @@
     };
 
     /* @TEXTS@ */
+    // TODO: Use the language + "_" + region representation for the locale string key.
+    // Currently we are dropping the region from the key.
     private static final Object[] LANGUAGES_AND_TEXTS = {
         /* @LANGUAGES_AND_TEXTS@ */
     };
diff --git a/tools/make-keyboard-text/res/values-be/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-be-rBY/donottranslate-more-keys.xml
similarity index 100%
rename from tools/make-keyboard-text/res/values-be/donottranslate-more-keys.xml
rename to tools/make-keyboard-text/res/values-be-rBY/donottranslate-more-keys.xml
diff --git a/tools/make-keyboard-text/res/values-et/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-et-rEE/donottranslate-more-keys.xml
similarity index 100%
rename from tools/make-keyboard-text/res/values-et/donottranslate-more-keys.xml
rename to tools/make-keyboard-text/res/values-et-rEE/donottranslate-more-keys.xml
diff --git a/tools/make-keyboard-text/res/values-hy/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-hy-rAM/donottranslate-more-keys.xml
similarity index 100%
rename from tools/make-keyboard-text/res/values-hy/donottranslate-more-keys.xml
rename to tools/make-keyboard-text/res/values-hy-rAM/donottranslate-more-keys.xml
diff --git a/tools/make-keyboard-text/res/values-ka/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-ka-rGE/donottranslate-more-keys.xml
similarity index 100%
rename from tools/make-keyboard-text/res/values-ka/donottranslate-more-keys.xml
rename to tools/make-keyboard-text/res/values-ka-rGE/donottranslate-more-keys.xml
diff --git a/tools/make-keyboard-text/res/values-km/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-km-rKH/donottranslate-more-keys.xml
similarity index 100%
rename from tools/make-keyboard-text/res/values-km/donottranslate-more-keys.xml
rename to tools/make-keyboard-text/res/values-km-rKH/donottranslate-more-keys.xml
diff --git a/tools/make-keyboard-text/res/values-lo/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-lo-rLA/donottranslate-more-keys.xml
similarity index 100%
rename from tools/make-keyboard-text/res/values-lo/donottranslate-more-keys.xml
rename to tools/make-keyboard-text/res/values-lo-rLA/donottranslate-more-keys.xml
diff --git a/tools/make-keyboard-text/res/values-mn/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-mn-rMN/donottranslate-more-keys.xml
similarity index 100%
rename from tools/make-keyboard-text/res/values-mn/donottranslate-more-keys.xml
rename to tools/make-keyboard-text/res/values-mn-rMN/donottranslate-more-keys.xml
diff --git a/tools/make-keyboard-text/src/com/android/inputmethod/keyboard/tools/LocaleUtils.java b/tools/make-keyboard-text/src/com/android/inputmethod/keyboard/tools/LocaleUtils.java
new file mode 100644
index 0000000..9fdc1f6
--- /dev/null
+++ b/tools/make-keyboard-text/src/com/android/inputmethod/keyboard/tools/LocaleUtils.java
@@ -0,0 +1,61 @@
+/*
+ * 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.keyboard.tools;
+
+import java.util.HashMap;
+import java.util.Locale;
+
+/**
+ * A class to help with handling Locales in string form.
+ *
+ * This is a subset of com/android/inputmethod/latin/utils/LocaleUtils.java in order to use
+ * for the make-keyboard-text tool.
+ */
+public final class LocaleUtils {
+    private LocaleUtils() {
+        // Intentional empty constructor for utility class.
+    }
+
+    private static final HashMap<String, Locale> sLocaleCache = new HashMap<String, Locale>();
+
+    /**
+     * Creates a locale from a string specification.
+     */
+    public static Locale constructLocaleFromString(final String localeStr) {
+        if (localeStr == null) {
+            return null;
+        }
+        synchronized (sLocaleCache) {
+            Locale retval = sLocaleCache.get(localeStr);
+            if (retval != null) {
+                return retval;
+            }
+            String[] localeParams = localeStr.split("_", 3);
+            if (localeParams.length == 1) {
+                retval = new Locale(localeParams[0]);
+            } else if (localeParams.length == 2) {
+                retval = new Locale(localeParams[0], localeParams[1]);
+            } else if (localeParams.length == 3) {
+                retval = new Locale(localeParams[0], localeParams[1], localeParams[2]);
+            }
+            if (retval != null) {
+                sLocaleCache.put(localeStr, retval);
+            }
+            return retval;
+        }
+    }
+}
diff --git a/tools/make-keyboard-text/src/com/android/inputmethod/keyboard/tools/MoreKeysResources.java b/tools/make-keyboard-text/src/com/android/inputmethod/keyboard/tools/MoreKeysResources.java
index 2643e01..a883830 100644
--- a/tools/make-keyboard-text/src/com/android/inputmethod/keyboard/tools/MoreKeysResources.java
+++ b/tools/make-keyboard-text/src/com/android/inputmethod/keyboard/tools/MoreKeysResources.java
@@ -37,7 +37,7 @@
     private static final String MARK_DEFAULT_TEXTS = "@DEFAULT_TEXTS@";
     private static final String MARK_TEXTS = "@TEXTS@";
     private static final String MARK_LANGUAGES_AND_TEXTS = "@LANGUAGES_AND_TEXTS@";
-    private static final String DEFAUT_LANGUAGE_NAME = "DEFAULT";
+    private static final String DEFAULT_LANGUAGE_NAME = "DEFAULT";
     private static final String ARRAY_NAME_FOR_LANGUAGE = "LANGUAGE_%s";
     private static final String EMPTY_STRING_VAR = "EMPTY";
 
@@ -72,7 +72,7 @@
         final int languagePos = dirName.indexOf('-');
         if (languagePos < 0) {
             // Default resource.
-            return DEFAUT_LANGUAGE_NAME;
+            return DEFAULT_LANGUAGE_NAME;
         }
         final String language = dirName.substring(languagePos + 1);
         final int countryPos = language.indexOf("-r");
@@ -84,10 +84,12 @@
 
     public void writeToJava(final String outDir) {
         final ArrayList<String> list = JarUtils.getNameListing(mJar, JAVA_TEMPLATE);
-        if (list.isEmpty())
+        if (list.isEmpty()) {
             throw new RuntimeException("Can't find java template " + JAVA_TEMPLATE);
-        if (list.size() > 1)
+        }
+        if (list.size() > 1) {
             throw new RuntimeException("Found multiple java template " + JAVA_TEMPLATE);
+        }
         final String template = list.get(0);
         final String javaPackage = template.substring(0, template.lastIndexOf('/'));
         PrintStream ps = null;
@@ -131,7 +133,7 @@
     }
 
     private void dumpNames(final PrintStream out) {
-        final StringResourceMap defaultResMap = mResourcesMap.get(DEFAUT_LANGUAGE_NAME);
+        final StringResourceMap defaultResMap = mResourcesMap.get(DEFAULT_LANGUAGE_NAME);
         int id = 0;
         for (final StringResource res : defaultResMap.getResources()) {
             out.format("        /* %2d */ \"%s\",\n", id, res.mName);
@@ -141,17 +143,17 @@
     }
 
     private void dumpDefaultTexts(final PrintStream out) {
-        final StringResourceMap defaultResMap = mResourcesMap.get(DEFAUT_LANGUAGE_NAME);
+        final StringResourceMap defaultResMap = mResourcesMap.get(DEFAULT_LANGUAGE_NAME);
         dumpTextsInternal(out, defaultResMap, defaultResMap);
     }
 
     private void dumpTexts(final PrintStream out) {
-        final StringResourceMap defaultResMap = mResourcesMap.get(DEFAUT_LANGUAGE_NAME);
+        final StringResourceMap defaultResMap = mResourcesMap.get(DEFAULT_LANGUAGE_NAME);
         final ArrayList<String> allLanguages = new ArrayList<String>();
         allLanguages.addAll(mResourcesMap.keySet());
         Collections.sort(allLanguages);
         for (final String language : allLanguages) {
-            if (language.equals(DEFAUT_LANGUAGE_NAME)) {
+            if (language.equals(DEFAULT_LANGUAGE_NAME)) {
                 continue;
             }
             out.format("    /* Language %s: %s */\n", language, getLanguageDisplayName(language));
@@ -174,17 +176,22 @@
         allLanguages.addAll(mResourcesMap.keySet());
         Collections.sort(allLanguages);
         for (final String language : allLanguages) {
-            out.format("        \"%s\", " + ARRAY_NAME_FOR_LANGUAGE + ", /* %s */\n",
-                    language, language, getLanguageDisplayName(language));
+            final Locale locale = LocaleUtils.constructLocaleFromString(language);
+            // If we use a different key, dump the original as comment for now.
+            final String languageKeyToDump = locale.getCountry().isEmpty()
+                    ? String.format("\"%s\"", language)
+                    : String.format("\"%s\" /* \"%s\" */", locale.getLanguage(), language);
+            out.format("        %s, " + ARRAY_NAME_FOR_LANGUAGE + ", /* %s */\n",
+                    languageKeyToDump, language, getLanguageDisplayName(language));
         }
     }
 
     private static String getLanguageDisplayName(final String language) {
-        if (language.equals(NO_LANGUAGE_CODE)) {
+        final Locale locale = LocaleUtils.constructLocaleFromString(language);
+        if (locale.getLanguage().equals(NO_LANGUAGE_CODE)) {
             return NO_LANGUAGE_DISPLAY_NAME;
-        } else {
-            return new Locale(language).getDisplayLanguage();
         }
+        return locale.getDisplayName(Locale.ENGLISH);
     }
 
     private static void dumpTextsInternal(final PrintStream out, final StringResourceMap resMap,